diff --git a/.config/example.yml b/.config/example.yml index 427377a694..b84a50c525 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -1,67 +1,136 @@ -# インスタンス名 -name: +name: example-instance-name # Name of your instance +description: example-description # Description of your instance -# インスタンスの紹介 -description: - -# サーバーのメンテナ情報 maintainer: - # メンテナの名前 - name: + name: example-maitainer-name # Your name + url: http://example.com/ # Your contact (http or mailto) + repository_url: https://github.com/syuilo/misskey # Repository URL + feedback_url: https://github.com/syuilo/misskey/issues # Feedback URL (e.g. github issue) - # メンテナの連絡先(URLかmailto形式のURL) - url: +# URL and Port settings overview +# e.g., If you want to realize following structure: +# +# +--- https://example.com:123 ----------+ +# +------+ |+-------------+ +---------------+| +# | User | ---> || Proxy (123) | ---> | Misskey (456) || +# +------+ |+-------------+ +---------------+| +# +--------------------------------------+ +# +# You need to set 'https://example.com:123' to 'url' prop and +# You need to set 456 to 'port' prop. +# +# In other words, the 'url' prop should be the final accessible URL seen by a user. +# 'port' prop is a port that the Misskey server should actually listen +# on and it is not necessarily the port that a user accesses. -# (Misskeyを動かす)URL -url: +url: http://localhost/ -# 待受ポート -port: +# A port that your Misskey server should listen. +# This value is not a port to use when accessing with a browser. +port: 80 -# TLSの設定(利用しない場合は省略してください) -https: - # 証明書のパス... - key: - cert: - -# MongoDBの設定 mongodb: host: localhost port: 27017 db: misskey - user: - pass: + user: example-misskey-user + pass: example-misskey-pass -# Redisの設定 redis: host: localhost port: 6379 - pass: + pass: example-pass -# reCAPTCHAの設定 -recaptcha: - site_key: - secret_key: +# Drive capacity of a local user (MB) +localDriveCapacityMb: 256 -# ServiceWrokerの設定 -sw: - # VAPIDの公開鍵 - public_key: +# Drive capacity of a remote user (MB) +remoteDriveCapacityMb: 8 - # VAPIDの秘密鍵 - private_key: - -# Google Maps API -google_maps_api_key: - -# Twitterインテグレーションの設定(利用しない場合は省略可能) -twitter: - # インテグレーション用アプリのコンシューマーキー - consumer_key: - - # インテグレーション用アプリのコンシューマーシークレット - consumer_secret: - -# true にすると、リモートのファイルをキャッシュしなくなります(直リンクします)。 -# ストレージ容量を節約することができますが、「リモートメディアを表示しない」設定をオンにしているユーザーは、リモートの画像などは見えなくなります。 +# If enabled: +# Server will not cache remote files (Using direct link instead). +# You can save your storage. +# Users cannot see remote images when they turn off "Show media from a remote server" setting. preventCache: false + +drive: + storage: 'db' + + # OR + + # storage: 'minio' + # bucket: + # prefix: + # config: + # endPoint: + # port: + # secure: + # accessKey: + # secretKey: + + # S3 example + # storage: 'minio' + # bucket: bucket-name + # prefix: files + # config: + # endPoint: s3-us-west-2.amazonaws.com + # region: us-west-2 + # secure: true + # accessKey: XXX + # secretKey: YYY + + # S3 example (with CDN, custom domain) + # storage: 'minio' + # bucket: drive.example.com + # prefix: files + # baseUrl: https://drive.example.com + # config: + # endPoint: s3-us-west-2.amazonaws.com + # region: us-west-2 + # secure: true + # accessKey: XXX + # secretKey: YYY + +# +# Below settings are optional +# + +# TLS +# https: +# # path for certification +# key: example-tls-key +# cert: example-tls-cert + +# Elasticsearch +# elasticsearch: +# host: localhost +# port: 9200 +# pass: null + +# reCAPTCHA +# recaptcha: +# site_key: example-site-key +# secret_key: example-secret-key + +# ServiceWorker +# sw: +# # Public key of VAPID +# public_key: example-sw-public-key + +# # Private key of VAPID +# private_key: example-sw-private-key + +# google_maps_api_key: example-google-maps-api-key + +# Twitter integration +# twitter: +# consumer_key: example-twitter-consumer-key +# consumer_secret: example-twitter-consumer-secret-key + +# Ghost +# Ghost account is an account used for the purpose of delegating +# followers when putting users in the list. +# ghost: user-id-of-your-ghost-account + +# Clustering +# clusterLimit: 1 diff --git a/.gitattributes b/.gitattributes index 9ea77a4b0e..58a7812fdf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,3 +2,4 @@ *.psd -diff -text *.ai -diff -text yarn.lock -diff -text +package-lock.json -diff -text diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE deleted file mode 100644 index e75e7608e7..0000000000 --- a/.github/ISSUE_TEMPLATE +++ /dev/null @@ -1,7 +0,0 @@ -<!-- -Misskeyへの貢献ありがとうございます。 - -バグの報告や提案などで、可能であれば以下の情報を含めてください。 -* お使いのブラウザ -* デスクトップ版Misskeyかモバイル版Misskeyか ---> diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..e4e5282e56 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,22 @@ +--- +name: Bug Report +about: Create a report to help us improve +--- + +# Summary +<!-- Tell us what the bug is --> + +# Expected Behavior +<!--- Tell us what should happen --> + +# Actual Behavior +<!--- Tell us what happens instead of the expected behavior --> + +# Steps to Reproduce +1. +2. +3. + +# Environment +<!-- Tell us where on the platform it happens --> +<!-- e.g. desktop or mobile version, your browser, your OS --> diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..018e68df97 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,11 @@ +--- +name: Feature Request +about: Suggest an idea for this project +--- + +# Summary +<!-- Tell us what the suggestion is --> + +# Environment +<!-- Tell us where on the platform it related --> +<!-- e.g. desktop or mobile version, your browser, your OS --> diff --git a/.gitignore b/.gitignore index 197c1ec4d2..51e6a31b74 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,4 @@ npm-debug.log *.pem run.bat api-docs.json -package-lock.json *.log diff --git a/.npmrc b/.npmrc index 2fcf1d76c2..b680f3f72d 100644 --- a/.npmrc +++ b/.npmrc @@ -1,2 +1,2 @@ -package-lock = false save-exact=true +package-lock = false diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..36cfce106e --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,12 @@ +{ + "recommendations": [ + "ducksoupdev.vue2", + "editorconfig.editorconfig", + "eg2.tslint", + "eg2.vscode-npm-script", + "hollowtree.vue-snippets", + "ms-vscode.typescript-javascript-grammar", + "octref.vetur", + "sysoev.language-stylus" + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c0214ff9f..08ad99977f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ ChangeLog This document describes breaking changes only. +5.0.0 +----- + +### Migration + +起動する前に、`node cli/migration/5.0.0`してください。 + +Please run `node cli/migration/5.0.0` before launch. + 4.0.0 ----- diff --git a/README.md b/README.md index 197fd6952d..9e1c834b40 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![][dependencies-badge]][dependencies-link] [](http://makeapullrequest.com) [](https://greenkeeper.io/) -> Lead Maintainer: [syuilo][syuilo-link] +**Microblogging. Redefined.** **[Misskey](https://misskey.xyz)** is a completely open source, ultimately sophisticated professional microblogging software. @@ -18,14 +18,13 @@ ultimately sophisticated professional microblogging software. :sparkles: Features ---------------------------------------------------------------- +* Rich text contents * Reactions * User lists -* Customizable column view (known as MisskeyDeck) +* Customizable column view (called MisskeyDeck) * and widgets! * Private messages -* Mute -* Real-time timelines -* ActivityPub compatible +* ActivityPub support and more! You can see it with your own eyes at [misskey.xyz](https://misskey.xyz). @@ -44,15 +43,15 @@ If you want to... :heart: Backers & Sponsors ---------------------------------------------------------------- -| ![][nagarus-icon] | ![][dansup-icon] | -|:-:|:-:| -| [nagarus][nagarus-link] | [dansup][dansup-link] | +| <img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1?token-time=2145916800&token-hash=tB1e_r8RlZ5sFL0KV_e8dugapxatNBRK1Z3h67TO1g8%3D"> | <img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12378075/0156f769e20f412594fa6b87d85fe228/1?token-time=2145916800&token-hash=IsIJRUXszzoD6-7pDnRY8I05T9nSznc4GTaxj7C9SwU%3D"> | <img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1?token-time=2145916800&token-hash=S1zP0QyLU52Dqq6dtc9qNYyWfW86XrYHiR4NMbeOrnA%3D"> | <img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1?token-time=2145916800&token-hash=tMosUojzUYJCH_3t--tvYA-SMCyrS__hzSndyaRSnbo%3D"> | +|:-:|:-:|:-:|:-:| +| [Gargron](https://www.patreon.com/mastodon) | [39ff](https://www.patreon.com/user/creators?u=12378075) | [dansup](https://www.patreon.com/dansup) | [Takashi Shibuya](https://www.patreon.com/user/creators?u=12531784) | :four_leaf_clover: Copyright ---------------------------------------------------------------- > Copyright (c) 2014-2018 syuilo -Misskey is an open-source software licensed under [GNU AGPLv3](LICENSE). +Misskey is an open-source software licensed under the [GNU AGPLv3](LICENSE). [![][agpl-3.0-badge]][AGPL-3.0] @@ -73,9 +72,3 @@ Misskey is an open-source software licensed under [GNU AGPLv3](LICENSE). [syuilo-link]: https://syuilo.com [syuilo-icon]: https://avatars2.githubusercontent.com/u/4439005?v=3&s=70 - -[nagarus-link]: https://www.patreon.com/user/creators?u=11601413 -[nagarus-icon]: https://c10.patreonusercontent.com/3/eyJ2IjoiMSIsInciOjIwMH0%3D/patreon-media/user/11601413/20cb15f209924302b399b99d3c98b850?token-time=2145916800&token-hash=IO31nK6VZCMWBWU2VAk2c824BX2QZ4DNPKyHHZXS0iw%3D -[dansup-link]: https://www.patreon.com/dansup -[dansup-icon]: https://c10.patreonusercontent.com/3/eyJ2IjoiMSIsInciOjIwMH0%3D/patreon-media/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb?token-time=2145916800&token-hash=opXAM_pnhUTuN1jCA6p_Nn_YsaqohY465YFjWFqMEEE%3D - diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 280d6a99ae..0000000000 --- a/appveyor.yml +++ /dev/null @@ -1,41 +0,0 @@ -# appveyor file -# http://www.appveyor.com/docs/appveyor-yml - -environment: - matrix: - - nodejs_version: 10.1.0 - -cache: - - node_modules - -build: off - -install: - # Update Node.js - # 標準で入っている Node.js を更新します (2014/11/13 時点では、v0.10.32 が標準) - - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) - - node --version - - # Update NPM - - npm install -g npm - - npm --version - - # Update node-gyp - # 必須! node-gyp のバージョンを上げないと、ネイティブモジュールのコンパイルに失敗します - - npm install -g node-gyp - - - npm install - -init: - # git clone の際の改行を変換しないようにします - - git config --global core.autocrlf false - -before_test: - # 設定ファイルを配置 - - cp ./.travis/default.yml ./.config - - cp ./.travis/test.yml ./.config - - - npm run build - -test_script: - - npm test diff --git a/assets/apple-touch-icon.png b/assets/apple-touch-icon.png index b3c4be42af..fc91b6bab9 100644 Binary files a/assets/apple-touch-icon.png and b/assets/apple-touch-icon.png differ diff --git a/assets/favicon/favicon.png b/assets/favicon/favicon.png index 2efa2cad61..de535d7e2a 100644 Binary files a/assets/favicon/favicon.png and b/assets/favicon/favicon.png differ diff --git a/assets/icons/128.png b/assets/icons/128.png index 0bfa5aeb3e..c0f5db0cef 100644 Binary files a/assets/icons/128.png and b/assets/icons/128.png differ diff --git a/assets/icons/192.png b/assets/icons/192.png index 3fa9b0dab7..0f92a83e45 100644 Binary files a/assets/icons/192.png and b/assets/icons/192.png differ diff --git a/assets/icons/256.png b/assets/icons/256.png index b3c4be42af..fc91b6bab9 100644 Binary files a/assets/icons/256.png and b/assets/icons/256.png differ diff --git a/assets/icons/64.png b/assets/icons/64.png index ab35f8fec1..2b14ba3b5f 100644 Binary files a/assets/icons/64.png and b/assets/icons/64.png differ diff --git a/assets/title.png b/assets/title.png index cacbb248d3..7cb7dcdd6e 100644 Binary files a/assets/title.png and b/assets/title.png differ diff --git a/cli/clean-cached-remote-files.js b/cli/clean-cached-remote-files.js index a9c38a4cdf..5b388c73b4 100644 --- a/cli/clean-cached-remote-files.js +++ b/cli/clean-cached-remote-files.js @@ -9,7 +9,7 @@ const q = { 'metadata._user.host': { $ne: null }, - 'metadata.isMetaOnly': false + 'metadata.withoutChunks': false }; async function main() { @@ -57,7 +57,7 @@ async function main() { DriveFile.update({ _id: file._id }, { $set: { - 'metadata.isMetaOnly': true + 'metadata.withoutChunks': true } }) ]).then(async () => { diff --git a/cli/init.js b/cli/init.js deleted file mode 100644 index 5a36509574..0000000000 --- a/cli/init.js +++ /dev/null @@ -1,168 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const yaml = require('js-yaml'); -const inquirer = require('inquirer'); -const chalk = require('chalk'); - -const configDirPath = `${__dirname}/../.config`; -const configPath = `${configDirPath}/default.yml`; - -const form = [{ - type: 'input', - name: 'maintainerName', - message: 'Your name:' -}, { - type: 'input', - name: 'maintainerUrl', - message: 'Your home page URL or your mailto URL:' -}, { - type: 'input', - name: 'url', - message: 'URL you want to run Misskey:', - validate: function(wannabeurl) { - return wannabeurl.match('^http\(s?\)://') ? true : - 'URL needs to start with http:// or https://'; - } -}, { - type: 'input', - name: 'port', - message: 'Listen port (e.g. 443):' -}, { - type: 'confirm', - name: 'https', - message: 'Use TLS?', - default: false -}, { - type: 'input', - name: 'https_key', - message: 'Path of tls key:', - when: ctx => ctx.https -}, { - type: 'input', - name: 'https_cert', - message: 'Path of tls cert:', - when: ctx => ctx.https -}, { - type: 'input', - name: 'https_ca', - message: 'Path of tls ca:', - when: ctx => ctx.https -}, { - type: 'input', - name: 'mongo_host', - message: 'MongoDB\'s host:', - default: 'localhost' -}, { - type: 'input', - name: 'mongo_port', - message: 'MongoDB\'s port:', - default: '27017' -}, { - type: 'input', - name: 'mongo_db', - message: 'MongoDB\'s db:', - default: 'misskey' -}, { - type: 'input', - name: 'mongo_user', - message: 'MongoDB\'s user:' -}, { - type: 'password', - name: 'mongo_pass', - message: 'MongoDB\'s password:' -}, { - type: 'input', - name: 'redis_host', - message: 'Redis\'s host:', - default: 'localhost' -}, { - type: 'input', - name: 'redis_port', - message: 'Redis\'s port:', - default: '6379' -}, { - type: 'password', - name: 'redis_pass', - message: 'Redis\'s password:' -}, { - type: 'confirm', - name: 'elasticsearch', - message: 'Use Elasticsearch?', - default: false -}, { - type: 'input', - name: 'es_host', - message: 'Elasticsearch\'s host:', - default: 'localhost', - when: ctx => ctx.elasticsearch -}, { - type: 'input', - name: 'es_port', - message: 'Elasticsearch\'s port:', - default: '9200', - when: ctx => ctx.elasticsearch -}, { - type: 'password', - name: 'es_pass', - message: 'Elasticsearch\'s password:', - when: ctx => ctx.elasticsearch -}, { - type: 'input', - name: 'recaptcha_site', - message: 'reCAPTCHA\'s site key:' -}, { - type: 'input', - name: 'recaptcha_secret', - message: 'reCAPTCHA\'s secret key:' -}]; - -inquirer.prompt(form).then(as => { - // Mapping answers - const conf = { - maintainer: { - name: as['maintainerName'], - url: as['maintainerUrl'] - }, - url: as['url'], - port: parseInt(as['port'], 10), - mongodb: { - host: as['mongo_host'], - port: parseInt(as['mongo_port'], 10), - db: as['mongo_db'], - user: as['mongo_user'], - pass: as['mongo_pass'] - }, - redis: { - host: as['redis_host'], - port: parseInt(as['redis_port'], 10), - pass: as['redis_pass'] - }, - elasticsearch: { - enable: as['elasticsearch'], - host: as['es_host'] || null, - port: parseInt(as['es_port'], 10) || null, - pass: as['es_pass'] || null - }, - recaptcha: { - site_key: as['recaptcha_site'], - secret_key: as['recaptcha_secret'] - } - }; - - if (as['https']) { - conf.https = { - key: as['https_key'] || null, - cert: as['https_cert'] || null, - ca: as['https_ca'] || null - }; - } - - console.log(`Thanks. Writing the configuration to ${chalk.bold(path.resolve(configPath))}`); - - try { - fs.writeFileSync(configPath, yaml.dump(conf)); - console.log(chalk.green('Well done.')); - } catch (e) { - console.error(e); - } -}); diff --git a/cli/mark-admin.js b/cli/mark-admin.js new file mode 100644 index 0000000000..e10035fde9 --- /dev/null +++ b/cli/mark-admin.js @@ -0,0 +1,23 @@ +const mongo = require('mongodb'); +const User = require('../built/models/user').default; + +const args = process.argv.slice(2); + +const user = args[0]; + +const q = user.startsWith('@') ? { + username: user.split('@')[1], + host: user.split('@')[2] || null +} : { _id: new mongo.ObjectID(user) }; + +console.log(`Mark as admin ${user}...`); + +User.update(q, { + $set: { + isAdmin: true + } +}).then(() => { + console.log(`Done ${user}`); +}, e => { + console.error(e); +}); diff --git a/cli/mark-verified.js b/cli/mark-verified.js new file mode 100644 index 0000000000..cdee91ddca --- /dev/null +++ b/cli/mark-verified.js @@ -0,0 +1,23 @@ +const mongo = require('mongodb'); +const User = require('../built/models/user').default; + +const args = process.argv.slice(2); + +const user = args[0]; + +const q = user.startsWith('@') ? { + username: user.split('@')[1], + host: user.split('@')[2] || null +} : { _id: new mongo.ObjectID(user) }; + +console.log(`Mark as verfied ${user}...`); + +User.update(q, { + $set: { + isVerified: true + } +}).then(() => { + console.log(`Done ${user}`); +}, e => { + console.error(e); +}); diff --git a/migration/2.0.0.js b/cli/migration/2.0.0.js similarity index 88% rename from migration/2.0.0.js rename to cli/migration/2.0.0.js index eb8f5730c7..f7298972e5 100644 --- a/migration/2.0.0.js +++ b/cli/migration/2.0.0.js @@ -3,8 +3,8 @@ const chalk = require('chalk'); const sequential = require('promise-sequential'); -const { default: User } = require('../built/models/user'); -const { default: DriveFile } = require('../built/models/drive-file'); +const { default: User } = require('../../built/models/user'); +const { default: DriveFile } = require('../../built/models/drive-file'); async function main() { const promiseGens = []; diff --git a/migration/2.4.0.js b/cli/migration/2.4.0.js similarity index 91% rename from migration/2.4.0.js rename to cli/migration/2.4.0.js index e9584a1dfc..aa37849aa1 100644 --- a/migration/2.4.0.js +++ b/cli/migration/2.4.0.js @@ -3,8 +3,8 @@ const chalk = require('chalk'); const sequential = require('promise-sequential'); -const { default: User } = require('../built/models/user'); -const { default: DriveFile } = require('../built/models/drive-file'); +const { default: User } = require('../../built/models/user'); +const { default: DriveFile } = require('../../built/models/drive-file'); async function main() { const promiseGens = []; diff --git a/cli/migration/5.0.0.js b/cli/migration/5.0.0.js new file mode 100644 index 0000000000..bef103fe4a --- /dev/null +++ b/cli/migration/5.0.0.js @@ -0,0 +1,9 @@ +const { default: DriveFile } = require('../../built/models/drive-file'); + +DriveFile.update({}, { + $rename: { + 'metadata.isMetaOnly': 'metadata.withoutChunks' + } +}, { + multi: true +}); diff --git a/cli/reset-password.js b/cli/reset-password.js new file mode 100644 index 0000000000..d94c90f3d5 --- /dev/null +++ b/cli/reset-password.js @@ -0,0 +1,29 @@ +const mongo = require('mongodb'); +const bcrypt = require('bcryptjs'); +const User = require('../built/models/user').default; + +const args = process.argv.slice(2); + +const user = args[0]; + +const q = user.startsWith('@') ? { + username: user.split('@')[1], + host: user.split('@')[2] || null +} : { _id: new mongo.ObjectID(user) }; + +console.log(`Resetting password for ${user}...`); + +const passwd = 'yo'; + +// Generate hash of password +const hash = bcrypt.hashSync(passwd); + +User.update(q, { + $set: { + password: hash + } +}).then(() => { + console.log(`Password of ${user} is now '${passwd}'`); +}, e => { + console.error(e); +}); diff --git a/docker/Dockerfile b/docker/Dockerfile index 7cee650de3..f089c02545 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -14,7 +14,7 @@ RUN pacman -S --noconfirm pacman RUN pacman-db-upgrade RUN pacman -S --noconfirm archlinux-keyring RUN pacman -Syyu --noconfirm -RUN pacman -S --noconfirm git nodejs npm mongodb redis imagemagick +RUN pacman -S --noconfirm git nodejs npm mongodb redis COPY misskey.sh /root/misskey.sh RUN chmod u+x /root/misskey.sh diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..b4ba573439 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,6 @@ +# Docs +These docs are for contributors of Misskey or admins of instance of Misskey. +Docs for users are located in `src/docs`. + +これらのドキュメントはMisskeyの開発者またはMisskeyインスタンス運営者向けです。 +利用者向けのドキュメントは`src/docs`にあります。 diff --git a/docs/manage.en.md b/docs/manage.en.md new file mode 100644 index 0000000000..a7296ce479 --- /dev/null +++ b/docs/manage.en.md @@ -0,0 +1,46 @@ +# Management guide + +## Check the status of the job queue +coming soon + +## Mark as 'admin' user +``` shell +node cli/mark-admin (User-ID or Username) +``` + +## Mark as 'verified' user +``` shell +node cli/mark-verified (User-ID or Username) +``` + +## Suspend users +``` shell +node cli/suspend (User-ID or Username) +``` +e.g. +``` shell +# Use id +node cli/suspend 57d01a501fdf2d07be417afe + +# Use username +node cli/suspend @syuilo + +# Use username (remote) +node cli/suspend @syuilo@misskey.xyz +``` + +## Reset password +``` shell +node cli/reset-password (User-ID or Username) +``` + +## Clean up cached remote files +``` shell +node cli/clean-cached-remote-files +``` + +## Clean up unused drive files +``` shell +node cli/clean-unused-drive-files +``` +> We recommend that you announce a user that unused drive files will be deleted before performing this operation, as it may delete the user's important files. diff --git a/docs/manage.ja.md b/docs/manage.ja.md index d56ed4c19b..f289037ad3 100644 --- a/docs/manage.ja.md +++ b/docs/manage.ja.md @@ -1,13 +1,46 @@ # 運営ガイド ## ジョブキューの状態を調べる -Misskeyのディレクトリで: +coming soon + +## 管理者ユーザーを設定する ``` shell -node_modules/kue/bin/kue-dashboard -p 3050 +node cli/mark-admin (ユーザーID または ユーザー名) +``` + +## 'verified'ユーザーを設定する +``` shell +node cli/mark-verified (ユーザーID または ユーザー名) ``` -ポート3050にアクセスするとUIが表示されます ## ユーザーを凍結する ``` shell -node cli/suspend (ユーザーID) +node cli/suspend (ユーザーID または ユーザー名) ``` +例: +``` shell +# ユーザーID +node cli/suspend 57d01a501fdf2d07be417afe + +# ユーザー名 +node cli/suspend @syuilo + +# ユーザー名 (リモート) +node cli/suspend @syuilo@misskey.xyz +``` + +## ユーザーのパスワードをリセットする +``` shell +node cli/reset-password (ユーザーID または ユーザー名) +``` + +## キャッシュされたリモートファイルをクリーンアップする +``` shell +node cli/clean-cached-remote-files +``` + +## 使われていないドライブのファイルをクリーンアップする +``` shell +node cli/clean-unused-drive-files +``` +> ユーザーの大事なファイルを削除する可能性があるので、この操作を実行する前にユーザーに告知することをお勧めします。 diff --git a/docs/setup.en.md b/docs/setup.en.md index 28e025521b..56632cc361 100644 --- a/docs/setup.en.md +++ b/docs/setup.en.md @@ -8,18 +8,13 @@ This guide describes how to install and setup Misskey. ---------------------------------------------------------------- -*1.* reCAPTCHA tokens +*1.* Create Misskey user ---------------------------------------------------------------- -Misskey requires reCAPTCHA tokens. -Please visit https://www.google.com/recaptcha/intro/ and generate keys. +Running misskey on root is not a good idea so we create a user for that. +In debian for exemple : -*(optional)* Generating VAPID keys ----------------------------------------------------------------- -If you want to enable ServiceWroker, you need to generate VAPID keys: - -``` shell -npm install web-push -g -web-push generate-vapid-keys +``` +adduser --disabled-password --disabled-login misskey ``` *2.* Install dependencies @@ -27,25 +22,52 @@ web-push generate-vapid-keys Please install and setup these softwares: #### Dependencies :package: -* *Node.js* and *npm* -* **[MongoDB](https://www.mongodb.com/)** +* **[Node.js](https://nodejs.org/en/)** +* **[MongoDB](https://www.mongodb.com/)** >= 3.6 * **[Redis](https://redis.io/)** -* **[ImageMagick](http://www.imagemagick.org/script/index.php)** >= 7.0 ##### Optional * [Elasticsearch](https://www.elastic.co/) - used to provide searching feature instead of MongoDB -*3.* Install Misskey ----------------------------------------------------------------- -1. `git clone -b master git://github.com/syuilo/misskey.git` -2. `cd misskey` -3. `npm install` -*4.* Prepare configuration +*3.* Setup MongoDB ---------------------------------------------------------------- -You need to generate config file via `npm run config` command. +In root : +1. `mongo` Go to the mongo shell +2. `use misskey` Use the misskey database +3. `db.users.save( {dummy:"dummy"} )` Write dummy data to initialize the db. +4. `db.createUser( { user: "misskey", pwd: "<password>", roles: [ { role: "readWrite", db: "misskey" } ] } )` Create the misskey user. +5. `exit` You're done ! -*5.* Build Misskey +*4.* Install Misskey +---------------------------------------------------------------- +1. `su - misskey` Connect to misskey user. +2. `git clone -b master git://github.com/syuilo/misskey.git` Clone the misskey repo from master branch. +3. `cd misskey` Navigate to misskey directory +4. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest) +5. `npm install` Install misskey dependencies. + +*(optional)* reCAPTCHA tokens +---------------------------------------------------------------- +If you want to enable reCAPTCHA, you need to generate reCAPTCHA tokens: +Please visit https://www.google.com/recaptcha/intro/ and generate keys. + +*(optional)* Generating VAPID keys +---------------------------------------------------------------- +If you want to enable ServiceWroker, you need to generate VAPID keys: +Unless you have set your global node_modules location elsewhere, you need to run this in root. + +``` shell +npm install web-push -g +web-push generate-vapid-keys +``` + +*5.* Make configuration file +---------------------------------------------------------------- +1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`. +2. Edit `default.yml` + +*6.* Build Misskey ---------------------------------------------------------------- Build misskey with the following: @@ -61,14 +83,48 @@ If you're still encountering errors about some modules, use node-gyp: 3. `node-gyp build` 4. `npm run build` -*6.* That is it. +*7.* That is it. ---------------------------------------------------------------- Well done! Now, you have an environment that run to Misskey. -### Launch -Just `sudo npm start`. GLHF! +### Launch normally +Just `npm start`. GLHF! + +### Launch with systemd + +1. Create a systemd service here: `/etc/systemd/system/misskey.service` +2. Edit it, and paste this and save: + +``` +[Unit] +Description=Misskey daemon + +[Service] +Type=simple +User=misskey +ExecStart=/usr/bin/npm start +WorkingDirectory=/home/misskey/misskey +TimeoutSec=60 +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=misskey +Restart=always + +[Install] +WantedBy=multi-user.target +``` + +3. `systemctl daemon-reload ; systemctl enable misskey` Reload systemd and enable the misskey service. +4. `systemctl start misskey` Start the misskey service. + +You can check if the service is running with `systemctl status misskey`. ### Way to Update to latest version of your Misskey -1. `git reset --hard && git pull origin master` -2. `npm install` -3. `npm run build` +1. `git fetch` +2. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` +3. `npm install` +4. `npm run build` + +---------------------------------------------------------------- + +If you have any questions or troubles, feel free to contact us! diff --git a/docs/setup.ja.md b/docs/setup.ja.md index 0f1e46761b..7c701b019f 100644 --- a/docs/setup.ja.md +++ b/docs/setup.ja.md @@ -8,10 +8,48 @@ Misskeyサーバーの構築にご関心をお寄せいただきありがとう ---------------------------------------------------------------- -*1.* reCAPTCHAトークンの用意 +*1.* Misskeyユーザーの作成 ---------------------------------------------------------------- -MisskeyはreCAPTCHAトークンを必要とします。 -https://www.google.com/recaptcha/intro/ にアクセスしてトークンを生成してください。 +Misskeyのrootで実行しない方がよいため、代わりにユーザーを作成します。 +Debianの例: + +``` +adduser --disabled-password --disabled-login misskey +``` + +*2.* 依存関係をインストールする +---------------------------------------------------------------- +これらのソフトウェアをインストール・設定してください: + +#### 依存関係 :package: +* **[Node.js](https://nodejs.org/en/)** +* **[MongoDB](https://www.mongodb.com/)** (3.6以上) +* **[Redis](https://redis.io/)** + +##### オプション +* [Elasticsearch](https://www.elastic.co/) - 検索機能を向上させるために用います。 + +*3.* MongoDBの設定 +---------------------------------------------------------------- +ルートで: +1. `mongo` mongoシェルを起動 +2. `use misskey` misskeyデータベースを使用 +3. `db.users.save( {dummy:"dummy"} )` ダミーデータを書き込みDBを初期化 +4. `db.createUser( { user: "misskey", pwd: "<password>", roles: [ { role: "readWrite", db: "misskey" } ] } )` misskeyユーザーを作成 +5. `exit` mongoシェルを終了 + +*4.* Misskeyのインストール +---------------------------------------------------------------- +1. `su - misskey` misskeyユーザーを使用 +2. `git clone -b master git://github.com/syuilo/misskey.git` masterブランチからMisskeyレポジトリをクローン +3. `cd misskey` misskeyディレクトリに移動 +4. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認 +5. `npm install` Misskeyの依存パッケージをインストール + +*(オプション)* reCAPTCHAトークン +---------------------------------------------------------------- +reCAPTCHAを有効にする場合、reCAPTCHAトークンを取得する必要があります。 +https://www.google.com/recaptcha/intro/ にアクセスしてトークンを取得してください。 *(オプション)* VAPIDキーペアの生成 ---------------------------------------------------------------- @@ -22,56 +60,67 @@ npm install web-push -g web-push generate-vapid-keys ``` -*2.* 依存関係をインストールする +*5.* 設定ファイルを作成する ---------------------------------------------------------------- -これらのソフトウェアをインストール・設定してください: +1. `cp .config/example.yml .config/default.yml` `.config/example.yml`をコピーし名前を`default.yml`にする。 +2. `default.yml` を編集する。 -#### 依存関係 :package: -* *Node.js* と *npm* -* **[MongoDB](https://www.mongodb.com/)** -* **[Redis](https://redis.io/)** -* **[ImageMagick](http://www.imagemagick.org/script/index.php)** - -##### オプション -* [Elasticsearch](https://www.elastic.co/) - 検索機能を向上させるために用います。 - -*3.* Misskeyのインストール +*6.* Misskeyのビルド ---------------------------------------------------------------- -1. `git clone -b master git://github.com/syuilo/misskey.git` -2. `cd misskey` -3. `npm install` -*4.* 設定ファイルを用意する ----------------------------------------------------------------- -`npm run config`コマンドを利用して、ガイドに従って情報を入力してください。 +次のコマンドでMisskeyをビルドしてください: -*5.* Misskeyのビルド ----------------------------------------------------------------- +`npm run build` + +Debianをお使いであれば、`build-essential`パッケージをインストールする必要があります。 + +何らかのモジュールでエラーが発生する場合はnode-gypを使ってください: 1. `npm install -g node-gyp` 2. `node-gyp configure` 3. `node-gyp build` 4. `npm run build` -*6.* 以上です! +*7.* 以上です! ---------------------------------------------------------------- お疲れ様でした。これでMisskeyを動かす準備は整いました。 -### 起動 -`sudo npm start`するだけです。GLHF! +### 通常起動 +`npm start`するだけです。GLHF! + +### systemdを用いた起動 +1. systemdサービスのファイルを作成: `/etc/systemd/system/misskey.service` +2. エディタで開き、以下のコードを貼り付けて保存: + +``` +[Unit] +Description=Misskey daemon + +[Service] +Type=simple +User=misskey +ExecStart=/usr/bin/npm start +WorkingDirectory=/home/misskey/misskey +TimeoutSec=60 +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=misskey +Restart=always + +[Install] +WantedBy=multi-user.target +``` + +3. `systemctl daemon-reload ; systemctl enable misskey` systemdを再読み込みしmisskeyサービスを有効化 +4. `systemctl start misskey` misskeyサービスの起動 + +`systemctl status misskey`と入力すると、サービスの状態を調べることができます。 ### Misskeyを最新バージョンにアップデートする方法: -1. `git reset --hard && git pull origin master` -2. `npm install` -3. `npm run build` +1. `git fetch` +2. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` +3. `npm install` +4. `npm run build` -## メモリが足りなくてビルドできない場合 -Misskeyの(クライアントの)ビルドには、目安として8GBくらいのメモリを必要とします。 -VPSなどでビルドする時は、もしかしたらメモリが足りなくなる可能性があります。 -そうなった場合、もしVPSではなくあなたのPCが十分なメモリを搭載しているなら、あなたのPC上でビルドし、生成されたファイルをVPSにFTPでアップロードする方法を採ることができます。 +---------------------------------------------------------------- -1. あなたのPC上にMisskeyをインストールする -2. 設定ファイルを用意する。設定ファイルは、サーバーに合わせた設定にします。 -3. npm run webpack -4. built/client をサーバーにアップロードする -5. サーバー上で、npm run gulp -6. 完了 +なにかお困りのことがありましたらお気軽にご連絡ください。 diff --git a/docs/translate.en.md b/docs/translate.en.md index cedb0bafc3..8ac65d3564 100644 --- a/docs/translate.en.md +++ b/docs/translate.en.md @@ -4,19 +4,19 @@ Misskey's Translation If you find an untranslated part on Misskey: -------------------------------------------- -1. Look for untranslated parts in the miskey's source code. +1. Look for untranslated parts in the misskey's source code. - For instance, if you find an untranslated part in: `src/client/app/mobile/views/pages/home.vue`. 2. Replace the untranslated portion with a character string of the form `%i18n:@foo%`. - In fact, `foo` should be a word that is appropriate for the situation and is easy to understand in English. - For example, if the untranslated portion is the following "タイムライン" you must write: `%i18n:@timeline%`. -3. Open each language file in /locales, check whether the <strong>file name (path)</strong> found in step 1 exists, if not, create it. +3. Open the `locales/ja.yml`, check whether the <strong>file name (path)</strong> found in step 1 exists, if not, create it. - Do not put the beginning of the path `src/client/app/` in the locale file. - For example, in this case we want to modify untranslated parts of `src/client/app/mobile/views/pages/home.vue`, so the key is `mobile/views/pages/home.vue`. -4. Add the translated text property using the `foo` keyword below the path that you found or created in step 2. Make sure to type your text in quotation marks. Text should always be inside of quotes. - - For example, in this case we add timeline: `timeline: "Timeline"` to `locales/en.yml`, and `timeline: "タイムライン"` to `locales/ja.yml`. +4. Add the text property using the `foo` keyword below the path that you found or created in step 2. Make sure to type your text in quotation marks. Text should always be inside of quotes. + - For example, in this case we add timeline: `timeline: "タイムライン"` to `locales/ja.yml`. 5. And done! diff --git a/docs/translate.ja.md b/docs/translate.ja.md index 4804478d1b..8a2ef25005 100644 --- a/docs/translate.ja.md +++ b/docs/translate.ja.md @@ -11,12 +11,12 @@ Misskey内の未翻訳箇所を見つけたら - `foo`は実際にはその場に適したわかりやすい(英語の)名前にしてください。 - 例えば未翻訳箇所が「タイムライン」というテキストだった場合、`%i18n:@timeline%`のようにします。 -3. /locales 内にあるそれぞれの言語ファイルを開き、1.で見つけた<strong>ファイル名(パス)</strong>のキーが存在するか確認し、無ければ作成してください。 +3. `locales/ja.yml`を開き、1.で見つけた<strong>ファイル名(パス)</strong>のキーが存在するか確認し、無ければ作成してください。 - パスの`src/client/app/`は省略してください。 - 例えば、今回の例では`src/client/app/mobile/views/pages/home.vue`の未翻訳箇所を修正したいので、キーは`mobile/views/pages/home.vue`になります。 -4. そのキーの直下に2.で置換した`foo`の部分をキーとし、翻訳後のテキストを値とするプロパティを追加します。 - - 例えば、今回の例で言うと`locales/ja.yml`に`timeline: "タイムライン"`、`locales/en.yml`に`timeline: "Timeline"`を追加します。 +4. そのキーの直下に2.で置換した`foo`の部分をキーとし、テキストを値とするプロパティを追加します。 + - 例えば、今回の例で言うと`locales/ja.yml`に`timeline: "タイムライン"`を追加します。 5. 完了です! diff --git a/elasticsearch/README.md b/elasticsearch/README.md deleted file mode 100644 index c7fcb245f0..0000000000 --- a/elasticsearch/README.md +++ /dev/null @@ -1,6 +0,0 @@ -How to create indexes -===================== - -``` shell -curl -XPOST localhost:9200/misskey -d @path/to/mappings.json -``` diff --git a/elasticsearch/mappings.json b/elasticsearch/mappings.json deleted file mode 100644 index 654ab17450..0000000000 --- a/elasticsearch/mappings.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "settings": { - "analysis": { - "analyzer": { - "bigram": { - "tokenizer": "bigram_tokenizer" - } - }, - "tokenizer": { - "bigram_tokenizer": { - "type": "nGram", - "min_gram": 2, - "max_gram": 2, - "token_chars": [ - "letter", - "digit" - ] - } - } - } - }, - "mappings": { - "user": { - "properties": { - "username": { - "type": "string", - "index": "analyzed", - "analyzer": "bigram" - }, - "name": { - "type": "string", - "index": "analyzed", - "analyzer": "bigram" - }, - "bio": { - "type": "string", - "index": "analyzed", - "analyzer": "kuromoji" - } - } - }, - "post": { - "properties": { - "text": { - "type": "string", - "index": "analyzed", - "analyzer": "kuromoji" - } - } - }, - "drive_file": { - "properties": { - "name": { - "type": "string", - "index": "analyzed", - "analyzer": "kuromoji" - }, - "user": { - "type": "string", - "index": "not_analyzed" - } - } - } - } -} diff --git a/gulpfile.ts b/gulpfile.ts index 49a80879d2..9145750333 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -9,6 +9,7 @@ import * as ts from 'gulp-typescript'; const sourcemaps = require('gulp-sourcemaps'); import tslint from 'gulp-tslint'; const cssnano = require('gulp-cssnano'); +const stylus = require('gulp-stylus'); import * as uglifyComposer from 'gulp-uglify/composer'; import pug = require('gulp-pug'); import * as rimraf from 'rimraf'; @@ -20,9 +21,8 @@ import * as replace from 'gulp-replace'; import * as htmlmin from 'gulp-htmlmin'; const uglifyes = require('uglify-es'); -import locales from './locales'; -import { fa } from './src/build/fa'; -const client = require('./built/client/meta.json'); +const locales = require('./locales'); +import { fa } from './src/misc/fa'; import config from './src/config'; const uglify = uglifyComposer(uglifyes, console); @@ -38,8 +38,6 @@ if (isDebug) { const constants = require('./src/const.json'); -require('./src/client/docs/gulpfile.ts'); - gulp.task('build', [ 'build:ts', 'build:copy', @@ -47,8 +45,6 @@ gulp.task('build', [ 'doc' ]); -gulp.task('rebuild', ['clean', 'build']); - gulp.task('build:ts', () => { const tsProject = ts.createProject('./tsconfig.json'); @@ -85,19 +81,19 @@ gulp.task('lint', () => ); gulp.task('format', () => -gulp.src('./src/**/*.ts') - .pipe(tslint({ - formatter: 'verbose', - fix: true - })) - .pipe(tslint.report()) + gulp.src('./src/**/*.ts') + .pipe(tslint({ + formatter: 'verbose', + fix: true + })) + .pipe(tslint.report()) ); gulp.task('mocha', () => - gulp.src([]) + gulp.src('./test/**/*.ts') .pipe(mocha({ exit: true, - compilers: 'ts:ts-node/register' + require: 'ts-node/register' } as any)) ); @@ -118,8 +114,9 @@ gulp.task('build:client', [ 'copy:client' ]); -gulp.task('build:client:script', () => - gulp.src(['./src/client/app/boot.js', './src/client/app/safe.js']) +gulp.task('build:client:script', () => { + const client = require('./built/client/meta.json'); + return gulp.src(['./src/client/app/boot.js', './src/client/app/safe.js']) .pipe(replace('VERSION', JSON.stringify(client.version))) .pipe(replace('API', JSON.stringify(config.api_url))) .pipe(replace('ENV', JSON.stringify(env))) @@ -127,8 +124,8 @@ gulp.task('build:client:script', () => .pipe(isProduction ? uglify({ toplevel: true } as any) : gutil.noop()) - .pipe(gulp.dest('./built/client/assets/')) as any -); + .pipe(gulp.dest('./built/client/assets/')); +}); gulp.task('build:client:styles', () => gulp.src('./src/client/app/init.css') @@ -201,3 +198,10 @@ gulp.task('build:client:pug', [ })) .pipe(gulp.dest('./built/client/app/')) ); + +gulp.task('doc', () => + gulp.src('./src/docs/**/*.styl') + .pipe(stylus()) + .pipe((cssnano as any)()) + .pipe(gulp.dest('./built/docs/assets/')) +); diff --git a/locales/en.yml b/locales/en.yml index 09d35003d1..febc4f6912 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -889,6 +889,7 @@ mobile/views/pages/settings/settings.profile.vue: saved: "Profile updated" uploading: "Uploading" upload-failed: "Failed to upload" + mobile/views/pages/search.vue: search: "Search" empty: "No posts were found for '{}'" diff --git a/locales/fr.yml b/locales/fr.yml index 94d5baeeeb..4a96ee28ed 100644 --- a/locales/fr.yml +++ b/locales/fr.yml @@ -40,7 +40,7 @@ common: hmm: "Hmm ... ?" surprise: "Wow" congrats: "Félicitations !" - angry: "En colère" + angry: "Faché" confused: "Confus" pudding: "Pudding" note-placeholders: diff --git a/locales/index.js b/locales/index.js new file mode 100644 index 0000000000..5b525c77df --- /dev/null +++ b/locales/index.js @@ -0,0 +1,27 @@ +/** + * Languages Loader + */ + +const fs = require('fs'); +const yaml = require('js-yaml'); + +const loadLang = lang => yaml.safeLoad( + fs.readFileSync(`${__dirname}/${lang}.yml`, 'utf-8')); + +const native = loadLang('ja'); + +const langs = { + 'de': loadLang('de'), + 'en': loadLang('en'), + 'fr': loadLang('fr'), + 'ja': native, + 'pl': loadLang('pl'), + 'es': loadLang('es') +}; + +Object.values(langs).forEach(locale => { + // Extend native language (Japanese) + locale = Object.assign({}, native, locale); +}); + +module.exports = langs; diff --git a/locales/index.ts b/locales/index.ts deleted file mode 100644 index 45b5df0957..0000000000 --- a/locales/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Languages Loader - */ - -import * as fs from 'fs'; -import * as yaml from 'js-yaml'; - -export type LangKey = 'de' | 'en' | 'fr' | 'ja' | 'pl' | 'es'; -export type LocaleObject = { [key: string]: any }; - -const loadLang = (lang: LangKey) => yaml.safeLoad( - fs.readFileSync(`./locales/${lang}.yml`, 'utf-8')) as LocaleObject; - -const native = loadLang('ja'); - -const langs: { [key: string]: LocaleObject } = { - 'de': loadLang('de'), - 'en': loadLang('en'), - 'fr': loadLang('fr'), - 'ja': native, - 'pl': loadLang('pl'), - 'es': loadLang('es') -}; - -Object.entries(langs).map(([, locale]) => { - // Extend native language (Japanese) - locale = Object.assign({}, native, locale); -}); - -export function isAvailableLanguage(lang: string): lang is LangKey { - return lang in langs; -} - -export default langs; diff --git a/locales/ja.yml b/locales/ja.yml index fc790d8c53..9e65066d9d 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -6,6 +6,14 @@ common: misskey: "A ⭐ of fediverse" about-title: "A ⭐ of fediverse." about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。" + + customization-tips: + title: "カスタマイズのヒント" + paragraph1: "ホームのカスタマイズでは、ウィジェットを追加/削除したり、ドラッグ&ドロップして並べ替えたりすることができます。" + paragraph2: "一部のウィジェットは、<strong><strong>右</strong>クリック</strong>することで表示を変更することができます。" + paragraph3: "ウィジェットを削除するには、ヘッダーの<strong>「ゴミ箱」</strong>と書かれたエリアにウィジェットをドラッグ&ドロップします。" + paragraph4: "カスタマイズを終了するには、右上の「完了」をクリックします。" + gotit: "Got it!" time: unknown: "なぞのじかん" @@ -19,6 +27,8 @@ common: months_ago: "{}ヶ月前" years_ago: "{}年前" + trash: "ゴミ箱" + weekday-short: sunday: "日" monday: "月" @@ -56,6 +66,7 @@ common: my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" i-like-sushi: "私は(プリンよりむしろ)寿司が好き" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" + verified-user: "認証済みのユーザー" reversi: drawn: "引き分け" @@ -63,6 +74,7 @@ common: opponent-turn: "相手のターンです" turn-of: "{}のターンです" past-turn-of: "{}のターン" + won: "{}の勝ち" widgets: analog-clock: "アナログ時計" @@ -93,6 +105,7 @@ common: widgets: "ウィジェット" home: "ホーム" local: "ローカル" + hybrid: "ソーシャル" global: "グローバル" notifications: "通知" list: "リスト" @@ -279,6 +292,11 @@ common/views/widgets/memo.vue: title: "付箋" memo: "ここに書いて!" save: "保存" + +common/views/widgets/slideshow.vue: + folder-customize-mode: "フォルダを指定するには、カスタマイズモードを終了してください" + folder: "クリックしてフォルダを指定してください" + no-image: "このフォルダには画像がありません" common/views/pages/follow.vue: signed-in-as: "{}としてサインイン中" @@ -329,6 +347,8 @@ desktop/views/components/drive.file.vue: banner: "バナー" contextmenu: rename: "名前を変更" + mark-as-sensitive: "閲覧注意に設定" + unmark-as-sensitive: "閲覧注意を解除" copy-url: "URLをコピー" download: "ダウンロード" else-files: "その他..." @@ -376,6 +396,14 @@ desktop/views/components/drive.vue: upload: "ファイルをアップロード" url-upload: "URLからアップロード" +desktop/views/components/media-image.vue: + sensitive: "閲覧注意" + click-to-show: "クリックして表示" + +desktop/views/components/media-video.vue: + sensitive: "閲覧注意" + click-to-show: "クリックして表示" + desktop/views/components/follow-button.vue: following: "フォロー中" follow: "フォロー" @@ -440,12 +468,16 @@ desktop/views/components/notes.note.vue: desktop/views/components/notes.vue: error: "読み込みに失敗しました。" retry: "リトライ" + load-more: "もっと読み込む" desktop/views/components/notifications.vue: more: "もっと見る" empty: "ありません!" desktop/views/components/post-form.vue: + add-visible-user: "+ユーザーを追加" + attach-location-information: "位置情報を添付する" + hide-contents: "内容を隠す" reply-placeholder: "この投稿への返信..." quote-placeholder: "この投稿を引用..." submit: "投稿" @@ -464,7 +496,13 @@ desktop/views/components/post-form.vue: insert-a-kao: "v('ω')v" create-poll: "アンケートを作成" text-remain: "残り{}文字" - + recent-tags: "最近" + click-to-tagging: "クリックでタグ付け" + visibility: "公開範囲" + geolocation-alert: "お使いの端末は位置情報に対応していません" + error: "エラー" + enter-username: "ユーザー名を入力してください" + desktop/views/components/post-form-window.vue: note: "新規投稿" reply: "返信" @@ -512,6 +550,8 @@ desktop/views/components/settings.vue: display: "デザインと表示" customize: "ホームをカスタマイズ" + choose-wallpaper: "壁紙を選択" + delete-wallpaper: "壁紙を削除" dark-mode: "ダークモード" circle-icons: "円形のアイコンを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" @@ -621,8 +661,12 @@ desktop/views/components/settings.profile.vue: description: "自己紹介" birthday: "誕生日" save: "保存" + locked-account: "アカウントの保護" + is-locked: "投稿を非公開にする" + other: "その他" is-bot: "このアカウントはBotです" is-cat: "このアカウントはCatです" + profile-updated: "プロフィールを更新しました" desktop/views/components/sub-note-content.vue: private: "この投稿は非公開です" @@ -636,6 +680,7 @@ desktop/views/components/taskmanager.vue: desktop/views/components/timeline.vue: home: "ホーム" local: "ローカル" + hybrid: "ソーシャル" global: "グローバル" list: "リスト" @@ -648,7 +693,7 @@ desktop/views/components/ui.header.account.vue: favorites: "お気に入り" lists: "リスト" follow-requests: "フォロー申請" - customize: "カスタマイズ" + customize: "ホームのカスタマイズ" settings: "設定" signout: "サインアウト" dark: "闇に飲まれる" @@ -698,6 +743,7 @@ desktop/views/components/window.vue: desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "メディア投稿のみ" is-media-view: "メディアビュー" + edit: "オプション" desktop/views/pages/deck/deck.note.vue: reposted-by: "{}がRenote" @@ -844,6 +890,14 @@ mobile/views/components/drive.file-detail.vue: hash: "ハッシュ (md5)" exif: "EXIF" +mobile/views/components/media-image.vue: + sensitive: "閲覧注意" + click-to-show: "クリックして表示" + +mobile/views/components/media-video.vue: + sensitive: "閲覧注意" + click-to-show: "クリックして表示" + mobile/views/components/follow-button.vue: following: "フォロー中" follow: "フォロー" @@ -958,6 +1012,7 @@ mobile/views/pages/following.vue: mobile/views/pages/home.vue: home: "ホーム" local: "ローカル" + hybrid: "ソーシャル" global: "グローバル" mobile/views/pages/messaging.vue: @@ -1088,11 +1143,17 @@ docs: properties: "プロパティ" endpoints: params: "パラメータ" + no-params: "パラメータはありません" res: "レスポンス" + require-credential: "このエンドポイントは認証情報が必須です。" + require-permission: "このエンドポイントは{permission}の権限を必要とします。" + has-limit: "レートリミットがあります。" + duration-limit: "直近{duration}ミリ秒の間のこのエンドポイントへのリクエスト数の合計が{max}を超える場合はリクエストできません。" + min-interval-limit: "前回のリクエストから{interval}ミリ秒経っていない場合はリクエストできません。" + show-src: "このエンドポイントのソースコードも閲覧できます。" + show-src-link: "コードをGitHubで見る" + generated: "このドキュメントはAPI定義に基づき自動生成されています。" props: name: "名前" type: "型" - optional: "オプション" description: "説明" - yes: "はい" - no: "いいえ" diff --git a/migration/README.md b/migration/README.md deleted file mode 100644 index d52e84b35a..0000000000 --- a/migration/README.md +++ /dev/null @@ -1,11 +0,0 @@ -Misskeyの破壊的変更に対応するいくつかのスニペットがあります。 -MongoDBシェルで実行する必要のあるものとnodeで直接実行する必要のあるものがあります。 -ファイル名が `shell.` から始まるものは前者、 `node.` から始まるものは後者です。 - -MongoDBシェルで実行する場合、`use`でデータベースを選択しておく必要があります。 - -nodeで実行するいくつかのスニペットは、並列処理させる数を引数で設定できるものがあります。 -処理中にエラーで落ちる場合は、メモリが足りていない可能性があるので、少ない数に設定してみてください。 -※デフォルトは`5`です。 - -ファイルを作成する際は `../init-migration-file.sh -t _type_ -n _name_` を実行すると _type_._unixtime_._name_.js が生成されます diff --git a/migration/init-migration-file.sh b/migration/init-migration-file.sh deleted file mode 100644 index c6a2b862e6..0000000000 --- a/migration/init-migration-file.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -usage() { - echo "$0 [-t type] [-n name]" - echo " type: [node | shell]" - echo " name: if no present, set untitled" - exit 0 -} - -while getopts :t:n:h OPT -do - case $OPT in - t) type=$OPTARG - ;; - n) name=$OPTARG - ;; - h) usage - ;; - \?) usage - ;; - :) usage - ;; - esac -done - -if [ "$type" = "" ] -then - echo "no type present!!!" - usage -fi - -if [ "$name" = "" ] -then - name="untitled" -fi - -touch "$(realpath $(dirname $BASH_SOURCE))/migration/$type.$(date +%s).$name.js" diff --git a/package.json b/package.json index a9ae2ba591..4647e3d89a 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,18 @@ { "name": "misskey", "author": "syuilo <i@syuilo.com>", - "version": "4.15.0", - "clientVersion": "1.0.6878", + "version": "5.8.0", + "clientVersion": "1.0.7664", "codename": "nighthike", "main": "./built/index.js", "private": true, "scripts": { - "config": "node ./cli/init.js", "start": "node ./built", "debug": "DEBUG=misskey:* node ./built", - "swagger": "node ./swagger.js", "build": "webpack && gulp build", "webpack": "webpack", "watch": "webpack --watch", "gulp": "gulp build", - "rebuild": "gulp rebuild", "clean": "gulp clean", "cleanall": "gulp cleanall", "lint": "gulp lint", @@ -27,15 +24,15 @@ "@fortawesome/fontawesome-free-brands": "5.0.13", "@fortawesome/fontawesome-free-regular": "5.0.13", "@fortawesome/fontawesome-free-solid": "5.0.13", - "@koa/cors": "2.2.1", + "@koa/cors": "2.2.2", "@prezzemolo/rap": "0.1.2", "@prezzemolo/zip": "0.0.3", "@types/bcryptjs": "2.4.1", + "@types/dateformat": "1.0.1", "@types/debug": "0.0.30", "@types/deep-equal": "1.0.1", - "@types/elasticsearch": "5.0.24", + "@types/elasticsearch": "5.0.25", "@types/file-type": "5.2.1", - "@types/gm": "1.18.0", "@types/gulp": "3.8.36", "@types/gulp-htmlmin": "1.3.32", "@types/gulp-mocha": "0.0.32", @@ -43,31 +40,29 @@ "@types/gulp-replace": "0.0.31", "@types/gulp-uglify": "3.0.5", "@types/gulp-util": "3.0.34", - "@types/inquirer": "0.0.42", "@types/is-root": "1.0.0", "@types/is-url": "1.2.28", - "@types/js-yaml": "3.11.1", + "@types/js-yaml": "3.11.2", "@types/jsdom": "11.0.6", "@types/koa": "2.0.46", - "@types/koa-bodyparser": "5.0.0", + "@types/koa-bodyparser": "5.0.1", "@types/koa-compress": "2.0.8", "@types/koa-favicon": "2.0.19", "@types/koa-logger": "3.1.0", "@types/koa-mount": "3.0.1", "@types/koa-multer": "1.0.0", - "@types/koa-router": "7.0.30", + "@types/koa-router": "7.0.31", "@types/koa-send": "4.1.1", "@types/koa-views": "2.0.3", - "@types/koa__cors": "2.2.2", - "@types/kue": "0.11.9", - "@types/license-checker": "15.0.0", + "@types/koa__cors": "2.2.3", + "@types/minio": "6.0.2", "@types/mkdirp": "0.5.2", "@types/mocha": "5.2.3", - "@types/mongodb": "3.1.0", + "@types/mongodb": "3.1.2", "@types/ms": "0.7.30", - "@types/node": "10.5.1", - "@types/nopt": "3.0.29", + "@types/node": "10.5.4", "@types/parse5": "5.0.0", + "@types/portscanner": "2.1.0", "@types/pug": "2.0.4", "@types/qrcode": "1.2.0", "@types/ratelimiter": "2.1.28", @@ -76,11 +71,14 @@ "@types/request-promise-native": "1.0.15", "@types/rimraf": "2.0.2", "@types/seedrandom": "2.4.27", + "@types/sharp": "0.17.9", + "@types/showdown": "1.7.5", "@types/single-line-log": "1.1.0", "@types/speakeasy": "2.0.2", + "@types/systeminformation": "3.23.0", "@types/tmp": "0.0.33", "@types/uuid": "3.4.3", - "@types/webpack": "4.4.4", + "@types/webpack": "4.4.8", "@types/webpack-stream": "3.2.10", "@types/websocket": "0.0.39", "@types/ws": "5.1.2", @@ -88,51 +86,54 @@ "autosize": "4.0.2", "autwh": "0.1.0", "bcryptjs": "2.4.3", + "bee-queue": "1.2.2", "bootstrap-vue": "2.0.0-rc.11", - "cafy": "8.0.0", + "cafy": "11.3.0", "chalk": "2.4.1", + "commander": "2.16.0", "crc-32": "1.2.0", - "css-loader": "0.28.11", + "css-loader": "1.0.0", + "dateformat": "3.0.3", "debug": "3.1.0", "deep-equal": "1.0.1", "deepcopy": "0.6.3", "diskusage": "0.2.4", "dompurify": "1.0.5", - "elasticsearch": "15.0.0", - "element-ui": "2.4.2", - "emojilib": "2.2.12", + "elasticsearch": "15.1.1", + "element-ui": "2.4.5", + "emojilib": "2.3.0", "escape-regexp": "0.0.1", "eslint": "5.0.1", - "eslint-plugin-vue": "4.5.0", + "eslint-plugin-vue": "4.7.1", "eventemitter3": "3.1.0", "exif-js": "2.3.0", "file-loader": "1.1.11", - "file-type": "8.0.0", + "file-type": "8.1.0", "fuckadblock": "3.2.1", - "gm": "1.23.1", "gulp": "3.9.1", "gulp-cssnano": "2.1.3", "gulp-htmlmin": "4.0.0", "gulp-imagemin": "4.1.0", "gulp-mocha": "6.0.0", "gulp-pug": "4.0.1", - "gulp-rename": "1.3.0", + "gulp-rename": "1.4.0", "gulp-replace": "1.0.0", "gulp-sourcemaps": "2.6.4", "gulp-stylus": "2.7.0", "gulp-tslint": "8.1.3", "gulp-typescript": "4.0.2", - "gulp-uglify": "3.0.0", + "gulp-uglify": "3.0.1", "gulp-util": "3.0.8", - "hard-source-webpack-plugin": "0.10.1", + "hard-source-webpack-plugin": "0.12.0", "highlight.js": "9.12.0", - "html-minifier": "3.5.17", + "html-minifier": "3.5.19", "http-signature": "1.2.0", - "inquirer": "6.0.0", + "insert-text-at-cursor": "0.1.1", "is-root": "2.0.0", "is-url": "1.2.4", + "jquery": "3.3.1", "js-yaml": "3.12.0", - "jsdom": "11.11.0", + "jsdom": "11.12.0", "koa": "2.5.1", "koa-bodyparser": "4.2.1", "koa-compress": "3.0.0", @@ -145,32 +146,30 @@ "koa-send": "5.0.0", "koa-slow": "2.1.0", "koa-views": "6.1.4", - "kue": "0.11.6", - "license-checker": "20.1.0", "loader-utils": "1.1.0", "mecab-async": "0.1.2", + "minio": "6.0.0", "mkdirp": "0.5.1", "mocha": "5.2.0", "moji": "0.5.1", - "mongodb": "3.1.0", + "mongodb": "3.1.1", "monk": "6.0.6", "ms": "2.1.1", "nan": "2.10.0", - "node-sass": "4.9.0", + "node-sass": "4.9.2", "node-sass-json-importer": "3.3.1", - "nopt": "4.0.1", "nprogress": "0.2.0", "object-assign-deep": "0.4.0", "on-build-webpack": "0.1.0", "os-utils": "0.0.14", "parse5": "5.0.0", + "portscanner": "2.2.0", "progress-bar-webpack-plugin": "1.11.0", - "prominence": "0.2.0", "promise-sequential": "1.1.1", "pug": "2.0.3", "punycode": "2.1.1", - "qrcode": "1.2.0", - "ratelimiter": "3.1.0", + "qrcode": "1.2.2", + "ratelimiter": "3.2.0", "recaptcha-promise": "0.1.3", "reconnecting-websocket": "3.2.2", "redis": "2.8.0", @@ -181,22 +180,24 @@ "s-age": "1.1.2", "sass-loader": "7.0.3", "seedrandom": "2.4.3", + "sharp": "0.20.5", + "showdown": "1.8.6", + "showdown-highlightjs-extension": "0.1.2", "single-line-log": "1.1.2", "speakeasy": "2.0.0", "style-loader": "0.21.0", "stylus": "0.54.5", "stylus-loader": "3.0.2", "summaly": "2.0.6", - "swagger-jsdoc": "1.9.7", + "systeminformation": "3.42.4", "syuilo-password-strength": "0.0.1", - "tcp-port-used": "0.1.2", "textarea-caret": "3.1.0", "tmp": "0.0.33", "ts-loader": "4.4.1", "ts-node": "7.0.0", "tslint": "5.10.0", "typescript": "2.9.2", - "typescript-eslint-parser": "16.0.1", + "typescript-eslint-parser": "17.0.1", "uglify-es": "3.3.9", "url-loader": "1.0.1", "uuid": "3.3.2", @@ -205,18 +206,19 @@ "vue-cropperjs": "2.2.1", "vue-js-modal": "1.3.16", "vue-json-tree-view": "2.1.4", - "vue-loader": "15.2.4", + "vue-loader": "15.2.6", "vue-router": "3.0.1", + "vue-style-loader": "4.1.1", "vue-template-compiler": "2.5.16", "vuedraggable": "2.16.0", "vuex": "3.0.1", - "vuex-persistedstate": "^2.5.4", + "vuex-persistedstate": "2.5.4", "web-push": "3.3.2", "webfinger.js": "2.6.6", - "webpack": "4.14.0", - "webpack-cli": "3.0.8", + "webpack": "4.16.3", + "webpack-cli": "3.1.0", "websocket": "1.0.26", - "ws": "5.2.1", + "ws": "6.0.0", "xev": "2.0.1" }, "greenkeeper": { diff --git a/src/acct/render.ts b/src/acct/render.ts deleted file mode 100644 index c29bfb4764..0000000000 --- a/src/acct/render.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IUser } from '../models/user'; - -export default (user: IUser) => { - return user.host === null ? user.username : `${user.username}@${user.host}`; -}; diff --git a/src/client/app/auth/views/form.vue b/src/client/app/auth/views/form.vue index 152b900429..80086e3861 100644 --- a/src/client/app/auth/views/form.vue +++ b/src/client/app/auth/views/form.vue @@ -2,7 +2,7 @@ <div class="form"> <header> <h1><i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?</h1> - <img :src="`${app.iconUrl}?thumbnail&size=64`"/> + <img :src="app.iconUrl"/> </header> <div class="app"> <section> diff --git a/src/client/app/common/scripts/compose-notification.ts b/src/client/app/common/scripts/compose-notification.ts index 2e58649ac2..c93609bc59 100644 --- a/src/client/app/common/scripts/compose-notification.ts +++ b/src/client/app/common/scripts/compose-notification.ts @@ -1,6 +1,6 @@ -import getNoteSummary from '../../../../renderers/get-note-summary'; -import getReactionEmoji from '../../../../renderers/get-reaction-emoji'; -import getUserName from '../../../../renderers/get-user-name'; +import getNoteSummary from '../../../../misc/get-note-summary'; +import getReactionEmoji from '../../../../misc/get-reaction-emoji'; +import getUserName from '../../../../misc/get-user-name'; type Notification = { title: string; @@ -17,21 +17,21 @@ export default function(type, data): Notification { return { title: 'ファイルがアップロードされました', body: data.name, - icon: data.url + '?thumbnail&size=64' + icon: data.url }; case 'unread_messaging_message': return { title: `${getUserName(data.user)}さんからメッセージ:`, body: data.text, // TODO: getMessagingMessageSummary(data), - icon: data.user.avatarUrl + '?thumbnail&size=64' + icon: data.user.avatarUrl }; case 'reversi_invited': return { title: '対局への招待があります', body: `${getUserName(data.parent)}さんから`, - icon: data.parent.avatarUrl + '?thumbnail&size=64' + icon: data.parent.avatarUrl }; case 'notification': @@ -40,28 +40,28 @@ export default function(type, data): Notification { return { title: `${getUserName(data.user)}さんから:`, body: getNoteSummary(data), - icon: data.user.avatarUrl + '?thumbnail&size=64' + icon: data.user.avatarUrl }; case 'reply': return { title: `${getUserName(data.user)}さんから返信:`, body: getNoteSummary(data), - icon: data.user.avatarUrl + '?thumbnail&size=64' + icon: data.user.avatarUrl }; case 'quote': return { title: `${getUserName(data.user)}さんが引用:`, body: getNoteSummary(data), - icon: data.user.avatarUrl + '?thumbnail&size=64' + icon: data.user.avatarUrl }; case 'reaction': return { title: `${getUserName(data.user)}: ${getReactionEmoji(data.reaction)}:`, body: getNoteSummary(data.note), - icon: data.user.avatarUrl + '?thumbnail&size=64' + icon: data.user.avatarUrl }; default: diff --git a/src/client/app/common/scripts/streaming/reversi-game.ts b/src/client/app/common/scripts/streaming/games/reversi/reversi-game.ts similarity index 55% rename from src/client/app/common/scripts/streaming/reversi-game.ts rename to src/client/app/common/scripts/streaming/games/reversi/reversi-game.ts index 5638b3013f..e6b02fcfdb 100644 --- a/src/client/app/common/scripts/streaming/reversi-game.ts +++ b/src/client/app/common/scripts/streaming/games/reversi/reversi-game.ts @@ -1,9 +1,9 @@ -import Stream from './stream'; -import MiOS from '../../../mios'; +import Stream from '../../stream'; +import MiOS from '../../../../../mios'; export class ReversiGameStream extends Stream { constructor(os: MiOS, me, game) { - super(os, 'reversi-game', { + super(os, 'games/reversi-game', { i: me ? me.token : null, game: game.id }); diff --git a/src/client/app/common/scripts/streaming/reversi.ts b/src/client/app/common/scripts/streaming/games/reversi/reversi.ts similarity index 73% rename from src/client/app/common/scripts/streaming/reversi.ts rename to src/client/app/common/scripts/streaming/games/reversi/reversi.ts index 2e4395f0f1..1f4fd8c63e 100644 --- a/src/client/app/common/scripts/streaming/reversi.ts +++ b/src/client/app/common/scripts/streaming/games/reversi/reversi.ts @@ -1,10 +1,10 @@ -import StreamManager from './stream-manager'; -import Stream from './stream'; -import MiOS from '../../../mios'; +import StreamManager from '../../stream-manager'; +import Stream from '../../stream'; +import MiOS from '../../../../../mios'; export class ReversiStream extends Stream { constructor(os: MiOS, me) { - super(os, 'reversi', { + super(os, 'games/reversi', { i: me.token }); } diff --git a/src/client/app/common/scripts/streaming/hybrid-timeline.ts b/src/client/app/common/scripts/streaming/hybrid-timeline.ts new file mode 100644 index 0000000000..cd290797c4 --- /dev/null +++ b/src/client/app/common/scripts/streaming/hybrid-timeline.ts @@ -0,0 +1,34 @@ +import Stream from './stream'; +import StreamManager from './stream-manager'; +import MiOS from '../../../mios'; + +/** + * Hybrid timeline stream connection + */ +export class HybridTimelineStream extends Stream { + constructor(os: MiOS, me) { + super(os, 'hybrid-timeline', { + i: me.token + }); + } +} + +export class HybridTimelineStreamManager extends StreamManager<HybridTimelineStream> { + private me; + private os: MiOS; + + constructor(os: MiOS, me) { + super(); + + this.me = me; + this.os = os; + } + + public getConnection() { + if (this.connection == null) { + this.connection = new HybridTimelineStream(this.os, this.me); + } + + return this.connection; + } +} diff --git a/src/client/app/common/views/components/analog-clock.vue b/src/client/app/common/views/components/analog-clock.vue index 53fb2a8dad..43ae2ca933 100644 --- a/src/client/app/common/views/components/analog-clock.vue +++ b/src/client/app/common/views/components/analog-clock.vue @@ -39,13 +39,17 @@ export default Vue.extend({ dark: { type: Boolean, default: false + }, + smooth: { + type: Boolean, + default: false } }, data() { return { now: new Date(), - clock: null, + enabled: true, graduationsPadding: 0.5, handsPadding: 1, @@ -74,6 +78,9 @@ export default Vue.extend({ return themeColor; }, + ms(): number { + return this.now.getMilliseconds() * this.smooth; + } s(): number { return this.now.getSeconds(); }, @@ -85,13 +92,13 @@ export default Vue.extend({ }, hAngle(): number { - return Math.PI * (this.h % 12 + this.m / 60) / 6; + return Math.PI * (this.h % 12 + (this.m + (this.s + this.ms / 1000) / 60) / 60) / 6; }, mAngle(): number { - return Math.PI * (this.m + this.s / 60) / 30; + return Math.PI * (this.m + (this.s + this.ms / 1000) / 60) / 30; }, sAngle(): number { - return Math.PI * this.s / 30; + return Math.PI * (this.s + this.ms / 1000) / 30; }, graduations(): any { @@ -106,11 +113,17 @@ export default Vue.extend({ }, mounted() { - this.clock = setInterval(this.tick, 1000); + const update = () => { + if (this.enabled) { + this.tick(); + requestAnimationFrame(update); + } + }; + update(); }, beforeDestroy() { - clearInterval(this.clock); + this.enabled = false; }, methods: { diff --git a/src/client/app/common/views/components/autocomplete.vue b/src/client/app/common/views/components/autocomplete.vue index 84173d20b5..cd6066877c 100644 --- a/src/client/app/common/views/components/autocomplete.vue +++ b/src/client/app/common/views/components/autocomplete.vue @@ -2,11 +2,16 @@ <div class="mk-autocomplete" @contextmenu.prevent="() => {}"> <ol class="users" ref="suggests" v-if="users.length > 0"> <li v-for="user in users" @click="complete(type, user)" @keydown="onKeydown" tabindex="-1"> - <img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=32`" alt=""/> + <img class="avatar" :src="user.avatarUrl" alt=""/> <span class="name">{{ user | userName }}</span> <span class="username">@{{ user | acct }}</span> </li> </ol> + <ol class="hashtags" ref="suggests" v-if="hashtags.length > 0"> + <li v-for="hashtag in hashtags" @click="complete(type, hashtag)" @keydown="onKeydown" tabindex="-1"> + <span class="name">{{ hashtag }}</span> + </li> + </ol> <ol class="emojis" ref="suggests" v-if="emojis.length > 0"> <li v-for="emoji in emojis" @click="complete(type, emoji.emoji)" @keydown="onKeydown" tabindex="-1"> <span class="emoji">{{ emoji.emoji }}</span> @@ -48,33 +53,33 @@ emjdb.sort((a, b) => a.name.length - b.name.length); export default Vue.extend({ props: ['type', 'q', 'textarea', 'complete', 'close', 'x', 'y'], + data() { return { fetching: true, users: [], + hashtags: [], emojis: [], select: -1, emojilib } }, + computed: { items(): HTMLCollection { return (this.$refs.suggests as Element).children; } }, + updated() { //#region 位置調整 - const margin = 32; - - if (this.x + this.$el.offsetWidth > window.innerWidth - margin) { - this.$el.style.left = (this.x - this.$el.offsetWidth) + 'px'; - this.$el.style.marginLeft = '-16px'; + if (this.x + this.$el.offsetWidth > window.innerWidth) { + this.$el.style.left = (window.innerWidth - this.$el.offsetWidth) + 'px'; } else { this.$el.style.left = this.x + 'px'; - this.$el.style.marginLeft = '0'; } - if (this.y + this.$el.offsetHeight > window.innerHeight - margin) { + if (this.y + this.$el.offsetHeight > window.innerHeight) { this.$el.style.top = (this.y - this.$el.offsetHeight) + 'px'; this.$el.style.marginTop = '0'; } else { @@ -83,6 +88,7 @@ export default Vue.extend({ } //#endregion }, + mounted() { this.textarea.addEventListener('keydown', this.onKeydown); @@ -100,6 +106,7 @@ export default Vue.extend({ }); }); }, + beforeDestroy() { this.textarea.removeEventListener('keydown', this.onKeydown); @@ -107,6 +114,7 @@ export default Vue.extend({ el.removeEventListener('mousedown', this.onMousedown); }); }, + methods: { exec() { this.select = -1; @@ -117,7 +125,8 @@ export default Vue.extend({ } if (this.type == 'user') { - const cache = sessionStorage.getItem(this.q); + const cacheKey = 'autocomplete:user:' + this.q; + const cache = sessionStorage.getItem(cacheKey); if (cache) { const users = JSON.parse(cache); this.users = users; @@ -131,9 +140,33 @@ export default Vue.extend({ this.fetching = false; // キャッシュ - sessionStorage.setItem(this.q, JSON.stringify(users)); + sessionStorage.setItem(cacheKey, JSON.stringify(users)); }); } + } else if (this.type == 'hashtag') { + if (this.q == null || this.q == '') { + this.hashtags = JSON.parse(localStorage.getItem('hashtags') || '[]'); + this.fetching = false; + } else { + const cacheKey = 'autocomplete:hashtag:' + this.q; + const cache = sessionStorage.getItem(cacheKey); + if (cache) { + const hashtags = JSON.parse(cache); + this.hashtags = hashtags; + this.fetching = false; + } else { + (this as any).api('hashtags/search', { + query: this.q, + limit: 30 + }).then(hashtags => { + this.hashtags = hashtags; + this.fetching = false; + + // キャッシュ + sessionStorage.setItem(cacheKey, JSON.stringify(hashtags)); + }); + } + } } else if (this.type == 'emoji') { const matched = []; emjdb.some(x => { @@ -228,12 +261,13 @@ export default Vue.extend({ <style lang="stylus" scoped> @import '~const.styl' -.mk-autocomplete +root(isDark) position fixed z-index 65535 + max-width 100% margin-top calc(1em + 8px) overflow hidden - background #fff + background isDark ? #313543 : #fff border solid 1px rgba(#000, 0.1) border-radius 4px transition top 0.1s ease, left 0.1s ease @@ -248,7 +282,8 @@ export default Vue.extend({ list-style none > li - display block + display flex + align-items center padding 4px 12px white-space nowrap overflow hidden @@ -259,7 +294,13 @@ export default Vue.extend({ &, * user-select none + * + overflow hidden + text-overflow ellipsis + &:hover + background isDark ? rgba(#fff, 0.1) : rgba(#000, 0.1) + &[data-selected='true'] background $theme-color @@ -275,7 +316,6 @@ export default Vue.extend({ > .users > li .avatar - vertical-align middle min-width 28px min-height 28px max-width 28px @@ -285,10 +325,15 @@ export default Vue.extend({ .name margin 0 8px 0 0 - color rgba(#000, 0.8) + color isDark ? rgba(#fff, 0.8) : rgba(#000, 0.8) .username - color rgba(#000, 0.3) + color isDark ? rgba(#fff, 0.3) : rgba(#000, 0.3) + + > .hashtags > li + + .name + color isDark ? rgba(#fff, 0.8) : rgba(#000, 0.8) > .emojis > li @@ -298,10 +343,15 @@ export default Vue.extend({ width 24px .name - color rgba(#000, 0.8) + color isDark ? rgba(#fff, 0.8) : rgba(#000, 0.8) .alias margin 0 0 0 8px - color rgba(#000, 0.3) + color isDark ? rgba(#fff, 0.3) : rgba(#000, 0.3) +.mk-autocomplete[data-darkmode] + root(true) + +.mk-autocomplete:not([data-darkmode]) + root(false) </style> diff --git a/src/client/app/common/views/components/avatar.vue b/src/client/app/common/views/components/avatar.vue index a65b62882f..a924b62e64 100644 --- a/src/client/app/common/views/components/avatar.vue +++ b/src/client/app/common/views/components/avatar.vue @@ -31,7 +31,7 @@ export default Vue.extend({ : this.user.avatarColor && this.user.avatarColor.length == 3 ? `rgb(${ this.user.avatarColor.join(',') })` : null, - backgroundImage: this.lightmode ? null : `url(${ this.user.avatarUrl }?thumbnail)`, + backgroundImage: this.lightmode ? null : `url(${ this.user.avatarUrl })`, borderRadius: this.$store.state.settings.circleIcons ? '100%' : null }; } diff --git a/src/client/app/common/views/components/reversi.game.vue b/src/client/app/common/views/components/games/reversi/reversi.game.vue similarity index 93% rename from src/client/app/common/views/components/reversi.game.vue rename to src/client/app/common/views/components/games/reversi/reversi.game.vue index a2a6fd0dc1..dd2c94a603 100644 --- a/src/client/app/common/views/components/reversi.game.vue +++ b/src/client/app/common/views/components/games/reversi/reversi.game.vue @@ -8,7 +8,7 @@ <p class="turn1" v-if="iAmPlayer && !game.isEnded && !isMyTurn">%i18n:common.reversi.opponent-turn%<mk-ellipsis/></p> <p class="turn2" v-if="iAmPlayer && !game.isEnded && isMyTurn" v-animate-css="{ classes: 'tada', iteration: 'infinite' }">%i18n:common.reversi.my-turn%</p> <p class="result" v-if="game.isEnded && logPos == logs.length"> - <template v-if="game.winner"><b>{{ game.winner.name }}</b>の勝ち{{ game.settings.isLlotheo ? ' (ロセオ)' : '' }}</template> + <template v-if="game.winner">{{ '%i18n:common.reversi.won%'.replace('{}', game.winner.name) }}{{ game.settings.isLlotheo ? ' (ロセオ)' : '' }}</template> <template v-else>%i18n:common.reversi.drawn%</template> </p> </div> @@ -26,8 +26,8 @@ :class="{ empty: stone == null, none: o.map[i] == 'null', isEnded: game.isEnded, myTurn: !game.isEnded && isMyTurn, can: turnUser ? o.canPut(turnUser.id == blackUser.id, i) : null, prev: o.prevPos == i }" @click="set(i)" :title="`${String.fromCharCode(65 + o.transformPosToXy(i)[0])}${o.transformPosToXy(i)[1] + 1}`"> - <img v-if="stone === true" :src="`${blackUser.avatarUrl}?thumbnail&size=128`" alt=""> - <img v-if="stone === false" :src="`${whiteUser.avatarUrl}?thumbnail&size=128`" alt=""> + <img v-if="stone === true" :src="blackUser.avatarUrl" alt=""> + <img v-if="stone === false" :src="whiteUser.avatarUrl" alt=""> </div> </div> <div class="labels-y" v-if="this.$store.state.settings.reversiBoardLabels"> @@ -58,8 +58,8 @@ <script lang="ts"> import Vue from 'vue'; import * as CRC32 from 'crc-32'; -import Reversi, { Color } from '../../../../../reversi/core'; -import { url } from '../../../config'; +import Reversi, { Color } from '../../../../../../../games/reversi/core'; +import { url } from '../../../../../config'; export default Vue.extend({ props: ['initGame', 'connection'], @@ -105,13 +105,14 @@ export default Vue.extend({ } }, isMyTurn(): boolean { - if (this.turnUser == null) return null; + if (!this.iAmPlayer) return false; + if (this.turnUser == null) return false; return this.turnUser.id == this.$store.state.i.id; }, cellsStyle(): any { return { - 'grid-template-rows': `repeat(${ this.game.settings.map.length }, 1fr)`, - 'grid-template-columns': `repeat(${ this.game.settings.map[0].length }, 1fr)` + 'grid-template-rows': `repeat(${this.game.settings.map.length}, 1fr)`, + 'grid-template-columns': `repeat(${this.game.settings.map[0].length}, 1fr)` }; } }, diff --git a/src/client/app/common/views/components/reversi.gameroom.vue b/src/client/app/common/views/components/games/reversi/reversi.gameroom.vue similarity index 89% rename from src/client/app/common/views/components/reversi.gameroom.vue rename to src/client/app/common/views/components/games/reversi/reversi.gameroom.vue index 7ce0112451..4969a9347e 100644 --- a/src/client/app/common/views/components/reversi.gameroom.vue +++ b/src/client/app/common/views/components/games/reversi/reversi.gameroom.vue @@ -9,7 +9,7 @@ import Vue from 'vue'; import XGame from './reversi.game.vue'; import XRoom from './reversi.room.vue'; -import { ReversiGameStream } from '../../scripts/streaming/reversi-game'; +import { ReversiGameStream } from '../../../../scripts/streaming/games/reversi/reversi-game'; export default Vue.extend({ components: { diff --git a/src/client/app/common/views/components/reversi.room.vue b/src/client/app/common/views/components/games/reversi/reversi.room.vue similarity index 94% rename from src/client/app/common/views/components/reversi.room.vue rename to src/client/app/common/views/components/games/reversi/reversi.room.vue index 5074845758..841f6b366a 100644 --- a/src/client/app/common/views/components/reversi.room.vue +++ b/src/client/app/common/views/components/games/reversi/reversi.room.vue @@ -94,7 +94,7 @@ <script lang="ts"> import Vue from 'vue'; -import * as maps from '../../../../../reversi/maps'; +import * as maps from '../../../../../../../games/reversi/maps'; export default Vue.extend({ props: ['game', 'connection'], @@ -112,7 +112,7 @@ export default Vue.extend({ computed: { mapCategories(): string[] { - const categories = Object.entries(maps).map(x => x[1].category); + const categories = Object.values(maps).map(x => x.category); return categories.filter((item, pos) => categories.indexOf(item) == pos); }, isAccepted(): boolean { @@ -179,8 +179,8 @@ export default Vue.extend({ if (this.game.settings.map == null) { this.mapName = null; } else { - const foundMap = Object.entries(maps).find(x => x[1].data.join('') == this.game.settings.map.join('')); - this.mapName = foundMap ? foundMap[1].name : '-Custom-'; + const found = Object.values(maps).find(x => x.data.join('') == this.game.settings.map.join('')); + this.mapName = found ? found.name : '-Custom-'; } }, @@ -206,7 +206,7 @@ export default Vue.extend({ if (v == null) { this.game.settings.map = null; } else { - this.game.settings.map = Object.entries(maps).find(x => x[1].name == v)[1].data; + this.game.settings.map = Object.values(maps).find(x => x.name == v).data; } this.$forceUpdate(); this.updateSettings(); @@ -217,9 +217,9 @@ export default Vue.extend({ const y = Math.floor(pos / this.game.settings.map[0].length); const newPixel = pixel == ' ' ? '-' : - pixel == '-' ? 'b' : - pixel == 'b' ? 'w' : - ' '; + pixel == '-' ? 'b' : + pixel == 'b' ? 'w' : + ' '; const line = this.game.settings.map[y].split(''); line[x] = newPixel; this.$set(this.game.settings.map, y, line.join('')); diff --git a/src/client/app/common/views/components/reversi.vue b/src/client/app/common/views/components/games/reversi/reversi.vue similarity index 82% rename from src/client/app/common/views/components/reversi.vue rename to src/client/app/common/views/components/games/reversi/reversi.vue index 61705163ac..3d28b6bdd6 100644 --- a/src/client/app/common/views/components/reversi.vue +++ b/src/client/app/common/views/components/games/reversi/reversi.vue @@ -67,7 +67,9 @@ export default Vue.extend({ components: { XGameroom }, + props: ['initGame'], + data() { return { game: null, @@ -82,63 +84,73 @@ export default Vue.extend({ pingClock: null }; }, + watch: { game(g) { this.$emit('gamed', g); } }, + created() { if (this.initGame) { this.game = this.initGame; } }, + mounted() { - this.connection = (this as any).os.streams.reversiStream.getConnection(); - this.connectionId = (this as any).os.streams.reversiStream.use(); + if (this.$store.getters.isSignedIn) { + this.connection = (this as any).os.streams.reversiStream.getConnection(); + this.connectionId = (this as any).os.streams.reversiStream.use(); - this.connection.on('matched', this.onMatched); - this.connection.on('invited', this.onInvited); + this.connection.on('matched', this.onMatched); + this.connection.on('invited', this.onInvited); - (this as any).api('reversi/games', { - my: true - }).then(games => { - this.myGames = games; - }); + (this as any).api('games/reversi/games', { + my: true + }).then(games => { + this.myGames = games; + }); - (this as any).api('reversi/games').then(games => { + (this as any).api('games/reversi/invitations').then(invitations => { + this.invitations = this.invitations.concat(invitations); + }); + + this.pingClock = setInterval(() => { + if (this.matching) { + this.connection.send({ + type: 'ping', + id: this.matching.id + }); + } + }, 3000); + } + + (this as any).api('games/reversi/games').then(games => { this.games = games; this.gamesFetching = false; }); - - (this as any).api('reversi/invitations').then(invitations => { - this.invitations = this.invitations.concat(invitations); - }); - - this.pingClock = setInterval(() => { - if (this.matching) { - this.connection.send({ - type: 'ping', - id: this.matching.id - }); - } - }, 3000); }, + beforeDestroy() { - this.connection.off('matched', this.onMatched); - this.connection.off('invited', this.onInvited); - (this as any).os.streams.reversiStream.dispose(this.connectionId); + if (this.connection) { + this.connection.off('matched', this.onMatched); + this.connection.off('invited', this.onInvited); + (this as any).os.streams.reversiStream.dispose(this.connectionId); - clearInterval(this.pingClock); + clearInterval(this.pingClock); + } }, + methods: { go(game) { - (this as any).api('reversi/games/show', { + (this as any).api('games/reversi/games/show', { gameId: game.id }).then(game => { this.matching = null; this.game = game; }); }, + match() { (this as any).apis.input({ title: 'ユーザー名を入力してください' @@ -146,7 +158,7 @@ export default Vue.extend({ (this as any).api('users/show', { username }).then(user => { - (this as any).api('reversi/match', { + (this as any).api('games/reversi/match', { userId: user.id }).then(res => { if (res == null) { @@ -158,12 +170,14 @@ export default Vue.extend({ }); }); }, + cancel() { this.matching = null; - (this as any).api('reversi/match/cancel'); + (this as any).api('games/reversi/match/cancel'); }, + accept(invitation) { - (this as any).api('reversi/match', { + (this as any).api('games/reversi/match', { userId: invitation.parent.id }).then(game => { if (game) { @@ -172,10 +186,12 @@ export default Vue.extend({ } }); }, + onMatched(game) { this.matching = null; this.game = game; }, + onInvited(invite) { this.invitations.unshift(invite); } diff --git a/src/client/app/common/views/components/index.ts b/src/client/app/common/views/components/index.ts index e2cba2e53b..c18a1c3b68 100644 --- a/src/client/app/common/views/components/index.ts +++ b/src/client/app/common/views/components/index.ts @@ -27,7 +27,7 @@ import urlPreview from './url-preview.vue'; import twitterSetting from './twitter-setting.vue'; import fileTypeIcon from './file-type-icon.vue'; import Switch from './switch.vue'; -import Reversi from './reversi.vue'; +import Reversi from './games/reversi/reversi.vue'; import welcomeTimeline from './welcome-timeline.vue'; import uiInput from './ui/input.vue'; import uiButton from './ui/button.vue'; diff --git a/src/client/app/common/views/components/media-list.vue b/src/client/app/common/views/components/media-list.vue index 2f8a1943ad..cdfc2c8d3c 100644 --- a/src/client/app/common/views/components/media-list.vue +++ b/src/client/app/common/views/components/media-list.vue @@ -46,33 +46,45 @@ export default Vue.extend({ display grid grid-gap 4px + > * + overflow hidden + border-radius 4px + &[data-count="1"] grid-template-rows 1fr + &[data-count="2"] grid-template-columns 1fr 1fr grid-template-rows 1fr + &[data-count="3"] grid-template-columns 1fr 0.5fr grid-template-rows 1fr 1fr - :nth-child(1) + + > *:nth-child(1) grid-row 1 / 3 - :nth-child(3) + + > *:nth-child(3) grid-column 2 / 3 grid-row 2 / 3 + &[data-count="4"] grid-template-columns 1fr 1fr grid-template-rows 1fr 1fr - :nth-child(1) + > *:nth-child(1) grid-column 1 / 2 grid-row 1 / 2 - :nth-child(2) + + > *:nth-child(2) grid-column 2 / 3 grid-row 1 / 2 - :nth-child(3) + + > *:nth-child(3) grid-column 1 / 2 grid-row 2 / 3 - :nth-child(4) + + > *:nth-child(4) grid-column 2 / 3 grid-row 2 / 3 diff --git a/src/client/app/common/views/components/messaging-room.form.vue b/src/client/app/common/views/components/messaging-room.form.vue index 050906cf44..b6ca902660 100644 --- a/src/client/app/common/views/components/messaging-room.form.vue +++ b/src/client/app/common/views/components/messaging-room.form.vue @@ -119,7 +119,7 @@ export default Vue.extend({ }, onKeypress(e) { - if ((e.which == 10 || e.which == 13) && e.ctrlKey) { + if ((e.which == 10 || e.which == 13) && e.ctrlKey && this.canSend) { this.send(); } }, diff --git a/src/client/app/common/views/components/messaging-room.message.vue b/src/client/app/common/views/components/messaging-room.message.vue index f33173da6f..65231aed17 100644 --- a/src/client/app/common/views/components/messaging-room.message.vue +++ b/src/client/app/common/views/components/messaging-room.message.vue @@ -3,10 +3,9 @@ <mk-avatar class="avatar" :user="message.user" target="_blank"/> <div class="content"> <div class="balloon" :data-no-text="message.text == null"> - <p class="read" v-if="isMe && message.isRead">%i18n:@is-read%</p> - <button class="delete-button" v-if="isMe" title="%i18n:common.delete%"> + <!-- <button class="delete-button" v-if="isMe" title="%i18n:common.delete%"> <img src="/assets/desktop/messaging/delete.png" alt="Delete"/> - </button> + </button> --> <div class="content" v-if="!message.isDeleted"> <misskey-flavored-markdown class="text" v-if="message.text" ref="text" :text="message.text" :i="$store.state.i"/> <div class="file" v-if="message.file"> @@ -23,6 +22,7 @@ <div></div> <mk-url-preview v-for="url in urls" :url="url" :key="url"/> <footer> + <span class="read" v-if="isMe && message.isRead">%i18n:@is-read%</span> <mk-time :time="message.createdAt"/> <template v-if="message.is_edited">%fa:pencil-alt%</template> </footer> @@ -120,17 +120,6 @@ root(isDark) height 16px cursor pointer - > .read - user-select none - display block - position absolute - z-index 1 - bottom -4px - left -12px - margin 0 - color isDark ? rgba(#fff, 0.5) : rgba(#000, 0.5) - font-size 11px - > .content > .is-deleted @@ -258,6 +247,12 @@ root(isDark) > footer text-align right + > .read + user-select none + margin 0 4px 0 0 + color isDark ? rgba(#fff, 0.5) : rgba(#000, 0.5) + font-size 11px + &[data-is-deleted] > .baloon opacity 0.5 diff --git a/src/client/app/common/views/components/messaging.vue b/src/client/app/common/views/components/messaging.vue index 2ddec29984..6abfc92dca 100644 --- a/src/client/app/common/views/components/messaging.vue +++ b/src/client/app/common/views/components/messaging.vue @@ -51,7 +51,7 @@ <script lang="ts"> import Vue from 'vue'; -import getAcct from '../../../../../acct/render'; +import getAcct from '../../../../../misc/acct/render'; export default Vue.extend({ props: { diff --git a/src/client/app/common/views/components/misskey-flavored-markdown.ts b/src/client/app/common/views/components/misskey-flavored-markdown.ts index c321c76104..1480c0325c 100644 --- a/src/client/app/common/views/components/misskey-flavored-markdown.ts +++ b/src/client/app/common/views/components/misskey-flavored-markdown.ts @@ -1,7 +1,7 @@ import Vue from 'vue'; import * as emojilib from 'emojilib'; import parse from '../../../../../mfm/parse'; -import getAcct from '../../../../../acct/render'; +import getAcct from '../../../../../misc/acct/render'; import { url } from '../../../config'; import MkUrl from './url.vue'; import MkGoogle from './google.vue'; @@ -92,7 +92,7 @@ export default Vue.component('misskey-flavored-markdown', { case 'hashtag': return createElement('a', { attrs: { - href: `${url}/tags/${token.hashtag}`, + href: `${url}/tags/${encodeURIComponent(token.hashtag)}`, target: '_blank' } }, token.content); diff --git a/src/client/app/common/views/components/nav.vue b/src/client/app/common/views/components/nav.vue index cd1f99288a..e25dbc78ca 100644 --- a/src/client/app/common/views/components/nav.vue +++ b/src/client/app/common/views/components/nav.vue @@ -2,9 +2,9 @@ <span class="mk-nav"> <a :href="aboutUrl">%i18n:@about%</a> <i>・</i> - <a href="https://github.com/syuilo/misskey">%i18n:@repository%</a> + <a :href="repositoryUrl">%i18n:@repository%</a> <i>・</i> - <a href="https://github.com/syuilo/misskey/issues/new" target="_blank">%i18n:@feedback%</a> + <a :href="feedbackUrl" target="_blank">%i18n:@feedback%</a> <i>・</i> <a :href="devUrl">%i18n:@develop%</a> <i>・</i> @@ -14,7 +14,7 @@ <script lang="ts"> import Vue from 'vue'; -import { docsUrl, statsUrl, statusUrl, devUrl, lang } from '../../../config'; +import { docsUrl, statsUrl, statusUrl, devUrl, repositoryUrl, feedbackUrl, lang } from '../../../config'; export default Vue.extend({ data() { @@ -22,7 +22,9 @@ export default Vue.extend({ aboutUrl: `${docsUrl}/${lang}/about`, statsUrl, statusUrl, - devUrl + devUrl, + repositoryUrl: repositoryUrl || `https://github.com/syuilo/misskey`, + feedbackUrl: feedbackUrl || `https://github.com/syuilo/misskey/issues/new` } } }); diff --git a/src/client/app/common/views/components/note-header.vue b/src/client/app/common/views/components/note-header.vue index 25a3339264..9bba6990db 100644 --- a/src/client/app/common/views/components/note-header.vue +++ b/src/client/app/common/views/components/note-header.vue @@ -2,6 +2,7 @@ <header class="bvonvjxbwzaiskogyhbwgyxvcgserpmu"> <mk-avatar class="avatar" :user="note.user" v-if="$store.state.device.postStyle == 'smart'"/> <router-link class="name" :to="note.user | userPage" v-user-preview="note.user.id">{{ note.user | userName }}</router-link> + <span class="is-verified" v-if="note.user.isVerified" title="%i18n:common.verified-user%">%fa:bookmark%</span> <span class="is-admin" v-if="note.user.isAdmin">admin</span> <span class="is-bot" v-if="note.user.isBot">bot</span> <span class="is-cat" v-if="note.user.isCat">cat</span> @@ -69,6 +70,10 @@ root(isDark) &:hover text-decoration underline + > .is-verified + margin-right 8px + color #4dabf7 + > .is-admin > .is-bot > .is-cat diff --git a/src/client/app/common/views/components/reaction-picker.vue b/src/client/app/common/views/components/reaction-picker.vue index ed7aedb58e..5a149cc4d1 100644 --- a/src/client/app/common/views/components/reaction-picker.vue +++ b/src/client/app/common/views/components/reaction-picker.vue @@ -183,7 +183,7 @@ root(isDark) border-right solid $balloon-size transparent border-bottom solid $balloon-size $bgcolor - &.compact + &.big > div width 280px diff --git a/src/client/app/common/views/components/signup.vue b/src/client/app/common/views/components/signup.vue index 62373a59ec..45a183e144 100644 --- a/src/client/app/common/views/components/signup.vue +++ b/src/client/app/common/views/components/signup.vue @@ -29,11 +29,7 @@ <p slot="text" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@password-not-matched%</p> </div> </ui-input> - <div class="g-recaptcha" :data-sitekey="recaptchaSitekey" style="margin: 16px 0;"></div> - <label class="agree-tou" style="display: block; margin: 16px 0;"> - <input name="agree-tou" type="checkbox" required/> - <p><a :href="touUrl" target="_blank">利用規約</a>に同意する</p> - </label> + <div v-if="recaptchaSitekey != null" class="g-recaptcha" :data-sitekey="recaptchaSitekey" style="margin: 16px 0;"></div> <ui-button type="submit">%i18n:@create%</ui-button> </form> </template> @@ -41,7 +37,7 @@ <script lang="ts"> import Vue from 'vue'; const getPasswordStrength = require('syuilo-password-strength'); -import { host, url, docsUrl, lang, recaptchaSitekey } from '../../../config'; +import { host, url, recaptchaSitekey } from '../../../config'; export default Vue.extend({ data() { @@ -51,7 +47,6 @@ export default Vue.extend({ password: '', retypedPassword: '', url, - touUrl: `${docsUrl}/${lang}/tou`, recaptchaSitekey, usernameState: null, passwordStrength: '', @@ -115,7 +110,7 @@ export default Vue.extend({ (this as any).api('signup', { username: this.username, password: this.password, - 'g-recaptcha-response': (window as any).grecaptcha.getResponse() + 'g-recaptcha-response': recaptchaSitekey != null ? (window as any).grecaptcha.getResponse() : null }).then(() => { (this as any).api('signin', { username: this.username, @@ -126,15 +121,19 @@ export default Vue.extend({ }).catch(() => { alert('%i18n:@some-error%'); - (window as any).grecaptcha.reset(); + if (recaptchaSitekey != null) { + (window as any).grecaptcha.reset(); + } }); } }, mounted() { - const head = document.getElementsByTagName('head')[0]; - const script = document.createElement('script'); - script.setAttribute('src', 'https://www.google.com/recaptcha/api.js'); - head.appendChild(script); + if (recaptchaSitekey != null) { + const head = document.getElementsByTagName('head')[0]; + const script = document.createElement('script'); + script.setAttribute('src', 'https://www.google.com/recaptcha/api.js'); + head.appendChild(script); + } } }); </script> @@ -144,22 +143,4 @@ export default Vue.extend({ .mk-signup min-width 302px - - .agree-tou - padding 4px - border-radius 4px - - &:hover - background #f4f4f4 - - &:active - background #eee - - &, * - cursor pointer - - p - display inline - color #555 - </style> diff --git a/src/client/app/common/views/components/url-preview.vue b/src/client/app/common/views/components/url-preview.vue index 38979871c1..1e625f69ed 100644 --- a/src/client/app/common/views/components/url-preview.vue +++ b/src/client/app/common/views/components/url-preview.vue @@ -2,6 +2,11 @@ <iframe v-if="youtubeId" type="text/html" height="250" :src="`https://www.youtube.com/embed/${youtubeId}?origin=${misskeyUrl}`" frameborder="0"/> +<div v-else-if="tweetUrl && detail" class="twitter"> + <blockquote ref="tweet" class="twitter-tweet" :data-theme="$store.state.device.darkmode ? 'dark' : null"> + <a :href="url"></a> + </blockquote> +</div> <div v-else class="mk-url-preview"> <a :href="url" target="_blank" :title="url" v-if="!fetching"> <div class="thumbnail" v-if="thumbnail" :style="`background-image: url(${thumbnail})`"></div> @@ -24,7 +29,17 @@ import Vue from 'vue'; import { url as misskeyUrl } from '../../../config'; export default Vue.extend({ - props: ['url'], + props: { + url: { + type: String, + require: true + }, + detail: { + type: Boolean, + required: false, + default: false + } + }, data() { return { fetching: true, @@ -34,6 +49,7 @@ export default Vue.extend({ icon: null, sitename: null, youtubeId: null, + tweetUrl: null, misskeyUrl }; }, @@ -44,6 +60,25 @@ export default Vue.extend({ this.youtubeId = url.searchParams.get('v'); } else if (url.hostname == 'youtu.be') { this.youtubeId = url.pathname; + } else if (this.detail && url.hostname == 'twitter.com' && /^\/.+\/status(es)?\/\d+/.test(url.pathname)) { + this.tweetUrl = url; + const twttr = (window as any).twttr || {}; + const loadTweet = () => twttr.widgets.load(this.$refs.tweet); + + if (twttr.widgets) { + Vue.nextTick(loadTweet); + } else { + const wjsId = 'twitter-wjs'; + if (!document.getElementById(wjsId)) { + const head = document.getElementsByTagName('head')[0]; + const script = document.createElement('script'); + script.setAttribute('id', wjsId); + script.setAttribute('src', 'https://platform.twitter.com/widgets.js'); + head.appendChild(script); + } + twttr.ready = loadTweet; + (window as any).twttr = twttr; + } } else { fetch('/url?url=' + encodeURIComponent(this.url)).then(res => { res.json().then(info => { diff --git a/src/client/app/common/views/directives/autocomplete.ts b/src/client/app/common/views/directives/autocomplete.ts index 94635d301a..b252cf5c1f 100644 --- a/src/client/app/common/views/directives/autocomplete.ts +++ b/src/client/app/common/views/directives/autocomplete.ts @@ -1,5 +1,6 @@ import * as getCaretCoordinates from 'textarea-caret'; import MkAutocomplete from '../components/autocomplete.vue'; +import renderAcct from '../../../../../misc/acct/render'; export default { bind(el, binding, vn) { @@ -67,15 +68,30 @@ class Autocomplete { * テキスト入力時 */ private onInput() { - const caret = this.textarea.selectionStart; - const text = this.text.substr(0, caret); + const caretPos = this.textarea.selectionStart; + const text = this.text.substr(0, caretPos).split('\n').pop(); const mentionIndex = text.lastIndexOf('@'); + const hashtagIndex = text.lastIndexOf('#'); const emojiIndex = text.lastIndexOf(':'); + const max = Math.max( + mentionIndex, + hashtagIndex, + emojiIndex); + + if (max == -1) { + this.close(); + return; + } + + const isMention = mentionIndex != -1; + const isHashtag = hashtagIndex != -1; + const isEmoji = emojiIndex != -1; + let opened = false; - if (mentionIndex != -1 && mentionIndex > emojiIndex) { + if (isMention) { const username = text.substr(mentionIndex + 1); if (username != '' && username.match(/^[a-zA-Z0-9_]+$/)) { this.open('user', username); @@ -83,7 +99,15 @@ class Autocomplete { } } - if (emojiIndex != -1 && emojiIndex > mentionIndex) { + if (isHashtag && opened == false) { + const hashtag = text.substr(hashtagIndex + 1); + if (!hashtag.includes(' ')) { + this.open('hashtag', hashtag); + opened = true; + } + } + + if (isEmoji && opened == false) { const emoji = text.substr(emojiIndex + 1); if (emoji != '' && emoji.match(/^[\+\-a-z0-9_]+$/)) { this.open('emoji', emoji); @@ -164,13 +188,31 @@ class Autocomplete { const trimmedBefore = before.substring(0, before.lastIndexOf('@')); const after = source.substr(caret); + const acct = renderAcct(value); + // 挿入 - this.text = trimmedBefore + '@' + value.username + ' ' + after; + this.text = trimmedBefore + '@' + acct + ' ' + after; // キャレットを戻す this.vm.$nextTick(() => { this.textarea.focus(); - const pos = trimmedBefore.length + (value.username.length + 2); + const pos = trimmedBefore.length + (acct.length + 2); + this.textarea.setSelectionRange(pos, pos); + }); + } else if (type == 'hashtag') { + const source = this.text; + + const before = source.substr(0, caret); + const trimmedBefore = before.substring(0, before.lastIndexOf('#')); + const after = source.substr(caret); + + // 挿入 + this.text = trimmedBefore + '#' + value + ' ' + after; + + // キャレットを戻す + this.vm.$nextTick(() => { + this.textarea.focus(); + const pos = trimmedBefore.length + (value.length + 2); this.textarea.setSelectionRange(pos, pos); }); } else if (type == 'emoji') { diff --git a/src/client/app/common/views/filters/user.ts b/src/client/app/common/views/filters/user.ts index c5bb39f674..ca0910fc53 100644 --- a/src/client/app/common/views/filters/user.ts +++ b/src/client/app/common/views/filters/user.ts @@ -1,6 +1,6 @@ import Vue from 'vue'; -import getAcct from '../../../../../acct/render'; -import getUserName from '../../../../../renderers/get-user-name'; +import getAcct from '../../../../../misc/acct/render'; +import getUserName from '../../../../../misc/get-user-name'; Vue.filter('acct', user => { return getAcct(user); diff --git a/src/client/app/common/views/pages/follow.vue b/src/client/app/common/views/pages/follow.vue index c8e838be85..4b8c2d3b7c 100644 --- a/src/client/app/common/views/pages/follow.vue +++ b/src/client/app/common/views/pages/follow.vue @@ -31,8 +31,8 @@ <script lang="ts"> import Vue from 'vue'; -import parseAcct from '../../../../../acct/parse'; -import getUserName from '../../../../../renderers/get-user-name'; +import parseAcct from '../../../../../misc/acct/parse'; +import getUserName from '../../../../../misc/get-user-name'; import Progress from '../../../common/scripts/loading'; export default Vue.extend({ diff --git a/src/client/app/common/views/widgets/analog-clock.vue b/src/client/app/common/views/widgets/analog-clock.vue index b1177d4ddf..0de30228b3 100644 --- a/src/client/app/common/views/widgets/analog-clock.vue +++ b/src/client/app/common/views/widgets/analog-clock.vue @@ -1,8 +1,8 @@ <template> <div class="mkw-analog-clock"> - <mk-widget-container :naked="props.naked" :show-header="false"> + <mk-widget-container :naked="!(props.design % 2)" :show-header="false"> <div class="mkw-analog-clock--body"> - <mk-analog-clock :dark="$store.state.device.darkmode"/> + <mk-analog-clock :dark="$store.state.device.darkmode" :smooth="!(props.design && ~props.design)"/> </div> </mk-widget-container> </div> @@ -13,12 +13,13 @@ import define from '../../../common/define-widget'; export default define({ name: 'analog-clock', props: () => ({ - naked: false + design: -1 }) }).extend({ methods: { func() { - this.props.naked = !this.props.naked; + if (++this.props.design > 2) + this.props.design = -1; this.save(); } } diff --git a/src/client/app/common/views/widgets/calendar.vue b/src/client/app/common/views/widgets/calendar.vue index 333b56f629..9c8f1bff68 100644 --- a/src/client/app/common/views/widgets/calendar.vue +++ b/src/client/app/common/views/widgets/calendar.vue @@ -175,6 +175,7 @@ root(isDark) > .val height 4px background $theme-color + transition width .3s cubic-bezier(0.23, 1, 0.32, 1) &:nth-child(1) > .meter > .val diff --git a/src/client/app/common/views/widgets/hashtags.vue b/src/client/app/common/views/widgets/hashtags.vue index 2065bd407c..56520400b6 100644 --- a/src/client/app/common/views/widgets/hashtags.vue +++ b/src/client/app/common/views/widgets/hashtags.vue @@ -11,7 +11,7 @@ <div> <div v-for="stat in stats" :key="stat.tag"> <div class="tag"> - <router-link :to="`/tags/${ stat.tag }`" :title="stat.tag">#{{ stat.tag }}</router-link> + <router-link :to="`/tags/${ encodeURIComponent(stat.tag) }`" :title="stat.tag">#{{ stat.tag }}</router-link> <p>{{ '%i18n:@count%'.replace('{}', stat.usersCount) }}</p> </div> <x-chart class="chart" :src="stat.chart"/> diff --git a/src/client/app/common/views/widgets/photo-stream.vue b/src/client/app/common/views/widgets/photo-stream.vue index ae5924bb10..3e24c58e8e 100644 --- a/src/client/app/common/views/widgets/photo-stream.vue +++ b/src/client/app/common/views/widgets/photo-stream.vue @@ -5,7 +5,7 @@ <p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p> <div :class="$style.stream" v-if="!fetching && images.length > 0"> - <div v-for="image in images" :class="$style.img" :style="`background-image: url(${image.url}?thumbnail&size=256)`"></div> + <div v-for="image in images" :class="$style.img" :style="`background-image: url(${image.url})`"></div> </div> <p :class="$style.empty" v-if="!fetching && images.length == 0">%i18n:@no-photos%</p> </mk-widget-container> diff --git a/src/client/app/common/views/widgets/server.cpu-memory.vue b/src/client/app/common/views/widgets/server.cpu-memory.vue index da6b9f799f..2988993c94 100644 --- a/src/client/app/common/views/widgets/server.cpu-memory.vue +++ b/src/client/app/common/views/widgets/server.cpu-memory.vue @@ -102,7 +102,6 @@ export default Vue.extend({ }, methods: { onStats(stats) { - stats.mem.used = stats.mem.total - stats.mem.free; this.stats.push(stats); if (this.stats.length > 50) this.stats.shift(); @@ -111,8 +110,8 @@ export default Vue.extend({ this.cpuPolylinePoints = cpuPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' '); this.memPolylinePoints = memPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' '); - this.cpuPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${ this.viewBoxY } ${ this.cpuPolylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`; - this.memPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${ this.viewBoxY } ${ this.memPolylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`; + this.cpuPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${this.viewBoxY} ${this.cpuPolylinePoints} ${this.viewBoxX},${this.viewBoxY}`; + this.memPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${this.viewBoxY} ${this.memPolylinePoints} ${this.viewBoxX},${this.viewBoxY}`; this.cpuHeadX = cpuPolylinePoints[cpuPolylinePoints.length - 1][0]; this.cpuHeadY = cpuPolylinePoints[cpuPolylinePoints.length - 1][1]; diff --git a/src/client/app/common/views/widgets/server.memory.vue b/src/client/app/common/views/widgets/server.memory.vue index 9212f2271f..8a60621343 100644 --- a/src/client/app/common/views/widgets/server.memory.vue +++ b/src/client/app/common/views/widgets/server.memory.vue @@ -35,7 +35,7 @@ export default Vue.extend({ }, methods: { onStats(stats) { - stats.mem.used = stats.mem.total - stats.mem.free; + stats.mem.free = stats.mem.total - stats.mem.used; this.usage = stats.mem.used / stats.mem.total; this.total = stats.mem.total; this.used = stats.mem.used; diff --git a/src/client/app/common/views/widgets/slideshow.vue b/src/client/app/common/views/widgets/slideshow.vue index e1c28f5115..4f7f7e313f 100644 --- a/src/client/app/common/views/widgets/slideshow.vue +++ b/src/client/app/common/views/widgets/slideshow.vue @@ -2,10 +2,10 @@ <div class="mkw-slideshow" :data-mobile="platform == 'mobile'"> <div @click="choose"> <p v-if="props.folder === undefined"> - <template v-if="isCustomizeMode">フォルダを指定するには、カスタマイズモードを終了してください</template> - <template v-else>クリックしてフォルダを指定してください</template> + <template v-if="isCustomizeMode">%i18n:@folder-customize-mode%</template> + <template v-else>%i18n:@folder%</template> </p> - <p v-if="props.folder !== undefined && images.length == 0 && !fetching">このフォルダには画像がありません</p> + <p v-if="props.folder !== undefined && images.length == 0 && !fetching">%i18n:@no-image%</p> <div ref="slideA" class="slide a"></div> <div ref="slideB" class="slide b"></div> </div> @@ -72,7 +72,7 @@ export default define({ if (this.images.length == 0) return; const index = Math.floor(Math.random() * this.images.length); - const img = `url(${ this.images[index].url }?thumbnail&size=1024)`; + const img = `url(${ this.images[index].url })`; (this.$refs.slideB as any).style.backgroundImage = img; diff --git a/src/client/app/config.ts b/src/client/app/config.ts index c6efe26cd5..ceee0a2d62 100644 --- a/src/client/app/config.ts +++ b/src/client/app/config.ts @@ -9,6 +9,8 @@ declare const _DOCS_URL_: string; declare const _STATS_URL_: string; declare const _STATUS_URL_: string; declare const _DEV_URL_: string; +declare const _REPOSITORY_URL_: string; +declare const _FEEDBACK_URL_: string; declare const _LANG_: string; declare const _LANGS_: string; declare const _RECAPTCHA_SITEKEY_: string; @@ -32,6 +34,8 @@ export const docsUrl = _DOCS_URL_; export const statsUrl = _STATS_URL_; export const statusUrl = _STATUS_URL_; export const devUrl = _DEV_URL_; +export const repositoryUrl = _REPOSITORY_URL_; +export const feedbackUrl = _FEEDBACK_URL_; export const lang = _LANG_; export const langs = _LANGS_; export const recaptchaSitekey = _RECAPTCHA_SITEKEY_; diff --git a/src/client/app/desktop/assets/index.jpg b/src/client/app/desktop/assets/index.jpg index 10c412efe2..c054188159 100644 Binary files a/src/client/app/desktop/assets/index.jpg and b/src/client/app/desktop/assets/index.jpg differ diff --git a/src/client/app/desktop/assets/remove.png b/src/client/app/desktop/assets/remove.png index 8b1f4c06c9..c2e222a0fc 100644 Binary files a/src/client/app/desktop/assets/remove.png and b/src/client/app/desktop/assets/remove.png differ diff --git a/src/client/app/desktop/views/components/calendar.vue b/src/client/app/desktop/views/components/calendar.vue index 3b0330cf61..de9650b21b 100644 --- a/src/client/app/desktop/views/components/calendar.vue +++ b/src/client/app/desktop/views/components/calendar.vue @@ -35,10 +35,7 @@ import Vue from 'vue'; const eachMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; function isLeapYear(year) { - return (year % 400 == 0) ? true : - (year % 100 == 0) ? false : - (year % 4 == 0) ? true : - false; + return !(year & (year % 25 ? 3 : 15)); } export default Vue.extend({ diff --git a/src/client/app/desktop/views/components/choose-file-from-drive-window.vue b/src/client/app/desktop/views/components/choose-file-from-drive-window.vue index 30e59429d2..b894f0e109 100644 --- a/src/client/app/desktop/views/components/choose-file-from-drive-window.vue +++ b/src/client/app/desktop/views/components/choose-file-from-drive-window.vue @@ -28,7 +28,7 @@ export default Vue.extend({ default: false }, title: { - default: '%fa:R file%%i18n:@choose-prompt%s' + default: '%fa:R file%%i18n:@choose-prompt%' } }, data() { diff --git a/src/client/app/desktop/views/components/drive.file.vue b/src/client/app/desktop/views/components/drive.file.vue index 86addb1318..6541a8f21f 100644 --- a/src/client/app/desktop/views/components/drive.file.vue +++ b/src/client/app/desktop/views/components/drive.file.vue @@ -1,5 +1,5 @@ <template> -<div class="root file" +<div class="gvfdktuvdgwhmztnuekzkswkjygptfcv" :data-is-selected="isSelected" :data-is-contextmenu-showing="isContextmenuShowing" @click="onClick" @@ -16,7 +16,7 @@ <p>%i18n:@banner%</p> </div> <div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`"> - <img :src="`${file.url}?thumbnail&size=128`" alt="" @load="onThumbnailLoaded"/> + <img :src="file.url" alt="" @load="onThumbnailLoaded"/> </div> <p class="name"> <span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span> @@ -68,6 +68,11 @@ export default Vue.extend({ icon: '%fa:i-cursor%', action: this.rename }, { + type: 'item', + text: this.file.isSensitive ? '%i18n:@contextmenu.unmark-as-sensitive%' : '%i18n:@contextmenu.mark-as-sensitive%', + icon: this.file.isSensitive ? '%fa:R eye%' : '%fa:R eye-slash%', + action: this.toggleSensitive + }, null, { type: 'item', text: '%i18n:@contextmenu.copy-url%', icon: '%fa:link%', @@ -149,6 +154,13 @@ export default Vue.extend({ }); }, + toggleSensitive() { + (this as any).api('drive/files/update', { + fileId: this.file.id, + isSensitive: !this.file.isSensitive + }); + }, + copyUrl() { copyToClipboard(this.file.url); (this as any).apis.dialog({ @@ -312,10 +324,10 @@ root(isDark) > .ext opacity 0.5 -.root.file[data-darkmode] +.gvfdktuvdgwhmztnuekzkswkjygptfcv[data-darkmode] root(true) -.root.file:not([data-darkmode]) +.gvfdktuvdgwhmztnuekzkswkjygptfcv:not([data-darkmode]) root(false) </style> diff --git a/src/client/app/desktop/views/components/drive.folder.vue b/src/client/app/desktop/views/components/drive.folder.vue index fc0f353f47..e8077f9e3d 100644 --- a/src/client/app/desktop/views/components/drive.folder.vue +++ b/src/client/app/desktop/views/components/drive.folder.vue @@ -1,5 +1,5 @@ <template> -<div class="root folder" +<div class="ynntpczxvnusfwdyxsfuhvcmuypqopdd" :data-is-contextmenu-showing="isContextmenuShowing" :data-draghover="draghover" @click="onClick" @@ -216,10 +216,10 @@ export default Vue.extend({ <style lang="stylus" scoped> @import '~const.styl' -.root.folder +root(isDark) padding 8px height 64px - background lighten($theme-color, 95%) + background isDark ? rgba($theme-color, 0.2) : lighten($theme-color, 95%) border-radius 4px &, * @@ -229,10 +229,10 @@ export default Vue.extend({ pointer-events none &:hover - background lighten($theme-color, 90%) + background isDark ? rgba(lighten($theme-color, 10%), 0.2) : lighten($theme-color, 90%) &:active - background lighten($theme-color, 85%) + background isDark ? rgba(darken($theme-color, 10%), 0.2) : lighten($theme-color, 85%) &[data-is-contextmenu-showing] &[data-draghover] @@ -248,16 +248,22 @@ export default Vue.extend({ border-radius 4px &[data-draghover] - background lighten($theme-color, 90%) + background isDark ? rgba(darken($theme-color, 10%), 0.2) : lighten($theme-color, 90%) > .name margin 0 font-size 0.9em - color darken($theme-color, 30%) + color isDark ? #fff : darken($theme-color, 30%) > [data-fa] margin-right 4px margin-left 2px text-align left +.ynntpczxvnusfwdyxsfuhvcmuypqopdd[data-darkmode] + root(true) + +.ynntpczxvnusfwdyxsfuhvcmuypqopdd:not([data-darkmode]) + root(false) + </style> diff --git a/src/client/app/desktop/views/components/drive.vue b/src/client/app/desktop/views/components/drive.vue index df141b6d6c..6bad7c78a2 100644 --- a/src/client/app/desktop/views/components/drive.vue +++ b/src/client/app/desktop/views/components/drive.vue @@ -10,7 +10,10 @@ <span class="separator" v-if="folder != null">%fa:angle-right%</span> <span class="folder current" v-if="folder != null">{{ folder.name }}</span> </div> - <input class="search" type="search" placeholder=" %i18n:@search%"/> + <!-- + TODO: #343 + <input class="search" type="search" placeholder=" %i18n:@search%"/> + --> </nav> <div class="main" :class="{ uploading: uploadings.length > 0, fetching }" ref="main" diff --git a/src/client/app/desktop/views/components/followers-window.vue b/src/client/app/desktop/views/components/followers-window.vue index 7ed31315f1..fdab7bc1ce 100644 --- a/src/client/app/desktop/views/components/followers-window.vue +++ b/src/client/app/desktop/views/components/followers-window.vue @@ -1,7 +1,7 @@ <template> <mk-window width="400px" height="550px" @closed="$destroy"> <span slot="header" :class="$style.header"> - <img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""/>{{ '%i18n:@followers%'.replace('{}', name) }} + <img :src="user.avatarUrl" alt=""/>{{ '%i18n:@followers%'.replace('{}', name) }} </span> <mk-followers :user="user"/> </mk-window> diff --git a/src/client/app/desktop/views/components/following-window.vue b/src/client/app/desktop/views/components/following-window.vue index b97f21e2a3..7cca833a82 100644 --- a/src/client/app/desktop/views/components/following-window.vue +++ b/src/client/app/desktop/views/components/following-window.vue @@ -1,7 +1,7 @@ <template> <mk-window width="400px" height="550px" @closed="$destroy"> <span slot="header" :class="$style.header"> - <img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""/>{{ '%i18n:@following%'.replace('{}', name) }} + <img :src="user.avatarUrl" alt=""/>{{ '%i18n:@following%'.replace('{}', name) }} </span> <mk-following :user="user"/> </mk-window> diff --git a/src/client/app/desktop/views/components/home.vue b/src/client/app/desktop/views/components/home.vue index ab276d3c4b..d45cc82e13 100644 --- a/src/client/app/desktop/views/components/home.vue +++ b/src/client/app/desktop/views/components/home.vue @@ -34,7 +34,7 @@ </div> <div class="trash"> <x-draggable v-model="trash" :options="{ group: 'x' }" @add="onTrash"></x-draggable> - <p>ゴミ箱</p> + <p>%i18n:common.trash%</p> </div> </div> </div> @@ -53,7 +53,7 @@ </div> </x-draggable> <div class="main"> - <a @click="hint">カスタマイズのヒント</a> + <a @click="hint">%i18n:common.customization-tips.title%</a> <div> <mk-post-form v-if="$store.state.settings.showPostFormOnTopOfTl"/> <mk-timeline ref="tl" @loaded="onTlLoaded"/> @@ -187,13 +187,13 @@ export default Vue.extend({ methods: { hint() { (this as any).apis.dialog({ - title: '%fa:info-circle%カスタマイズのヒント', - text: '<p>ホームのカスタマイズでは、ウィジェットを追加/削除したり、ドラッグ&ドロップして並べ替えたりすることができます。</p>' + - '<p>一部のウィジェットは、<strong><strong>右</strong>クリック</strong>することで表示を変更することができます。</p>' + - '<p>ウィジェットを削除するには、ヘッダーの<strong>「ゴミ箱」</strong>と書かれたエリアにウィジェットをドラッグ&ドロップします。</p>' + - '<p>カスタマイズを終了するには、右上の「完了」をクリックします。</p>', + title: '%fa:info-circle%%i18n:common.customization-tips.title%', + text: '<p>%i18n:common.customization-tips.paragraph1%</p>' + + '<p>%i18n:common.customization-tips.paragraph2%</p>' + + '<p>%i18n:common.customization-tips.paragraph3%</p>' + + '<p>%i18n:common.customization-tips.paragraph4%</p>', actions: [{ - text: 'Got it!' + text: '%i18n:common.customization-tips.gotit%' }] }); }, diff --git a/src/client/app/desktop/views/components/media-image.vue b/src/client/app/desktop/views/components/media-image.vue index b98a4707ec..74bb03f4ed 100644 --- a/src/client/app/desktop/views/components/media-image.vue +++ b/src/client/app/desktop/views/components/media-image.vue @@ -1,5 +1,11 @@ <template> -<a class="mk-media-image" +<div class="ldwbgwstjsdgcjruamauqdrffetqudry" v-if="image.isSensitive && hide" @click="hide = false"> + <div> + <b>%fa:exclamation-triangle% %i18n:@sensitive%</b> + <span>%i18n:@click-to-show%</span> + </div> +</div> +<a class="lcjomzwbohoelkxsnuqjiaccdbdfiazy" v-else :href="image.url" @mousemove="onMousemove" @mouseleave="onMouseleave" @@ -21,13 +27,17 @@ export default Vue.extend({ }, raw: { default: false + }, + hide: { + type: Boolean, + default: true } }, computed: { style(): any { return { 'background-color': this.image.properties.avgColor && this.image.properties.avgColor.length == 3 ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent', - 'background-image': this.raw ? `url(${this.image.url})` : `url(${this.image.url}?thumbnail&size=512)` + 'background-image': this.raw ? `url(${this.image.url})` : `url(${this.image.url})` }; } }, @@ -56,16 +66,30 @@ export default Vue.extend({ </script> <style lang="stylus" scoped> -.mk-media-image +.lcjomzwbohoelkxsnuqjiaccdbdfiazy display block cursor zoom-in overflow hidden width 100% height 100% background-position center - border-radius 4px &:not(:hover) background-size cover +.ldwbgwstjsdgcjruamauqdrffetqudry + display flex + justify-content center + align-items center + background #111 + color #fff + + > div + display table-cell + text-align center + font-size 12px + + > b + display block + </style> diff --git a/src/client/app/desktop/views/components/media-video.vue b/src/client/app/desktop/views/components/media-video.vue index 3635941e64..6c60f2da96 100644 --- a/src/client/app/desktop/views/components/media-video.vue +++ b/src/client/app/desktop/views/components/media-video.vue @@ -1,12 +1,19 @@ <template> - <video class="mk-media-video" +<div class="uofhebxjdgksfmltszlxurtjnjjsvioh" v-if="video.isSensitive && hide" @click="hide = false"> + <div> + <b>%fa:exclamation-triangle% %i18n:@sensitive%</b> + <span>%i18n:@click-to-show%</span> + </div> +</div> +<div class="vwxdhznewyashiknzolsoihtlpicqepe" v-else> + <video class="video" :src="video.url" :title="video.name" controls @dblclick.prevent="onClick" ref="video" v-if="inlinePlayable" /> - <a class="mk-media-video-thumbnail" + <a class="thumbnail" :href="video.url" :style="imageStyle" @click.prevent="onClick" @@ -14,6 +21,7 @@ v-else> %fa:R play-circle% </a> +</div> </template> <script lang="ts"> @@ -21,11 +29,23 @@ import Vue from 'vue'; import MkMediaVideoDialog from './media-video-dialog.vue'; export default Vue.extend({ - props: ['video', 'inlinePlayable'], + props: { + video: { + type: Object, + required: true + }, + inlinePlayable: { + default: false + }, + hide: { + type: Boolean, + default: true + } + }, computed: { imageStyle(): any { return { - 'background-image': `url(${this.video.url}?thumbnail&size=512)` + 'background-image': `url(${this.video.url})` }; } }, @@ -47,22 +67,39 @@ export default Vue.extend({ </script> <style lang="stylus" scoped> -.mk-media-video - display block - width 100% - height 100% - border-radius 4px +.vwxdhznewyashiknzolsoihtlpicqepe + .video + display block + width 100% + height 100% + border-radius 4px -.mk-media-video-thumbnail + .thumbnail + display flex + justify-content center + align-items center + font-size 3.5em + + cursor zoom-in + overflow hidden + background-position center + background-size cover + width 100% + height 100% + +.uofhebxjdgksfmltszlxurtjnjjsvioh display flex justify-content center align-items center - font-size 3.5em + background #111 + color #fff + + > div + display table-cell + text-align center + font-size 12px + + > b + display block - cursor zoom-in - overflow hidden - background-position center - background-size cover - width 100% - height 100% </style> diff --git a/src/client/app/desktop/views/components/messaging-room-window.vue b/src/client/app/desktop/views/components/messaging-room-window.vue index cbb58b5e99..41b421b0e7 100644 --- a/src/client/app/desktop/views/components/messaging-room-window.vue +++ b/src/client/app/desktop/views/components/messaging-room-window.vue @@ -8,7 +8,7 @@ <script lang="ts"> import Vue from 'vue'; import { url } from '../../../config'; -import getAcct from '../../../../../acct/render'; +import getAcct from '../../../../../misc/acct/render'; export default Vue.extend({ props: ['user'], diff --git a/src/client/app/desktop/views/components/note-detail.vue b/src/client/app/desktop/views/components/note-detail.vue index e3d16d7056..36a5889220 100644 --- a/src/client/app/desktop/views/components/note-detail.vue +++ b/src/client/app/desktop/views/components/note-detail.vue @@ -46,7 +46,7 @@ <mk-media-list :media-list="p.media" :raw="true"/> </div> <mk-poll v-if="p.poll" :note="p"/> - <mk-url-preview v-for="url in urls" :url="url" :key="url"/> + <mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/> <a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a> <div class="map" v-if="p.geo" ref="map"></div> <div class="renote" v-if="p.renote"> diff --git a/src/client/app/desktop/views/components/notes.note.vue b/src/client/app/desktop/views/components/notes.note.vue index b8aff2d86e..3aa52f75f0 100644 --- a/src/client/app/desktop/views/components/notes.note.vue +++ b/src/client/app/desktop/views/components/notes.note.vue @@ -56,10 +56,10 @@ <button @click="menu" ref="menuButton"> %fa:ellipsis-h% </button> - <button title="%i18n:@detail"> + <!-- <button title="%i18n:@detail"> <template v-if="!isDetailOpened">%fa:caret-down%</template> <template v-if="isDetailOpened">%fa:caret-up%</template> - </button> + </button> --> </footer> </div> </article> diff --git a/src/client/app/desktop/views/components/notes.vue b/src/client/app/desktop/views/components/notes.vue index 1206eb7136..c959508020 100644 --- a/src/client/app/desktop/views/components/notes.vue +++ b/src/client/app/desktop/views/components/notes.vue @@ -34,7 +34,7 @@ <script lang="ts"> import Vue from 'vue'; import { url } from '../../../config'; -import getNoteSummary from '../../../../../renderers/get-note-summary'; +import getNoteSummary from '../../../../../misc/get-note-summary'; import XNote from './notes.note.vue'; diff --git a/src/client/app/desktop/views/components/notifications.vue b/src/client/app/desktop/views/components/notifications.vue index 32b36994db..b291e1f54a 100644 --- a/src/client/app/desktop/views/components/notifications.vue +++ b/src/client/app/desktop/views/components/notifications.vue @@ -110,7 +110,7 @@ <script lang="ts"> import Vue from 'vue'; -import getNoteSummary from '../../../../../renderers/get-note-summary'; +import getNoteSummary from '../../../../../misc/get-note-summary'; export default Vue.extend({ data() { diff --git a/src/client/app/desktop/views/components/post-form.vue b/src/client/app/desktop/views/components/post-form.vue index 3832e5b38c..9b8a0c0f18 100644 --- a/src/client/app/desktop/views/components/post-form.vue +++ b/src/client/app/desktop/views/components/post-form.vue @@ -8,7 +8,11 @@ <div class="content"> <div v-if="visibility == 'specified'" class="visibleUsers"> <span v-for="u in visibleUsers">{{ u | userName }}<a @click="removeVisibleUser(u)">[x]</a></span> - <a @click="addVisibleUser">+ユーザーを追加</a> + <a @click="addVisibleUser">%i18n:@add-visible-user%</a> + </div> + <div class="hashtags" v-if="recentHashtags.length > 0"> + <b>%i18n:@recent-tags%:</b> + <a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)" title="%@click-to-tagging%">#{{ tag }}</a> </div> <input v-show="useCw" v-model="cw" placeholder="内容への注釈 (オプション)"> <textarea :class="{ with: (files.length != 0 || poll) }" @@ -19,7 +23,7 @@ <div class="medias" :class="{ with: poll }" v-show="files.length != 0"> <x-draggable :list="files" :options="{ animation: 150 }"> <div v-for="file in files" :key="file.id"> - <div class="img" :style="{ backgroundImage: `url(${file.url}?thumbnail&size=64)` }" :title="file.name"></div> + <div class="img" :style="{ backgroundImage: `url(${file.url})` }" :title="file.name"></div> <img class="remove" @click="detachMedia(file.id)" src="/assets/desktop/remove.png" title="%i18n:@attach-cancel%" alt=""/> </div> </x-draggable> @@ -32,9 +36,15 @@ <button class="drive" title="%i18n:@attach-media-from-drive%" @click="chooseFileFromDrive">%fa:cloud%</button> <button class="kao" title="%i18n:@insert-a-kao%" @click="kao">%fa:R smile%</button> <button class="poll" title="%i18n:@create-poll%" @click="poll = true">%fa:chart-pie%</button> - <button class="poll" title="内容を隠す" @click="useCw = !useCw">%fa:eye-slash%</button> - <button class="geo" title="位置情報を添付する" @click="geo ? removeGeo() : setGeo()">%fa:map-marker-alt%</button> - <button class="visibility" title="公開範囲" @click="setVisibility" ref="visibilityButton">%fa:lock%</button> + <button class="poll" title="%i18n:@hide-contents%" @click="useCw = !useCw">%fa:eye-slash%</button> + <button class="geo" title="%i18n:@attach-location-information%" @click="geo ? removeGeo() : setGeo()">%fa:map-marker-alt%</button> + <button class="visibility" title="%i18n:@visibility%" @click="setVisibility" ref="visibilityButton"> + <span v-if="visibility === 'public'">%fa:globe%</span> + <span v-if="visibility === 'home'">%fa:home%</span> + <span v-if="visibility === 'followers'">%fa:unlock%</span> + <span v-if="visibility === 'specified'">%fa:envelope%</span> + <span v-if="visibility === 'private'">%fa:lock%</span> + </button> <p class="text-count" :class="{ over: text.length > 1000 }">{{ 1000 - text.length }}</p> <button :class="{ posting }" class="submit" :disabled="!canPost" @click="post"> {{ posting ? '%i18n:@posting%' : submitText }}<mk-ellipsis v-if="posting"/> @@ -46,6 +56,7 @@ <script lang="ts"> import Vue from 'vue'; +import insertTextAtCursor from 'insert-text-at-cursor'; import * as XDraggable from 'vuedraggable'; import getKao from '../../../common/scripts/get-kao'; import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue'; @@ -91,7 +102,8 @@ export default Vue.extend({ visibility: 'public', visibleUsers: [], autocomplete: null, - draghover: false + draghover: false, + recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]') }; }, @@ -131,7 +143,9 @@ export default Vue.extend({ }, canPost(): boolean { - return !this.posting && (this.text.length != 0 || this.files.length != 0 || this.poll || this.renote); + return !this.posting && + (1 <= this.text.length || 1 <= this.files.length || this.poll || this.renote) && + (this.text.trim().length <= 1000); } }, @@ -183,6 +197,10 @@ export default Vue.extend({ }, methods: { + addTag(tag: string) { + insertTextAtCursor(this.$refs.text, ` #${tag} `); + }, + watch() { this.$watch('text', () => this.saveDraft()); this.$watch('poll', () => this.saveDraft()); @@ -235,7 +253,7 @@ export default Vue.extend({ }, onKeydown(e) { - if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey)) this.post(); + if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey) && this.canPost) this.post(); }, onPaste(e) { @@ -287,7 +305,7 @@ export default Vue.extend({ setGeo() { if (navigator.geolocation == null) { - alert('お使いの端末は位置情報に対応していません'); + alert('%i18n:@geolocation-alert%'); return; } @@ -295,10 +313,10 @@ export default Vue.extend({ this.geo = pos.coords; this.$emit('geo-attached', this.geo); }, err => { - alert('エラー: ' + err.message); + alert('%i18n:@error%: ' + err.message); }, { - enableHighAccuracy: true - }); + enableHighAccuracy: true + }); }, removeGeo() { @@ -318,7 +336,7 @@ export default Vue.extend({ addVisibleUser() { (this as any).apis.input({ - title: 'ユーザー名を入力してください' + title: '%i18n:@enter-username%' }).then(username => { (this as any).api('users/show', { username @@ -370,6 +388,12 @@ export default Vue.extend({ }).then(() => { this.posting = false; }); + + if (this.text && this.text != '') { + const hashtags = parse(this.text).filter(x => x.type == 'hashtag').map(x => x.hashtag); + const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[]; + localStorage.setItem('hashtags', JSON.stringify(hashtags.concat(history).reduce((a, c) => a.includes(c) ? a : [...a, c], []))); + } }, saveDraft() { @@ -452,7 +476,7 @@ root(isDark) margin 0 max-width 100% min-width 100% - min-height 64px + min-height 84px &:hover & + * @@ -478,6 +502,19 @@ root(isDark) margin-right 16px color isDark ? #fff : #666 + > .hashtags + margin 0 0 8px 0 + overflow hidden + white-space nowrap + font-size 14px + + > b + color isDark ? #9baec8 : darken($theme-color, 20%) + + > * + margin-right 8px + white-space nowrap + > .medias margin 0 padding 0 diff --git a/src/client/app/desktop/views/components/settings.profile.vue b/src/client/app/desktop/views/components/settings.profile.vue index 0b3a25f389..262583b640 100644 --- a/src/client/app/desktop/views/components/settings.profile.vue +++ b/src/client/app/desktop/views/components/settings.profile.vue @@ -2,7 +2,7 @@ <div class="profile"> <label class="avatar ui from group"> <p>%i18n:@avatar%</p> - <img class="avatar" :src="`${$store.state.i.avatarUrl}?thumbnail&size=64`" alt="avatar"/> + <img class="avatar" :src="$store.state.i.avatarUrl" alt="avatar"/> <button class="ui" @click="updateAvatar">%i18n:@choice-avatar%</button> </label> <label class="ui from group"> @@ -63,7 +63,7 @@ export default Vue.extend({ description: this.description || null, birthday: this.birthday || null }).then(() => { - (this as any).apis.notify('プロフィールを更新しました'); + (this as any).apis.notify('%i18n:@profile-updated%'); }); }, onChangeIsLocked() { diff --git a/src/client/app/desktop/views/components/settings.vue b/src/client/app/desktop/views/components/settings.vue index 74ab45626d..00bd7a8783 100644 --- a/src/client/app/desktop/views/components/settings.vue +++ b/src/client/app/desktop/views/components/settings.vue @@ -410,7 +410,7 @@ export default Vue.extend({ localStorage.clear(); (this as any).apis.dialog({ title: '%i18n:@cache-cleared%', - text: '%i18n:@caache-cleared-desc%' + text: '%i18n:@cache-cleared-desc%' }); }, soundTest() { diff --git a/src/client/app/desktop/views/components/timeline.core.vue b/src/client/app/desktop/views/components/timeline.core.vue index 1728dad286..15e188be67 100644 --- a/src/client/app/desktop/views/components/timeline.core.vue +++ b/src/client/app/desktop/views/components/timeline.core.vue @@ -43,19 +43,21 @@ export default Vue.extend({ }, stream(): any { - return this.src == 'home' - ? (this as any).os.stream - : this.src == 'local' - ? (this as any).os.streams.localTimelineStream - : (this as any).os.streams.globalTimelineStream; + switch (this.src) { + case 'home': return (this as any).os.stream; + case 'local': return (this as any).os.streams.localTimelineStream; + case 'hybrid': return (this as any).os.streams.hybridTimelineStream; + case 'global': return (this as any).os.streams.globalTimelineStream; + } }, endpoint(): string { - return this.src == 'home' - ? 'notes/timeline' - : this.src == 'local' - ? 'notes/local-timeline' - : 'notes/global-timeline'; + switch (this.src) { + case 'home': return 'notes/timeline'; + case 'local': return 'notes/local-timeline'; + case 'hybrid': return 'notes/hybrid-timeline'; + case 'global': return 'notes/global-timeline'; + } }, canFetchMore(): boolean { diff --git a/src/client/app/desktop/views/components/timeline.vue b/src/client/app/desktop/views/components/timeline.vue index 0728b78aa9..52a7753438 100644 --- a/src/client/app/desktop/views/components/timeline.vue +++ b/src/client/app/desktop/views/components/timeline.vue @@ -3,12 +3,14 @@ <header> <span :data-active="src == 'home'" @click="src = 'home'">%fa:home% %i18n:@home%</span> <span :data-active="src == 'local'" @click="src = 'local'">%fa:R comments% %i18n:@local%</span> + <span :data-active="src == 'hybrid'" @click="src = 'hybrid'">%fa:share-alt% %i18n:@hybrid%</span> <span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% %i18n:@global%</span> <span :data-active="src == 'list'" @click="src = 'list'" v-if="list">%fa:list% {{ list.title }}</span> <button @click="chooseList" title="%i18n:@list%">%fa:list%</button> </header> <x-core v-if="src == 'home'" ref="tl" key="home" src="home"/> <x-core v-if="src == 'local'" ref="tl" key="local" src="local"/> + <x-core v-if="src == 'hybrid'" ref="tl" key="hybrid" src="hybrid"/> <x-core v-if="src == 'global'" ref="tl" key="global" src="global"/> <mk-user-list-timeline v-if="src == 'list'" ref="tl" :key="list.id" :list="list"/> </div> @@ -48,7 +50,7 @@ export default Vue.extend({ this.list = this.$store.state.device.tl.arg; } } else if (this.$store.state.i.followingCount == 0) { - this.src = 'local'; + this.src = 'hybrid'; } }, diff --git a/src/client/app/desktop/views/components/ui.header.nav.vue b/src/client/app/desktop/views/components/ui.header.nav.vue index 42211b57fe..f01aade306 100644 --- a/src/client/app/desktop/views/components/ui.header.nav.vue +++ b/src/client/app/desktop/views/components/ui.header.nav.vue @@ -2,13 +2,13 @@ <div class="nav"> <ul> <template v-if="$store.getters.isSignedIn"> - <li class="home" :class="{ active: $route.name == 'index' }"> + <li class="home" :class="{ active: $route.name == 'index' }" @click="goToTop"> <router-link to="/"> %fa:home% <p>%i18n:@home%</p> </router-link> </li> - <li class="deck" :class="{ active: $route.name == 'deck' }"> + <li class="deck" :class="{ active: $route.name == 'deck' }" @click="goToTop"> <router-link to="/deck"> %fa:columns% <p>%i18n:@deck% <small>(beta)</small></p> @@ -82,6 +82,13 @@ export default Vue.extend({ game() { (this as any).os.new(MkGameWindow); + }, + + goToTop() { + window.scrollTo({ + top: 0, + behavior: 'smooth' + }); } } }); diff --git a/src/client/app/desktop/views/components/ui.header.search.vue b/src/client/app/desktop/views/components/ui.header.search.vue index b6149a1878..9a36e52fcc 100644 --- a/src/client/app/desktop/views/components/ui.header.search.vue +++ b/src/client/app/desktop/views/components/ui.header.search.vue @@ -29,9 +29,7 @@ export default Vue.extend({ <style lang="stylus" scoped> @import '~const.styl' - -.search - +root(isDark) > [data-fa] display block position absolute @@ -60,15 +58,20 @@ export default Vue.extend({ border none border-radius 16px transition color 0.5s ease, border 0.5s ease - font-family FontAwesome, sans-serif + color isDark ? #fff : #000 &::placeholder color #9eaba8 &:hover - background rgba(#000, 0.08) + background isDark ? rgba(#fff, 0.04) : rgba(#000, 0.08) &:focus box-shadow 0 0 0 2px rgba($theme-color, 0.5) !important +.search[data-darkmode] + root(true) + +.search:not([data-darkmode]) + root(false) </style> diff --git a/src/client/app/desktop/views/components/ui.header.vue b/src/client/app/desktop/views/components/ui.header.vue index aa7c3ac44d..1ed5c3523b 100644 --- a/src/client/app/desktop/views/components/ui.header.vue +++ b/src/client/app/desktop/views/components/ui.header.vue @@ -9,6 +9,9 @@ <div class="left"> <x-nav/> </div> + <div class="center"> + <div class="icon" @click="goToTop"></div> + </div> <div class="right"> <x-search/> <x-account v-if="$store.getters.isSignedIn"/> @@ -42,6 +45,7 @@ export default Vue.extend({ XPost, XClock, }, + mounted() { this.$store.commit('setUiHeaderHeight', 48); @@ -93,7 +97,16 @@ export default Vue.extend({ }, 2500); } } - } + }, + + methods: { + goToTop() { + window.scrollTo({ + top: 0, + behavior: 'smooth' + }); + } + }, }); </script> @@ -142,26 +155,24 @@ root(isDark) max-width 1300px margin 0 auto - &:before - content "" - position absolute - top 0 - left 0 - display block - width 100% - height 48px - background-image isDark ? url('/assets/desktop/header-icon.dark.svg') : url('/assets/desktop/header-icon.light.svg') - background-size 24px - background-position center - background-repeat no-repeat - opacity 0.3 + > .center + margin auto + + > .icon + display block + width 48px + height 48px + background-image isDark ? url('/assets/desktop/header-icon.dark.svg') : url('/assets/desktop/header-icon.light.svg') + background-size 24px + background-position center + background-repeat no-repeat + opacity 0.3 + cursor pointer > .left - margin 0 auto 0 0 height 48px > .right - margin 0 0 0 auto height 48px > * diff --git a/src/client/app/desktop/views/components/user-preview.vue b/src/client/app/desktop/views/components/user-preview.vue index 788881ead5..aa17890682 100644 --- a/src/client/app/desktop/views/components/user-preview.vue +++ b/src/client/app/desktop/views/components/user-preview.vue @@ -1,7 +1,7 @@ <template> <div class="mk-user-preview"> <template v-if="u != null"> - <div class="banner" :style="u.bannerUrl ? `background-image: url(${u.bannerUrl}?thumbnail&size=512)` : ''"></div> + <div class="banner" :style="u.bannerUrl ? `background-image: url(${u.bannerUrl})` : ''"></div> <mk-avatar class="avatar" :user="u" :disable-preview="true"/> <div class="title"> <router-link class="name" :to="u | userPage">{{ u | userName }}</router-link> @@ -19,7 +19,7 @@ <p>%i18n:@followers%</p><a>{{ u.followersCount }}</a> </div> </div> - <mk-follow-button v-if="$store.getters.isSignedIn && user.id != $store.state.i.id" :user="u"/> + <mk-follow-button v-if="$store.getters.isSignedIn && u.id != $store.state.i.id" :user="u"/> </template> </div> </template> @@ -27,7 +27,7 @@ <script lang="ts"> import Vue from 'vue'; import * as anime from 'animejs'; -import parseAcct from '../../../../../acct/parse'; +import parseAcct from '../../../../../misc/acct/parse'; export default Vue.extend({ props: { diff --git a/src/client/app/desktop/views/pages/deck/deck.column-core.vue b/src/client/app/desktop/views/pages/deck/deck.column-core.vue index 28e7f13650..7f219c0be1 100644 --- a/src/client/app/desktop/views/pages/deck/deck.column-core.vue +++ b/src/client/app/desktop/views/pages/deck/deck.column-core.vue @@ -3,6 +3,7 @@ <x-notifications-column v-else-if="column.type == 'notifications'" :column="column" :is-stacked="isStacked"/> <x-tl-column v-else-if="column.type == 'home'" :column="column" :is-stacked="isStacked"/> <x-tl-column v-else-if="column.type == 'local'" :column="column" :is-stacked="isStacked"/> +<x-tl-column v-else-if="column.type == 'hybrid'" :column="column" :is-stacked="isStacked"/> <x-tl-column v-else-if="column.type == 'global'" :column="column" :is-stacked="isStacked"/> <x-tl-column v-else-if="column.type == 'list'" :column="column" :is-stacked="isStacked"/> </template> diff --git a/src/client/app/desktop/views/pages/deck/deck.notification.vue b/src/client/app/desktop/views/pages/deck/deck.notification.vue index a379adc69e..d0093ff282 100644 --- a/src/client/app/desktop/views/pages/deck/deck.notification.vue +++ b/src/client/app/desktop/views/pages/deck/deck.notification.vue @@ -81,7 +81,7 @@ <script lang="ts"> import Vue from 'vue'; -import getNoteSummary from '../../../../../../renderers/get-note-summary'; +import getNoteSummary from '../../../../../../misc/get-note-summary'; import XNote from './deck.note.vue'; export default Vue.extend({ diff --git a/src/client/app/desktop/views/pages/deck/deck.tl-column.vue b/src/client/app/desktop/views/pages/deck/deck.tl-column.vue index ffe1da670b..231b505f5d 100644 --- a/src/client/app/desktop/views/pages/deck/deck.tl-column.vue +++ b/src/client/app/desktop/views/pages/deck/deck.tl-column.vue @@ -3,6 +3,7 @@ <span slot="header"> <template v-if="column.type == 'home'">%fa:home%</template> <template v-if="column.type == 'local'">%fa:R comments%</template> + <template v-if="column.type == 'hybrid'">%fa:share-alt%</template> <template v-if="column.type == 'global'">%fa:globe%</template> <template v-if="column.type == 'list'">%fa:list%</template> <span>{{ name }}</span> @@ -61,6 +62,7 @@ export default Vue.extend({ switch (this.column.type) { case 'home': return '%i18n:common.deck.home%'; case 'local': return '%i18n:common.deck.local%'; + case 'hybrid': return '%i18n:common.deck.hybrid%'; case 'global': return '%i18n:common.deck.global%'; case 'list': return this.column.list.title; } diff --git a/src/client/app/desktop/views/pages/deck/deck.tl.vue b/src/client/app/desktop/views/pages/deck/deck.tl.vue index 8e05f09c5d..d402ee6a8b 100644 --- a/src/client/app/desktop/views/pages/deck/deck.tl.vue +++ b/src/client/app/desktop/views/pages/deck/deck.tl.vue @@ -41,27 +41,29 @@ export default Vue.extend({ }; }, - watch: { - mediaOnly() { - this.fetch(); - } - }, - computed: { stream(): any { - return this.src == 'home' - ? (this as any).os.stream - : this.src == 'local' - ? (this as any).os.streams.localTimelineStream - : (this as any).os.streams.globalTimelineStream; + switch (this.src) { + case 'home': return (this as any).os.stream; + case 'local': return (this as any).os.streams.localTimelineStream; + case 'hybrid': return (this as any).os.streams.hybridTimelineStream; + case 'global': return (this as any).os.streams.globalTimelineStream; + } }, endpoint(): string { - return this.src == 'home' - ? 'notes/timeline' - : this.src == 'local' - ? 'notes/local-timeline' - : 'notes/global-timeline'; + switch (this.src) { + case 'home': return 'notes/timeline'; + case 'local': return 'notes/local-timeline'; + case 'hybrid': return 'notes/hybrid-timeline'; + case 'global': return 'notes/global-timeline'; + } + }, + }, + + watch: { + mediaOnly() { + this.fetch(); } }, diff --git a/src/client/app/desktop/views/pages/deck/deck.vue b/src/client/app/desktop/views/pages/deck/deck.vue index da4acb8cca..26b989656e 100644 --- a/src/client/app/desktop/views/pages/deck/deck.vue +++ b/src/client/app/desktop/views/pages/deck/deck.vue @@ -119,6 +119,15 @@ export default Vue.extend({ type: 'local' }); } + }, { + icon: '%fa:share-alt%', + text: '%i18n:common.deck.hybrid%', + action: () => { + this.$store.dispatch('settings/addDeckColumn', { + id: uuid(), + type: 'hybrid' + }); + } }, { icon: '%fa:globe%', text: '%i18n:common.deck.global%', diff --git a/src/client/app/desktop/views/pages/favorites.vue b/src/client/app/desktop/views/pages/favorites.vue index 8adb9412f2..d3bb70f037 100644 --- a/src/client/app/desktop/views/pages/favorites.vue +++ b/src/client/app/desktop/views/pages/favorites.vue @@ -48,7 +48,7 @@ export default Vue.extend({ this.moreFetching = true; (this as any).api('i/favorites', { limit: 11, - maxId: this.favorites[this.favorites.length - 1].id + untilId: this.favorites[this.favorites.length - 1].id }).then(favorites => { if (favorites.length == 11) { this.existMore = true; diff --git a/src/client/app/desktop/views/pages/messaging-room.vue b/src/client/app/desktop/views/pages/messaging-room.vue index 06c32776c9..1ebd53cef4 100644 --- a/src/client/app/desktop/views/pages/messaging-room.vue +++ b/src/client/app/desktop/views/pages/messaging-room.vue @@ -7,8 +7,8 @@ <script lang="ts"> import Vue from 'vue'; import Progress from '../../../common/scripts/loading'; -import parseAcct from '../../../../../acct/parse'; -import getUserName from '../../../../../renderers/get-user-name'; +import parseAcct from '../../../../../misc/acct/parse'; +import getUserName from '../../../../../misc/get-user-name'; export default Vue.extend({ data() { diff --git a/src/client/app/desktop/views/pages/reversi.vue b/src/client/app/desktop/views/pages/reversi.vue index 098fc41f1c..b484b81b5d 100644 --- a/src/client/app/desktop/views/pages/reversi.vue +++ b/src/client/app/desktop/views/pages/reversi.vue @@ -33,7 +33,7 @@ export default Vue.extend({ Progress.start(); this.fetching = true; - (this as any).api('reversi/games/show', { + (this as any).api('games/reversi/games/show', { gameId: this.$route.params.game }).then(game => { this.game = game; diff --git a/src/client/app/desktop/views/pages/search.vue b/src/client/app/desktop/views/pages/search.vue index e79ac1c739..2576c26cb1 100644 --- a/src/client/app/desktop/views/pages/search.vue +++ b/src/client/app/desktop/views/pages/search.vue @@ -6,20 +6,15 @@ <div :class="$style.loading" v-if="fetching"> <mk-ellipsis-icon/> </div> + <p :class="$style.notAvailable" v-if="!fetching && notAvailable">検索機能を利用することができません。</p> <p :class="$style.empty" v-if="!fetching && empty">%fa:search%「{{ q }}」に関する投稿は見つかりませんでした。</p> - <mk-notes ref="timeline" :class="$style.notes" :notes="notes"> - <div slot="footer"> - <template v-if="!moreFetching">%fa:search%</template> - <template v-if="moreFetching">%fa:spinner .pulse .fw%</template> - </div> - </mk-notes> + <mk-notes ref="timeline" :class="$style.notes" :more="existMore ? more : null"/> </mk-ui> </template> <script lang="ts"> import Vue from 'vue'; import Progress from '../../../common/scripts/loading'; -import parse from '../../../common/scripts/parse-search-query'; const limit = 20; @@ -30,16 +25,14 @@ export default Vue.extend({ moreFetching: false, existMore: false, offset: 0, - notes: [] + empty: false, + notAvailable: false }; }, watch: { $route: 'fetch' }, computed: { - empty(): boolean { - return this.notes.length == 0; - }, q(): string { return this.$route.query.q; } @@ -66,39 +59,47 @@ export default Vue.extend({ this.fetching = true; Progress.start(); - (this as any).api('notes/search', Object.assign({ - limit: limit + 1, - offset: this.offset - }, parse(this.q))).then(notes => { - if (notes.length == limit + 1) { - notes.pop(); - this.existMore = true; - } - this.notes = notes; - this.fetching = false; - Progress.done(); - }); + (this.$refs.timeline as any).init(() => new Promise((res, rej) => { + (this as any).api('notes/search', { + limit: limit + 1, + offset: this.offset, + query: this.q + }).then(notes => { + if (notes.length == 0) this.empty = true; + if (notes.length == limit + 1) { + notes.pop(); + this.existMore = true; + } + res(notes); + this.fetching = false; + Progress.done(); + }, (e: string) => { + this.fetching = false; + Progress.done(); + if (e === 'searching not available') this.notAvailable = true; + }); + })); }, more() { - if (this.moreFetching || this.fetching || this.notes.length == 0 || !this.existMore) return; this.offset += limit; - this.moreFetching = true; - return (this as any).api('notes/search', Object.assign({ + + const promise = (this as any).api('notes/search', { limit: limit + 1, - offset: this.offset - }, parse(this.q))).then(notes => { + offset: this.offset, + query: this.q + }); + + promise.then(notes => { if (notes.length == limit + 1) { notes.pop(); } else { this.existMore = false; } - this.notes = this.notes.concat(notes); + notes.forEach(n => (this.$refs.timeline as any).append(n)); this.moreFetching = false; }); - }, - onScroll() { - const current = window.scrollY + window.innerHeight; - if (current > document.body.offsetHeight - 16) this.more(); + + return promise; } } }); @@ -135,4 +136,18 @@ export default Vue.extend({ font-size 3em color #ccc + +.notAvailable + display block + margin 0 auto + padding 32px + max-width 400px + text-align center + color #999 + + > [data-fa] + display block + margin-bottom 16px + font-size 3em + color #ccc </style> diff --git a/src/client/app/desktop/views/pages/user-list.users.vue b/src/client/app/desktop/views/pages/user-list.users.vue index 517fe89750..7d9a4606a1 100644 --- a/src/client/app/desktop/views/pages/user-list.users.vue +++ b/src/client/app/desktop/views/pages/user-list.users.vue @@ -49,7 +49,8 @@ export default Vue.extend({ add() { (this as any).apis.input({ title: '%i18n:@username%', - }).then(async username => { + }).then(async (username: string) => { + if (username.startsWith('@')) username = username.slice(1); const user = await (this as any).api('users/show', { username }); diff --git a/src/client/app/desktop/views/pages/user/user.followers-you-know.vue b/src/client/app/desktop/views/pages/user/user.followers-you-know.vue index 4c1b91e7a6..e4a771910a 100644 --- a/src/client/app/desktop/views/pages/user/user.followers-you-know.vue +++ b/src/client/app/desktop/views/pages/user/user.followers-you-know.vue @@ -4,7 +4,7 @@ <p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:@loading%<mk-ellipsis/></p> <div v-if="!fetching && users.length > 0"> <router-link v-for="user in users" :to="user | userPage" :key="user.id"> - <img :src="`${user.avatarUrl}?thumbnail&size=64`" :alt="user | userName" v-user-preview="user.id"/> + <img :src="user.avatarUrl" :alt="user | userName" v-user-preview="user.id"/> </router-link> </div> <p class="empty" v-if="!fetching && users.length == 0">%i18n:@no-users%</p> diff --git a/src/client/app/desktop/views/pages/user/user.photos.vue b/src/client/app/desktop/views/pages/user/user.photos.vue index 01c4c7b31e..ce7791a96b 100644 --- a/src/client/app/desktop/views/pages/user/user.photos.vue +++ b/src/client/app/desktop/views/pages/user/user.photos.vue @@ -4,7 +4,7 @@ <p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:@loading%<mk-ellipsis/></p> <div class="stream" v-if="!fetching && images.length > 0"> <div v-for="image in images" class="img" - :style="`background-image: url(${image.url}?thumbnail&size=256)`" + :style="`background-image: url(${image.url})`" ></div> </div> <p class="empty" v-if="!fetching && images.length == 0">%i18n:@no-photos%</p> diff --git a/src/client/app/desktop/views/pages/user/user.profile.vue b/src/client/app/desktop/views/pages/user/user.profile.vue index 0134d6f0be..b74dbc7e25 100644 --- a/src/client/app/desktop/views/pages/user/user.profile.vue +++ b/src/client/app/desktop/views/pages/user/user.profile.vue @@ -1,6 +1,6 @@ <template> -<div class="profile"> - <div class="friend-form" v-if="$store.getters.isSignedIn && $store.state.i.id != user.id"> +<div class="profile" v-if="$store.getters.isSignedIn"> + <div class="friend-form" v-if="$store.state.i.id != user.id"> <mk-follow-button :user="user" size="big"/> <p class="followed" v-if="user.isFollowed">%i18n:@follows-you%</p> <p class="stalk" v-if="user.isFollowing"> @@ -9,7 +9,7 @@ </p> </div> <div class="action-form"> - <button class="mute ui" @click="user.isMuted ? unmute() : mute()"> + <button class="mute ui" @click="user.isMuted ? unmute() : mute()" v-if="$store.state.i.id != user.id"> <span v-if="user.isMuted">%fa:eye% %i18n:@unmute%</span> <span v-if="!user.isMuted">%fa:eye-slash% %i18n:@mute%</span> </button> diff --git a/src/client/app/desktop/views/pages/user/user.vue b/src/client/app/desktop/views/pages/user/user.vue index fc5c900037..64a4eaa872 100644 --- a/src/client/app/desktop/views/pages/user/user.vue +++ b/src/client/app/desktop/views/pages/user/user.vue @@ -27,8 +27,8 @@ <script lang="ts"> import Vue from 'vue'; -import parseAcct from '../../../../../../acct/parse'; -import getUserName from '../../../../../../renderers/get-user-name'; +import parseAcct from '../../../../../../misc/acct/parse'; +import getUserName from '../../../../../../misc/get-user-name'; import Progress from '../../../../common/scripts/loading'; import XHeader from './user.header.vue'; import XTimeline from './user.timeline.vue'; diff --git a/src/client/app/desktop/views/widgets/notifications.vue b/src/client/app/desktop/views/widgets/notifications.vue index f75a091480..b44261d7c4 100644 --- a/src/client/app/desktop/views/widgets/notifications.vue +++ b/src/client/app/desktop/views/widgets/notifications.vue @@ -2,7 +2,7 @@ <div class="mkw-notifications"> <mk-widget-container :show-header="!props.compact"> <template slot="header">%fa:R bell%%i18n:@title%</template> - <button slot="func" title="%i18n:@settings%" @click="settings">%fa:cog%</button> + <!-- <button slot="func" title="%i18n:@settings%" @click="settings">%fa:cog%</button> --> <mk-notifications :class="$style.notifications"/> </mk-widget-container> diff --git a/src/client/app/desktop/views/widgets/post-form.vue b/src/client/app/desktop/views/widgets/post-form.vue index 3c4ade0e81..618d19efc4 100644 --- a/src/client/app/desktop/views/widgets/post-form.vue +++ b/src/client/app/desktop/views/widgets/post-form.vue @@ -45,7 +45,7 @@ export default define({ this.save(); }, onKeydown(e) { - if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey)) this.post(); + if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey) && !this.posting && this.text) this.post(); }, post() { this.posting = true; diff --git a/src/client/app/desktop/views/widgets/profile.vue b/src/client/app/desktop/views/widgets/profile.vue index 7b0fea3729..9702aaa90a 100644 --- a/src/client/app/desktop/views/widgets/profile.vue +++ b/src/client/app/desktop/views/widgets/profile.vue @@ -4,7 +4,7 @@ :data-melt="props.design == 2" > <div class="banner" - :style="$store.state.i.bannerUrl ? `background-image: url(${$store.state.i.bannerUrl}?thumbnail&size=256)` : ''" + :style="$store.state.i.bannerUrl ? `background-image: url(${$store.state.i.bannerUrl})` : ''" title="%i18n:@update-banner%" @click="os.apis.updateBanner" ></div> diff --git a/src/client/app/mios.ts b/src/client/app/mios.ts index 9a8d19adbd..565c8bf1f5 100644 --- a/src/client/app/mios.ts +++ b/src/client/app/mios.ts @@ -11,10 +11,11 @@ import { DriveStreamManager } from './common/scripts/streaming/drive'; import { ServerStatsStreamManager } from './common/scripts/streaming/server-stats'; import { NotesStatsStreamManager } from './common/scripts/streaming/notes-stats'; import { MessagingIndexStreamManager } from './common/scripts/streaming/messaging-index'; -import { ReversiStreamManager } from './common/scripts/streaming/reversi'; +import { ReversiStreamManager } from './common/scripts/streaming/games/reversi/reversi'; import Err from './common/views/components/connect-failed.vue'; import { LocalTimelineStreamManager } from './common/scripts/streaming/local-timeline'; +import { HybridTimelineStreamManager } from './common/scripts/streaming/hybrid-timeline'; import { GlobalTimelineStreamManager } from './common/scripts/streaming/global-timeline'; //#region api requests @@ -103,6 +104,7 @@ export default class MiOS extends EventEmitter { */ public streams: { localTimelineStream: LocalTimelineStreamManager; + hybridTimelineStream: HybridTimelineStreamManager; globalTimelineStream: GlobalTimelineStreamManager; driveStream: DriveStreamManager; serverStatsStream: ServerStatsStreamManager; @@ -111,6 +113,7 @@ export default class MiOS extends EventEmitter { reversiStream: ReversiStreamManager; } = { localTimelineStream: null, + hybridTimelineStream: null, globalTimelineStream: null, driveStream: null, serverStatsStream: null, @@ -230,6 +233,7 @@ export default class MiOS extends EventEmitter { // Init other stream manager this.streams.localTimelineStream = new LocalTimelineStreamManager(this, this.store.state.i); + this.streams.hybridTimelineStream = new HybridTimelineStreamManager(this, this.store.state.i); this.streams.globalTimelineStream = new GlobalTimelineStreamManager(this, this.store.state.i); this.streams.driveStream = new DriveStreamManager(this, this.store.state.i); this.streams.messagingIndexStream = new MessagingIndexStreamManager(this, this.store.state.i); diff --git a/src/client/app/mobile/views/components/drive.file.vue b/src/client/app/mobile/views/components/drive.file.vue index 94c8ae3535..776e11ecf8 100644 --- a/src/client/app/mobile/views/components/drive.file.vue +++ b/src/client/app/mobile/views/components/drive.file.vue @@ -43,7 +43,7 @@ export default Vue.extend({ thumbnail(): any { return { 'background-color': this.file.properties.avgColor && this.file.properties.avgColor.length == 3 ? `rgb(${this.file.properties.avgColor.join(',')})` : 'transparent', - 'background-image': `url(${this.file.url}?thumbnail&size=128)` + 'background-image': `url(${this.file.url})` }; } }, diff --git a/src/client/app/mobile/views/components/media-image.vue b/src/client/app/mobile/views/components/media-image.vue index c2f9c66e84..d9d68fa7ba 100644 --- a/src/client/app/mobile/views/components/media-image.vue +++ b/src/client/app/mobile/views/components/media-image.vue @@ -1,5 +1,11 @@ <template> -<a class="mk-media-image" :href="image.url" target="_blank" :style="style" :title="image.name"></a> +<div class="qjewsnkgzzxlxtzncydssfbgjibiehcy" v-if="image.isSensitive && hide" @click="hide = false"> + <div> + <b>%fa:exclamation-triangle% %i18n:@sensitive%</b> + <span>%i18n:@click-to-show%</span> + </div> +</div> +<a class="gqnyydlzavusgskkfvwvjiattxdzsqlf" v-else :href="image.url" target="_blank" :style="style" :title="image.name"></a> </template> <script lang="ts"> @@ -13,11 +19,15 @@ export default Vue.extend({ }, raw: { default: false + }, + hide: { + type: Boolean, + default: true } }, computed: { style(): any { - let url = `url(${this.image.url}?thumbnail)`; + let url = `url(${this.image.url})`; if (this.$store.state.device.loadRemoteMedia || this.$store.state.device.lightmode) { url = null; @@ -35,13 +45,27 @@ export default Vue.extend({ </script> <style lang="stylus" scoped> -.mk-media-image +.gqnyydlzavusgskkfvwvjiattxdzsqlf display block overflow hidden width 100% height 100% background-position center background-size cover - border-radius 4px + +.qjewsnkgzzxlxtzncydssfbgjibiehcy + display flex + justify-content center + align-items center + background #111 + color #fff + + > div + display table-cell + text-align center + font-size 12px + + > b + display block </style> diff --git a/src/client/app/mobile/views/components/media-video.vue b/src/client/app/mobile/views/components/media-video.vue index 68cd48587a..aea7f41460 100644 --- a/src/client/app/mobile/views/components/media-video.vue +++ b/src/client/app/mobile/views/components/media-video.vue @@ -1,28 +1,43 @@ <template> - <a class="mk-media-video" - :href="video.url" - target="_blank" - :style="imageStyle" - :title="video.name"> - %fa:R play-circle% - </a> +<div class="icozogqfvdetwohsdglrbswgrejoxbdj" v-if="video.isSensitive && hide" @click="hide = false"> + <div> + <b>%fa:exclamation-triangle% %i18n:@sensitive%</b> + <span>%i18n:@click-to-show%</span> + </div> +</div> +<a class="kkjnbbplepmiyuadieoenjgutgcmtsvu" v-else + :href="video.url" + target="_blank" + :style="imageStyle" + :title="video.name"> + %fa:R play-circle% +</a> </template> <script lang="ts"> import Vue from 'vue' export default Vue.extend({ - props: ['video'], + props: { + video: { + type: Object, + required: true + }, + hide: { + type: Boolean, + default: true + } + }, computed: { imageStyle(): any { return { - 'background-image': `url(${this.video.url}?thumbnail&size=512)` + 'background-image': `url(${this.video.url})` }; } },}) </script> <style lang="stylus" scoped> -.mk-media-video +.kkjnbbplepmiyuadieoenjgutgcmtsvu display flex justify-content center align-items center @@ -33,4 +48,20 @@ export default Vue.extend({ background-size cover width 100% height 100% + +.icozogqfvdetwohsdglrbswgrejoxbdj + display flex + justify-content center + align-items center + background #111 + color #fff + + > div + display table-cell + text-align center + font-size 12px + + > b + display block + </style> diff --git a/src/client/app/mobile/views/components/note-card.vue b/src/client/app/mobile/views/components/note-card.vue index 89700b5e82..e8427798cd 100644 --- a/src/client/app/mobile/views/components/note-card.vue +++ b/src/client/app/mobile/views/components/note-card.vue @@ -2,7 +2,7 @@ <div class="mk-note-card"> <a :href="note | notePage"> <header> - <img :src="`${note.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/><h3>{{ note.user | userName }}</h3> + <img :src="note.user.avatarUrl" alt="avatar"/><h3>{{ note.user | userName }}</h3> </header> <div> {{ text }} @@ -14,7 +14,7 @@ <script lang="ts"> import Vue from 'vue'; -import summary from '../../../../../renderers/get-note-summary'; +import summary from '../../../../../misc/get-note-summary'; export default Vue.extend({ props: ['note'], diff --git a/src/client/app/mobile/views/components/note-detail.vue b/src/client/app/mobile/views/components/note-detail.vue index fa15922183..317f08dcfa 100644 --- a/src/client/app/mobile/views/components/note-detail.vue +++ b/src/client/app/mobile/views/components/note-detail.vue @@ -44,7 +44,7 @@ <mk-media-list :media-list="p.media" :raw="true"/> </div> <mk-poll v-if="p.poll" :note="p"/> - <mk-url-preview v-for="url in urls" :url="url" :key="url"/> + <mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/> <a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a> <div class="map" v-if="p.geo" ref="map"></div> <div class="renote" v-if="p.renote"> diff --git a/src/client/app/mobile/views/components/notes.vue b/src/client/app/mobile/views/components/notes.vue index 06d22c7258..01f3d76c74 100644 --- a/src/client/app/mobile/views/components/notes.vue +++ b/src/client/app/mobile/views/components/notes.vue @@ -37,7 +37,7 @@ <script lang="ts"> import Vue from 'vue'; -import getNoteSummary from '../../../../../renderers/get-note-summary'; +import getNoteSummary from '../../../../../misc/get-note-summary'; const displayLimit = 30; diff --git a/src/client/app/mobile/views/components/notification-preview.vue b/src/client/app/mobile/views/components/notification-preview.vue index 5e2306932b..be2c7a60ed 100644 --- a/src/client/app/mobile/views/components/notification-preview.vue +++ b/src/client/app/mobile/views/components/notification-preview.vue @@ -66,7 +66,7 @@ <script lang="ts"> import Vue from 'vue'; -import getNoteSummary from '../../../../../renderers/get-note-summary'; +import getNoteSummary from '../../../../../misc/get-note-summary'; export default Vue.extend({ props: ['notification'], diff --git a/src/client/app/mobile/views/components/notification.vue b/src/client/app/mobile/views/components/notification.vue index bbcae05f10..ee90c6b46b 100644 --- a/src/client/app/mobile/views/components/notification.vue +++ b/src/client/app/mobile/views/components/notification.vue @@ -81,7 +81,7 @@ <script lang="ts"> import Vue from 'vue'; -import getNoteSummary from '../../../../../renderers/get-note-summary'; +import getNoteSummary from '../../../../../misc/get-note-summary'; export default Vue.extend({ props: ['notification'], diff --git a/src/client/app/mobile/views/components/post-form.vue b/src/client/app/mobile/views/components/post-form.vue index 1015a44115..1c71d0d46f 100644 --- a/src/client/app/mobile/views/components/post-form.vue +++ b/src/client/app/mobile/views/components/post-form.vue @@ -1,47 +1,59 @@ <template> <div class="mk-post-form"> - <header> - <button class="cancel" @click="cancel">%fa:times%</button> - <div> - <span class="text-count" :class="{ over: text.length > 1000 }">{{ 1000 - text.length }}</span> - <span class="geo" v-if="geo">%fa:map-marker-alt%</span> - <button class="submit" :disabled="!canPost" @click="post">{{ submitText }}</button> - </div> - </header> <div class="form"> - <mk-note-preview v-if="reply" :note="reply"/> - <mk-note-preview v-if="renote" :note="renote"/> - <div v-if="visibility == 'specified'" class="visibleUsers"> - <span v-for="u in visibleUsers">{{ u | userName }}<a @click="removeVisibleUser(u)">[x]</a></span> - <a @click="addVisibleUser">+%i18n:@add-visible-user%</a> + <header> + <button class="cancel" @click="cancel">%fa:times%</button> + <div> + <span class="text-count" :class="{ over: text.length > 1000 }">{{ 1000 - text.length }}</span> + <span class="geo" v-if="geo">%fa:map-marker-alt%</span> + <button class="submit" :disabled="!canPost" @click="post">{{ submitText }}</button> + </div> + </header> + <div class="form"> + <mk-note-preview v-if="reply" :note="reply"/> + <mk-note-preview v-if="renote" :note="renote"/> + <div v-if="visibility == 'specified'" class="visibleUsers"> + <span v-for="u in visibleUsers">{{ u | userName }}<a @click="removeVisibleUser(u)">[x]</a></span> + <a @click="addVisibleUser">+%i18n:@add-visible-user%</a> + </div> + <input v-show="useCw" v-model="cw" placeholder="%i18n:@cw-placeholder%"> + <textarea v-model="text" ref="text" :disabled="posting" :placeholder="placeholder" v-autocomplete="'text'"></textarea> + <div class="attaches" v-show="files.length != 0"> + <x-draggable class="files" :list="files" :options="{ animation: 150 }"> + <div class="file" v-for="file in files" :key="file.id"> + <div class="img" :style="`background-image: url(${file.url})`" @click="detachMedia(file)"></div> + </div> + </x-draggable> + </div> + <mk-poll-editor v-if="poll" ref="poll" @destroyed="poll = false"/> + <mk-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/> + <footer> + <button class="upload" @click="chooseFile">%fa:upload%</button> + <button class="drive" @click="chooseFileFromDrive">%fa:cloud%</button> + <button class="kao" @click="kao">%fa:R smile%</button> + <button class="poll" @click="poll = true">%fa:chart-pie%</button> + <button class="poll" @click="useCw = !useCw">%fa:eye-slash%</button> + <button class="geo" @click="geo ? removeGeo() : setGeo()">%fa:map-marker-alt%</button> + <button class="visibility" @click="setVisibility" ref="visibilityButton"> + <span v-if="visibility === 'public'">%fa:globe%</span> + <span v-if="visibility === 'home'">%fa:home%</span> + <span v-if="visibility === 'followers'">%fa:unlock%</span> + <span v-if="visibility === 'specified'">%fa:envelope%</span> + <span v-if="visibility === 'private'">%fa:lock%</span> + </button> + </footer> + <input ref="file" class="file" type="file" accept="image/*" multiple="multiple" @change="onChangeFile"/> </div> - <input v-show="useCw" v-model="cw" placeholder="%i18n:@cw-placeholder%"> - <textarea v-model="text" ref="text" :disabled="posting" :placeholder="placeholder"></textarea> - <div class="attaches" v-show="files.length != 0"> - <x-draggable class="files" :list="files" :options="{ animation: 150 }"> - <div class="file" v-for="file in files" :key="file.id"> - <div class="img" :style="`background-image: url(${file.url}?thumbnail&size=128)`" @click="detachMedia(file)"></div> - </div> - </x-draggable> - </div> - <mk-poll-editor v-if="poll" ref="poll" @destroyed="poll = false"/> - <mk-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/> - <footer> - <button class="upload" @click="chooseFile">%fa:upload%</button> - <button class="drive" @click="chooseFileFromDrive">%fa:cloud%</button> - <button class="kao" @click="kao">%fa:R smile%</button> - <button class="poll" @click="poll = true">%fa:chart-pie%</button> - <button class="poll" @click="useCw = !useCw">%fa:eye-slash%</button> - <button class="geo" @click="geo ? removeGeo() : setGeo()">%fa:map-marker-alt%</button> - <button class="visibility" @click="setVisibility" ref="visibilityButton">%fa:lock%</button> - </footer> - <input ref="file" class="file" type="file" accept="image/*" multiple="multiple" @change="onChangeFile"/> + </div> + <div class="hashtags" v-if="recentHashtags.length > 0"> + <a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)">#{{ tag }}</a> </div> </div> </template> <script lang="ts"> import Vue from 'vue'; +import insertTextAtCursor from 'insert-text-at-cursor'; import * as XDraggable from 'vuedraggable'; import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue'; import getKao from '../../../common/scripts/get-kao'; @@ -85,7 +97,8 @@ export default Vue.extend({ visibility: 'public', visibleUsers: [], useCw: false, - cw: null + cw: null, + recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]') }; }, @@ -125,7 +138,9 @@ export default Vue.extend({ }, canPost(): boolean { - return !this.posting && (this.text.length != 0 || this.files.length != 0 || this.poll || this.renote); + return !this.posting && + (1 <= this.text.length || 1 <= this.files.length || this.poll || this.renote) && + (this.text.trim().length <= 1000); } }, @@ -161,6 +176,10 @@ export default Vue.extend({ }, methods: { + addTag(tag: string) { + insertTextAtCursor(this.$refs.text, ` #${tag} `); + }, + focus() { (this.$refs.text as any).focus(); }, @@ -210,8 +229,8 @@ export default Vue.extend({ }, err => { alert('%i18n:@error%: ' + err.message); }, { - enableHighAccuracy: true - }); + enableHighAccuracy: true + }); }, removeGeo() { @@ -281,6 +300,12 @@ export default Vue.extend({ }).catch(err => { this.posting = false; }); + + if (this.text && this.text != '') { + const hashtags = parse(this.text).filter(x => x.type == 'hashtag').map(x => x.hashtag); + const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[]; + localStorage.setItem('hashtags', JSON.stringify(hashtags.concat(history).reduce((a, c) => a.includes(c) ? a : [...a, c], []))); + } }, cancel() { @@ -302,146 +327,156 @@ root(isDark) max-width 500px width calc(100% - 16px) margin 8px auto - background isDark ? #282C37 : #fff - border-radius 8px - box-shadow 0 0 2px rgba(#000, 0.1) @media (min-width 500px) margin 16px auto width calc(100% - 32px) - box-shadow 0 8px 32px rgba(#000, 0.1) + + > .form + box-shadow 0 8px 32px rgba(#000, 0.1) @media (min-width 600px) margin 32px auto - > header - z-index 1000 - height 50px - box-shadow 0 1px 0 0 isDark ? rgba(#000, 0.2) : rgba(#000, 0.1) - - > .cancel - padding 0 - width 50px - line-height 50px - font-size 24px - color isDark ? #9baec8 : #555 - - > div - position absolute - top 0 - right 0 - color #657786 - - > .text-count - line-height 50px - - > .geo - margin 0 8px - line-height 50px - - > .submit - margin 8px - padding 0 16px - line-height 34px - vertical-align bottom - color $theme-color-foreground - background $theme-color - border-radius 4px - - &:disabled - opacity 0.7 - > .form - max-width 500px - margin 0 auto + background isDark ? #282C37 : #fff + border-radius 8px + box-shadow 0 0 2px rgba(#000, 0.1) - > .mk-note-preview - padding 16px - - > .visibleUsers - margin-bottom 8px - font-size 14px - - > span - margin-right 16px - color isDark ? #fff : #666 - - > input - z-index 1 - - > input - > textarea - display block - padding 12px - margin 0 - width 100% - font-size 16px - color isDark ? #fff : #333 - background isDark ? #191d23 : #fff - border none - border-radius 0 + > header + z-index 1000 + height 50px box-shadow 0 1px 0 0 isDark ? rgba(#000, 0.2) : rgba(#000, 0.1) - &:disabled - opacity 0.5 - - > textarea - max-width 100% - min-width 100% - min-height 80px - - > .attaches - - > .files - display block - margin 0 - padding 4px - list-style none - - &:after - content "" - display block - clear both - - > .file - display block - float left - margin 0 - padding 0 - border solid 4px transparent - - > .img - width 64px - height 64px - background-size cover - background-position center center - - > .mk-uploader - margin 8px 0 0 0 - padding 8px - - > .file - display none - - > footer - white-space nowrap - overflow auto - -webkit-overflow-scrolling touch - overflow-scrolling touch - - > * - display inline-block + > .cancel padding 0 - margin 0 - width 48px - height 48px - font-size 20px + width 50px + line-height 50px + font-size 24px + color isDark ? #9baec8 : #555 + + > div + position absolute + top 0 + right 0 color #657786 - background transparent - outline none + + > .text-count + line-height 50px + + > .geo + margin 0 8px + line-height 50px + + > .submit + margin 8px + padding 0 16px + line-height 34px + vertical-align bottom + color $theme-color-foreground + background $theme-color + border-radius 4px + + &:disabled + opacity 0.7 + + > .form + max-width 500px + margin 0 auto + + > .mk-note-preview + padding 16px + + > .visibleUsers + margin 5px + font-size 14px + + > span + margin-right 16px + color isDark ? #fff : #666 + + > input + z-index 1 + + > input + > textarea + display block + padding 12px + margin 0 + width 100% + font-size 16px + color isDark ? #fff : #333 + background isDark ? #191d23 : #fff border none border-radius 0 - box-shadow none + box-shadow 0 1px 0 0 isDark ? rgba(#000, 0.2) : rgba(#000, 0.1) + + &:disabled + opacity 0.5 + + > textarea + max-width 100% + min-width 100% + min-height 80px + + > .attaches + + > .files + display block + margin 0 + padding 4px + list-style none + + &:after + content "" + display block + clear both + + > .file + display block + float left + margin 0 + padding 0 + border solid 4px transparent + + > .img + width 64px + height 64px + background-size cover + background-position center center + + > .mk-uploader + margin 8px 0 0 0 + padding 8px + + > .file + display none + + > footer + white-space nowrap + overflow auto + -webkit-overflow-scrolling touch + overflow-scrolling touch + + > * + display inline-block + padding 0 + margin 0 + width 48px + height 48px + font-size 20px + color #657786 + background transparent + outline none + border none + border-radius 0 + box-shadow none + + > .hashtags + margin 8px + + > * + margin-right 8px .mk-post-form[data-darkmode] root(true) diff --git a/src/client/app/mobile/views/components/ui.nav.vue b/src/client/app/mobile/views/components/ui.nav.vue index bb7a2f558c..5257dafd0e 100644 --- a/src/client/app/mobile/views/components/ui.nav.vue +++ b/src/client/app/mobile/views/components/ui.nav.vue @@ -10,7 +10,7 @@ <transition name="nav"> <div class="body" v-if="isOpen"> <router-link class="me" v-if="$store.getters.isSignedIn" :to="`/@${$store.state.i.username}`"> - <img class="avatar" :src="`${$store.state.i.avatarUrl}?thumbnail&size=128`" alt="avatar"/> + <img class="avatar" :src="$store.state.i.avatarUrl" alt="avatar"/> <p class="name">{{ $store.state.i | userName }}</p> </router-link> <div class="links"> diff --git a/src/client/app/mobile/views/components/user-card.vue b/src/client/app/mobile/views/components/user-card.vue index 808ee72402..7b8f2251b2 100644 --- a/src/client/app/mobile/views/components/user-card.vue +++ b/src/client/app/mobile/views/components/user-card.vue @@ -1,6 +1,6 @@ <template> <div class="mk-user-card"> - <header :style="user.bannerUrl ? `background-image: url(${user.bannerUrl}?thumbnail&size=1024)` : ''"> + <header :style="user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''"> <mk-avatar class="avatar" :user="user"/> </header> <a class="name" :href="user | userPage" target="_blank">{{ user | userName }}</a> diff --git a/src/client/app/mobile/views/pages/favorites.vue b/src/client/app/mobile/views/pages/favorites.vue index c4edd9d970..1cccf169b0 100644 --- a/src/client/app/mobile/views/pages/favorites.vue +++ b/src/client/app/mobile/views/pages/favorites.vue @@ -53,7 +53,7 @@ export default Vue.extend({ this.moreFetching = true; (this as any).api('i/favorites', { limit: 11, - maxId: this.favorites[this.favorites.length - 1].id + untilId: this.favorites[this.favorites.length - 1].id }).then(favorites => { if (favorites.length == 11) { this.existMore = true; diff --git a/src/client/app/mobile/views/pages/followers.vue b/src/client/app/mobile/views/pages/followers.vue index dfb9c62142..7dc72a7c30 100644 --- a/src/client/app/mobile/views/pages/followers.vue +++ b/src/client/app/mobile/views/pages/followers.vue @@ -1,7 +1,7 @@ <template> <mk-ui> <template slot="header" v-if="!fetching"> - <img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""> + <img :src="user.avatarUrl" alt=""> {{ '%i18n:@followers-of%'.replace('{}', name) }} </template> <mk-users-list @@ -19,8 +19,8 @@ <script lang="ts"> import Vue from 'vue'; import Progress from '../../../common/scripts/loading'; -import parseAcct from '../../../../../acct/parse'; -import getUserName from '../../../../../renderers/get-user-name'; +import parseAcct from '../../../../../misc/acct/parse'; +import getUserName from '../../../../../misc/get-user-name'; export default Vue.extend({ data() { diff --git a/src/client/app/mobile/views/pages/following.vue b/src/client/app/mobile/views/pages/following.vue index 35461ea2fc..6895a76d53 100644 --- a/src/client/app/mobile/views/pages/following.vue +++ b/src/client/app/mobile/views/pages/following.vue @@ -1,7 +1,7 @@ <template> <mk-ui> <template slot="header" v-if="!fetching"> - <img :src="`${user.avatarUrl}?thumbnail&size=64`" alt=""> + <img :src="user.avatarUrl" alt=""> {{ '%i18n:@following-of%'.replace('{}', name) }} </template> <mk-users-list @@ -19,7 +19,7 @@ <script lang="ts"> import Vue from 'vue'; import Progress from '../../../common/scripts/loading'; -import parseAcct from '../../../../../acct/parse'; +import parseAcct from '../../../../../misc/acct/parse'; export default Vue.extend({ data() { diff --git a/src/client/app/mobile/views/pages/home.timeline.vue b/src/client/app/mobile/views/pages/home.timeline.vue index 364367b940..93d1364e09 100644 --- a/src/client/app/mobile/views/pages/home.timeline.vue +++ b/src/client/app/mobile/views/pages/home.timeline.vue @@ -42,19 +42,21 @@ export default Vue.extend({ }, stream(): any { - return this.src == 'home' - ? (this as any).os.stream - : this.src == 'local' - ? (this as any).os.streams.localTimelineStream - : (this as any).os.streams.globalTimelineStream; + switch (this.src) { + case 'home': return (this as any).os.stream; + case 'local': return (this as any).os.streams.localTimelineStream; + case 'hybrid': return (this as any).os.streams.hybridTimelineStream; + case 'global': return (this as any).os.streams.globalTimelineStream; + } }, endpoint(): string { - return this.src == 'home' - ? 'notes/timeline' - : this.src == 'local' - ? 'notes/local-timeline' - : 'notes/global-timeline'; + switch (this.src) { + case 'home': return 'notes/timeline'; + case 'local': return 'notes/local-timeline'; + case 'hybrid': return 'notes/hybrid-timeline'; + case 'global': return 'notes/global-timeline'; + } }, canFetchMore(): boolean { diff --git a/src/client/app/mobile/views/pages/home.vue b/src/client/app/mobile/views/pages/home.vue index c0c2ee8ab5..2f57e422a3 100644 --- a/src/client/app/mobile/views/pages/home.vue +++ b/src/client/app/mobile/views/pages/home.vue @@ -4,6 +4,7 @@ <span> <span v-if="src == 'home'">%fa:home%%i18n:@home%</span> <span v-if="src == 'local'">%fa:R comments%%i18n:@local%</span> + <span v-if="src == 'hybrid'">%fa:share-alt%%i18n:@hybrid%</span> <span v-if="src == 'global'">%fa:globe%%i18n:@global%</span> <span v-if="src == 'list'">%fa:list%{{ list.title }}</span> </span> @@ -24,6 +25,7 @@ <div> <span :data-active="src == 'home'" @click="src = 'home'">%fa:home% %i18n:@home%</span> <span :data-active="src == 'local'" @click="src = 'local'">%fa:R comments% %i18n:@local%</span> + <span :data-active="src == 'hybrid'" @click="src = 'hybrid'">%fa:share-alt% %i18n:@hybrid%</span> <span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% %i18n:@global%</span> <template v-if="lists"> <span v-for="l in lists" :data-active="src == 'list' && list == l" @click="src = 'list'; list = l" :key="l.id">%fa:list% {{ l.title }}</span> @@ -35,6 +37,7 @@ <div class="tl"> <x-tl v-if="src == 'home'" ref="tl" key="home" src="home"/> <x-tl v-if="src == 'local'" ref="tl" key="local" src="local"/> + <x-tl v-if="src == 'hybrid'" ref="tl" key="hybrid" src="hybrid"/> <x-tl v-if="src == 'global'" ref="tl" key="global" src="global"/> <mk-user-list-timeline v-if="src == 'list'" ref="tl" :key="list.id" :list="list"/> </div> @@ -88,7 +91,7 @@ export default Vue.extend({ this.list = this.$store.state.device.tl.arg; } } else if (this.$store.state.i.followingCount == 0) { - this.src = 'local'; + this.src = 'hybrid'; } }, diff --git a/src/client/app/mobile/views/pages/messaging-room.vue b/src/client/app/mobile/views/pages/messaging-room.vue index 8b82b03fb9..35ae506761 100644 --- a/src/client/app/mobile/views/pages/messaging-room.vue +++ b/src/client/app/mobile/views/pages/messaging-room.vue @@ -10,7 +10,7 @@ <script lang="ts"> import Vue from 'vue'; -import parseAcct from '../../../../../acct/parse'; +import parseAcct from '../../../../../misc/acct/parse'; export default Vue.extend({ data() { diff --git a/src/client/app/mobile/views/pages/messaging.vue b/src/client/app/mobile/views/pages/messaging.vue index 057470efd9..8dcbc5d6c5 100644 --- a/src/client/app/mobile/views/pages/messaging.vue +++ b/src/client/app/mobile/views/pages/messaging.vue @@ -7,7 +7,7 @@ <script lang="ts"> import Vue from 'vue'; -import getAcct from '../../../../../acct/render'; +import getAcct from '../../../../../misc/acct/render'; export default Vue.extend({ mounted() { diff --git a/src/client/app/mobile/views/pages/notifications.vue b/src/client/app/mobile/views/pages/notifications.vue index 64cfa60da0..fcd930997b 100644 --- a/src/client/app/mobile/views/pages/notifications.vue +++ b/src/client/app/mobile/views/pages/notifications.vue @@ -24,7 +24,7 @@ export default Vue.extend({ const ok = window.confirm('%i18n:@read-all%'); if (!ok) return; - (this as any).api('notifications/mark_as_read_all'); + (this as any).api('notifications/mark_all_as_read'); }, onFetched() { Progress.done(); diff --git a/src/client/app/mobile/views/pages/reversi.vue b/src/client/app/mobile/views/pages/reversi.vue index e2f0db6d87..0cff1317aa 100644 --- a/src/client/app/mobile/views/pages/reversi.vue +++ b/src/client/app/mobile/views/pages/reversi.vue @@ -33,7 +33,7 @@ export default Vue.extend({ Progress.start(); this.fetching = true; - (this as any).api('reversi/games/show', { + (this as any).api('games/reversi/games/show', { gameId: this.$route.params.game }).then(game => { this.game = game; diff --git a/src/client/app/mobile/views/pages/search.vue b/src/client/app/mobile/views/pages/search.vue index 9850fbcfb4..2559922efb 100644 --- a/src/client/app/mobile/views/pages/search.vue +++ b/src/client/app/mobile/views/pages/search.vue @@ -1,14 +1,10 @@ <template> <mk-ui> <span slot="header">%fa:search% {{ q }}</span> - <main v-if="!fetching"> - <mk-notes :class="$style.notes" :notes="notes"> - <span v-if="notes.length == 0">{{ '%i18n:@empty%'.replace('{}', q) }}</span> - <button v-if="existMore" @click="more" :disabled="fetching" slot="tail"> - <span v-if="!fetching">%i18n:@load-more%</span> - <span v-if="fetching">%i18n:common.loading%<mk-ellipsis/></span> - </button> - </mk-notes> + + <main> + <p v-if="!fetching && empty">%fa:search%「{{ q }}」に関する投稿は見つかりませんでした。</p> + <mk-notes ref="timeline" :more="existMore ? more : null"/> </main> </mk-ui> </template> @@ -16,7 +12,6 @@ <script lang="ts"> import Vue from 'vue'; import Progress from '../../../common/scripts/loading'; -import parse from '../../../common/scripts/parse-search-query'; const limit = 20; @@ -24,8 +19,9 @@ export default Vue.extend({ data() { return { fetching: true, + moreFetching: false, existMore: false, - notes: [], + empty: false, offset: 0 }; }, @@ -47,31 +43,43 @@ export default Vue.extend({ this.fetching = true; Progress.start(); - (this as any).api('notes/search', Object.assign({ - limit: limit + 1 - }, parse(this.q))).then(notes => { - if (notes.length == limit + 1) { - notes.pop(); - this.existMore = true; - } - this.notes = notes; - this.fetching = false; - Progress.done(); - }); + (this.$refs.timeline as any).init(() => new Promise((res, rej) => { + (this as any).api('notes/search', { + limit: limit + 1, + offset: this.offset, + query: this.q + }).then(notes => { + if (notes.length == 0) this.empty = true; + if (notes.length == limit + 1) { + notes.pop(); + this.existMore = true; + } + res(notes); + this.fetching = false; + Progress.done(); + }, rej); + })); }, more() { this.offset += limit; - (this as any).api('notes/search', Object.assign({ + + const promise = (this as any).api('notes/search', { limit: limit + 1, - offset: this.offset - }, parse(this.q))).then(notes => { + offset: this.offset, + query: this.q + }); + + promise.then(notes => { if (notes.length == limit + 1) { notes.pop(); } else { this.existMore = false; } - this.notes = this.notes.concat(notes); + notes.forEach(n => (this.$refs.timeline as any).append(n)); + this.moreFetching = false; }); + + return promise; } } }); diff --git a/src/client/app/mobile/views/pages/settings.vue b/src/client/app/mobile/views/pages/settings.vue index 89e5eaff67..f4645b1837 100644 --- a/src/client/app/mobile/views/pages/settings.vue +++ b/src/client/app/mobile/views/pages/settings.vue @@ -78,6 +78,8 @@ </ui-card> </div> + <div class="signout" @click="signout">%i18n:@signout%</div> + <footer> <small>ver {{ version }} ({{ codename }})</small> </footer> @@ -247,6 +249,14 @@ root(isDark) background isDark ? #273c34 : #fcfff5 box-shadow 0 3px 1px -2px rgba(#000, 0.2), 0 2px 2px 0 rgba(#000, 0.14), 0 1px 5px 0 rgba(#000, 0.12) + > .signout + margin 16px + padding 16px + text-align center + color isDark ? #ff5f56 : #cc2727 + background isDark ? #652222 : #fff6f5 + box-shadow 0 3px 1px -2px rgba(#000, 0.2), 0 2px 2px 0 rgba(#000, 0.14), 0 1px 5px 0 rgba(#000, 0.12) + > footer margin 16px text-align center diff --git a/src/client/app/mobile/views/pages/user.vue b/src/client/app/mobile/views/pages/user.vue index ba9de9f8a6..2bc89b81be 100644 --- a/src/client/app/mobile/views/pages/user.vue +++ b/src/client/app/mobile/views/pages/user.vue @@ -1,6 +1,6 @@ <template> <mk-ui> - <template slot="header" v-if="!fetching"><img :src="`${user.avatarUrl}?thumbnail&size=64`" alt="">{{ user | userName }}</template> + <template slot="header" v-if="!fetching"><img :src="user.avatarUrl" alt="">{{ user | userName }}</template> <main v-if="!fetching" :data-darkmode="$store.state.device.darkmode"> <div class="is-suspended" v-if="user.isSuspended"><p>%fa:exclamation-triangle% %i18n:@is-suspended%</p></div> <div class="is-remote" v-if="user.host != null"><p>%fa:exclamation-triangle% %i18n:@is-remote%<a :href="user.url || user.uri" target="_blank">%i18n:@view-remote%</a></p></div> @@ -64,7 +64,7 @@ <script lang="ts"> import Vue from 'vue'; import * as age from 's-age'; -import parseAcct from '../../../../../acct/parse'; +import parseAcct from '../../../../../misc/acct/parse'; import Progress from '../../../common/scripts/loading'; import XHome from './user/home.vue'; diff --git a/src/client/app/mobile/views/pages/user/home.followers-you-know.vue b/src/client/app/mobile/views/pages/user/home.followers-you-know.vue index 6f809d889e..d5e3bef963 100644 --- a/src/client/app/mobile/views/pages/user/home.followers-you-know.vue +++ b/src/client/app/mobile/views/pages/user/home.followers-you-know.vue @@ -3,7 +3,7 @@ <p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:@loading%<mk-ellipsis/></p> <div v-if="!fetching && users.length > 0"> <a v-for="user in users" :key="user.id" :href="user | userPage"> - <img :src="`${user.avatarUrl}?thumbnail&size=64`" :alt="user | userName"/> + <img :src="user.avatarUrl" :alt="user | userName"/> </a> </div> <p class="empty" v-if="!fetching && users.length == 0">%i18n:@no-users%</p> diff --git a/src/client/app/mobile/views/pages/user/home.photos.vue b/src/client/app/mobile/views/pages/user/home.photos.vue index bfd2aa8332..73ff1d5173 100644 --- a/src/client/app/mobile/views/pages/user/home.photos.vue +++ b/src/client/app/mobile/views/pages/user/home.photos.vue @@ -4,7 +4,7 @@ <div class="stream" v-if="!fetching && images.length > 0"> <a v-for="image in images" class="img" - :style="`background-image: url(${image.media.url}?thumbnail&size=256)`" + :style="`background-image: url(${image.media.url})`" :href="image.note | notePage" ></a> </div> diff --git a/src/client/app/mobile/views/widgets/profile.vue b/src/client/app/mobile/views/widgets/profile.vue index a94f7e94b8..6ce3468c49 100644 --- a/src/client/app/mobile/views/widgets/profile.vue +++ b/src/client/app/mobile/views/widgets/profile.vue @@ -2,10 +2,10 @@ <div class="mkw-profile"> <mk-widget-container> <div :class="$style.banner" - :style="$store.state.i.bannerUrl ? `background-image: url(${$store.state.i.bannerUrl}?thumbnail&size=256)` : ''" + :style="$store.state.i.bannerUrl ? `background-image: url(${$store.state.i.bannerUrl})` : ''" ></div> <img :class="$style.avatar" - :src="`${$store.state.i.avatarUrl}?thumbnail&size=96`" + :src="$store.state.i.avatarUrl" alt="avatar" /> <router-link :class="$style.name" :to="$store.state.i | userPage">{{ $store.state.i | userName }}</router-link> diff --git a/src/client/assets/error.jpg b/src/client/assets/error.jpg index 872b1a3f5d..24d92f3803 100644 Binary files a/src/client/assets/error.jpg and b/src/client/assets/error.jpg differ diff --git a/src/client/assets/pointer.png b/src/client/assets/pointer.png index c8bd07a3ae..0d03f75d2b 100644 Binary files a/src/client/assets/pointer.png and b/src/client/assets/pointer.png differ diff --git a/src/client/assets/reactions/angry.png b/src/client/assets/reactions/angry.png index d81c431a25..7e32dd6809 100644 Binary files a/src/client/assets/reactions/angry.png and b/src/client/assets/reactions/angry.png differ diff --git a/src/client/assets/reactions/confused.png b/src/client/assets/reactions/confused.png index cfaa60146f..c791854183 100644 Binary files a/src/client/assets/reactions/confused.png and b/src/client/assets/reactions/confused.png differ diff --git a/src/client/assets/reactions/congrats.png b/src/client/assets/reactions/congrats.png index 350adda322..fdea27fcb9 100644 Binary files a/src/client/assets/reactions/congrats.png and b/src/client/assets/reactions/congrats.png differ diff --git a/src/client/assets/reactions/hmm.png b/src/client/assets/reactions/hmm.png index a9a7e9ac88..725fe3898d 100644 Binary files a/src/client/assets/reactions/hmm.png and b/src/client/assets/reactions/hmm.png differ diff --git a/src/client/assets/reactions/laugh.png b/src/client/assets/reactions/laugh.png index cd2225ffe1..3b3c10a27a 100644 Binary files a/src/client/assets/reactions/laugh.png and b/src/client/assets/reactions/laugh.png differ diff --git a/src/client/assets/reactions/like.png b/src/client/assets/reactions/like.png index 9fe67c9109..526b391f96 100644 Binary files a/src/client/assets/reactions/like.png and b/src/client/assets/reactions/like.png differ diff --git a/src/client/assets/reactions/love.png b/src/client/assets/reactions/love.png index b8a7532ef0..9fe82cd070 100644 Binary files a/src/client/assets/reactions/love.png and b/src/client/assets/reactions/love.png differ diff --git a/src/client/assets/reactions/pudding.png b/src/client/assets/reactions/pudding.png index 27a6b048e8..e4d10a229d 100644 Binary files a/src/client/assets/reactions/pudding.png and b/src/client/assets/reactions/pudding.png differ diff --git a/src/client/assets/reactions/surprise.png b/src/client/assets/reactions/surprise.png index 5904cb2c6c..aa55592ded 100644 Binary files a/src/client/assets/reactions/surprise.png and b/src/client/assets/reactions/surprise.png differ diff --git a/src/client/docs/about.en.pug b/src/client/docs/about.en.pug deleted file mode 100644 index 893d9dd6a1..0000000000 --- a/src/client/docs/about.en.pug +++ /dev/null @@ -1,3 +0,0 @@ -h1 About Misskey - -p Misskey is a mini blog SNS. diff --git a/src/client/docs/about.ja.pug b/src/client/docs/about.ja.pug deleted file mode 100644 index fec933b0c6..0000000000 --- a/src/client/docs/about.ja.pug +++ /dev/null @@ -1,3 +0,0 @@ -h1 Misskeyについて - -p MisskeyはミニブログSNSです。 diff --git a/src/client/docs/api.ja.pug b/src/client/docs/api.ja.pug deleted file mode 100644 index 665cfdc4b8..0000000000 --- a/src/client/docs/api.ja.pug +++ /dev/null @@ -1,103 +0,0 @@ -h1 Misskey API - -p MisskeyはWeb APIを公開しており、様々な操作をプログラム上から行うことができます。 -p APIを自分のアカウントから利用する場合(自分のアカウントのみ操作したい場合)と、アプリケーションから利用する場合(不特定のアカウントを操作したい場合)とで利用手順が異なりますので、それぞれのケースについて説明します。 - -section - h2 自分の所有するアカウントからAPIにアクセスする場合 - p 「設定 > API」で、APIにアクセスするのに必要なAPIキーを取得してください。 - p APIにアクセスする際には、リクエストにAPIキーを「i」というパラメータ名で含めます。 - div.ui.info.warn: p %fa:exclamation-triangle%アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。 - p APIの詳しい使用法は「Misskey APIの利用」セクションをご覧ください。 - -section - h2 アプリケーションからAPIにアクセスする場合 - p - | 直接ユーザーのAPIキーをアプリケーションが扱うのは危険なので、 - | アプリケーションからAPIを利用する際には、アプリケーションとアプリケーションを利用するユーザーが結び付けられた専用のトークン(アクセストークン)をMisskeyに発行してもらい、 - | そのトークンをリクエストのパラメータに含める必要があります。 - div.ui.info: p %fa:info-circle%アクセストークンは、ユーザーが自分のアカウントにあなたのアプリケーションがアクセスすることを許可した場合のみ発行されます - - p それでは、アクセストークンを取得するまでの流れを説明します。 - - section - h3 1.アプリケーションを登録する - p まず、あなたのアプリケーションやWebサービス(以後、あなたのアプリと呼びます)をMisskeyに登録します。 - p - a(href=common.config.dev_url, target="_blank") デベロッパーセンター - | にアクセスし、「アプリ > アプリ作成」に進みます。 - | フォームに必要事項を記入し、アプリを作成してください。フォームの記入欄の説明は以下の通りです: - - table - thead - tr - th 名前 - th 説明 - tbody - tr - td アプリケーション名 - td あなたのアプリの名称。 - tr - td アプリの概要 - td あなたのアプリの簡単な説明や紹介。 - tr - td コールバックURL - td ユーザーが後述する認証フォームで認証を終えた際にリダイレクトするURLを設定できます。あなたのアプリがWebサービスである場合に有用です。 - tr - td 権限 - td あなたのアプリが要求する権限。ここで要求した機能だけがAPIからアクセスできます。 - - p 登録が済むとあなたのアプリのシークレットキーが入手できます。このシークレットキーは後で使用します。 - div.ui.info.warn: p %fa:exclamation-triangle%アプリに成りすまされる可能性があるため、極力このシークレットキーは公開しないようにしてください。 - - section - h3 2.ユーザーに認証させる - p あなたのアプリを使ってもらうには、ユーザーにアカウントへのアクセスの許可をもらう必要があります。 - p - | 認証セッションを開始するには、#{common.config.api_url}/auth/session/generate へパラメータに appSecret としてシークレットキーを含めたリクエストを送信します。 - | リクエスト形式はJSONで、メソッドはPOSTです。 - | レスポンスとして認証セッションのトークンや認証フォームのURLが取得できるので、認証フォームのURLをブラウザで表示し、ユーザーにフォームを提示してください。 - - p - | あなたのアプリがコールバックURLを設定している場合、 - | ユーザーがあなたのアプリの連携を許可すると設定しているコールバックURLに token という名前でセッションのトークンが含まれたクエリを付けてリダイレクトします。 - - p - | あなたのアプリがコールバックURLを設定していない場合、ユーザーがあなたのアプリの連携を許可したことを(何らかの方法で(たとえばボタンを押させるなど))確認出来るようにしてください。 - - section - h3 3.ユーザーのアクセストークンを取得する - p ユーザーが連携を許可したら、#{common.config.api_url}/auth/session/userkey へ次のパラメータを含むリクエストを送信します: - table - thead - tr - th 名前 - th 型 - th 説明 - tbody - tr - td appSecret - td string - td あなたのアプリのシークレットキー - tr - td token - td string - td セッションのトークン - p 上手くいけば、認証したユーザーのアクセストークンがレスポンスとして取得できます。おめでとうございます! - - p アクセストークンが取得できたら、「ユーザーのアクセストークン+あなたのアプリのシークレットキーをsha256したもの」を「i」というパラメータでリクエストに含めると、APIにアクセスすることができます。 - - p 「i」パラメータの生成方法を擬似コードで表すと次のようになります: - pre: code - | const i = sha256(accessToken + secretKey); - - p APIの詳しい使用法は「Misskey APIの利用」セクションをご覧ください。 - -section - h2 Misskey APIの利用 - p APIはすべてリクエストのパラメータ・レスポンスともにJSON形式です。また、すべてのエンドポイントはPOSTメソッドのみ受け付けます。 - p APIリファレンスもご確認ください。 - - section - h3 レートリミット - p Misskey APIにはレートリミットがあり、短時間のうちに多数のリクエストを送信すると、一定時間APIを利用することができなくなることがあります。 diff --git a/src/client/docs/api/endpoints/notes/create.yaml b/src/client/docs/api/endpoints/notes/create.yaml deleted file mode 100644 index 04ada2ecd5..0000000000 --- a/src/client/docs/api/endpoints/notes/create.yaml +++ /dev/null @@ -1,59 +0,0 @@ -endpoint: "notes/create" - -desc: - ja: "投稿します。" - en: "Compose new note." - -params: - - name: "text" - type: "string" - optional: true - desc: - ja: "投稿の本文" - en: "The text of your note" - - name: "cw" - type: "string" - optional: true - desc: - ja: "コンテンツの警告。このパラメータを指定すると設定したテキストで投稿のコンテンツを隠す事が出来ます。" - en: "Content Warning" - - name: "mediaIds" - type: "id(DriveFile)[]" - optional: true - desc: - ja: "添付するメディア(1~4つ)" - en: "Media you want to attach (1~4)" - - name: "replyId" - type: "id(Note)" - optional: true - desc: - ja: "返信する投稿" - en: "The note you want to reply" - - name: "renoteId" - type: "id(Note)" - optional: true - desc: - ja: "引用する投稿" - en: "The note you want to quote" - - name: "poll" - type: "object" - optional: true - desc: - ja: "投票" - en: "The poll" - defName: "poll" - def: - - name: "choices" - type: "string[]" - optional: false - desc: - ja: "投票の選択肢" - en: "Choices of a poll" - -res: - - name: "createdNote" - type: "entity(Note)" - optional: false - desc: - ja: "作成した投稿" - en: "A note that created" diff --git a/src/client/docs/api/endpoints/notes/timeline.yaml b/src/client/docs/api/endpoints/notes/timeline.yaml deleted file mode 100644 index 71c346f355..0000000000 --- a/src/client/docs/api/endpoints/notes/timeline.yaml +++ /dev/null @@ -1,32 +0,0 @@ -endpoint: "notes/timeline" - -desc: - ja: "タイムラインを取得します。" - en: "Get your timeline." - -params: - - name: "limit" - type: "number" - optional: true - desc: - ja: "取得する最大の数" - - name: "sinceId" - type: "id(Note)" - optional: true - desc: - ja: "指定すると、この投稿を基点としてより新しい投稿を取得します" - - name: "untilId" - type: "id(Note)" - optional: true - desc: - ja: "指定すると、この投稿を基点としてより古い投稿を取得します" - - name: "sinceDate" - type: "number" - optional: true - desc: - ja: "指定した時間を基点としてより新しい投稿を取得します。数値は、1970 年 1 月 1 日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。" - - name: "untilDate" - type: "number" - optional: true - desc: - ja: "指定した時間を基点としてより古い投稿を取得します。数値は、1970 年 1 月 1 日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。" diff --git a/src/client/docs/api/endpoints/view.pug b/src/client/docs/api/endpoints/view.pug deleted file mode 100644 index f8795c8442..0000000000 --- a/src/client/docs/api/endpoints/view.pug +++ /dev/null @@ -1,32 +0,0 @@ -extends ../../layout.pug -include ../mixins - -block meta - link(rel="stylesheet" href="/docs/assets/api/endpoints/style.css") - -block main - h1= endpoint - - p#url - span.method POST - span.host - = url.host - | / - span.path= url.path - - p#desc= desc[lang] || desc['ja'] - - section - h2 %i18n:docs.api.endpoints.params% - +propTable(params) - - if paramDefs - each paramDef in paramDefs - section(id= paramDef.name) - h3= paramDef.name - +propTable(paramDef.params) - - if res - section - h2 %i18n:docs.api.endpoints.res% - +propTable(res) diff --git a/src/client/docs/api/entities/post.yaml b/src/client/docs/api/entities/post.yaml deleted file mode 100644 index 6fd26543bb..0000000000 --- a/src/client/docs/api/entities/post.yaml +++ /dev/null @@ -1,168 +0,0 @@ -name: "Note" - -desc: - ja: "投稿。" - en: "A note." - -props: - - name: "id" - type: "id" - optional: false - desc: - ja: "投稿ID" - en: "The ID of this note" - - name: "createdAt" - type: "date" - optional: false - desc: - ja: "投稿日時" - en: "The posted date of this note" - - name: "viaMobile" - type: "boolean" - optional: true - desc: - ja: "モバイル端末から投稿したか否か(自己申告であることに留意)" - en: "Whether this note sent via a mobile device" - - name: "text" - type: "string" - optional: true - desc: - ja: "投稿の本文 (ローカルの場合Markdown風のフォーマット)" - en: "The text of this note (in Markdown like format if local)" - - name: "mediaIds" - type: "id(DriveFile)[]" - optional: true - desc: - ja: "添付されているメディアのID (なければレスポンスでは空配列)" - en: "The IDs of the attached media (empty array for response if no media is attached)" - - name: "media" - type: "entity(DriveFile)[]" - optional: true - desc: - ja: "添付されているメディア" - en: "The attached media" - - name: "userId" - type: "id(User)" - optional: false - desc: - ja: "投稿者ID" - en: "The ID of author of this note" - - name: "user" - type: "entity(User)" - optional: true - desc: - ja: "投稿者" - en: "The author of this note" - - name: "myReaction" - type: "string" - optional: true - desc: - ja: "この投稿に対する自分の<a href='/docs/api/reactions'>リアクション</a>" - en: "The your <a href='/docs/api/reactions'>reaction</a> of this note" - - name: "reactionCounts" - type: "object" - optional: false - desc: - ja: "<a href='/docs/api/reactions'>リアクション</a>をキーとし、この投稿に対するそのリアクションの数を値としたオブジェクト" - - name: "replyId" - type: "id(Note)" - optional: true - desc: - ja: "返信した投稿のID" - en: "The ID of the replyed note" - - name: "reply" - type: "entity(Note)" - optional: true - desc: - ja: "返信した投稿" - en: "The replyed note" - - name: "renoteId" - type: "id(Note)" - optional: true - desc: - ja: "引用した投稿のID" - en: "The ID of the quoted note" - - name: "renote" - type: "entity(Note)" - optional: true - desc: - ja: "引用した投稿" - en: "The quoted note" - - name: "poll" - type: "object" - optional: true - desc: - ja: "投票" - en: "The poll" - defName: "poll" - def: - - name: "choices" - type: "object[]" - optional: false - desc: - ja: "投票の選択肢" - en: "The choices of this poll" - defName: "choice" - def: - - name: "id" - type: "number" - optional: false - desc: - ja: "選択肢ID" - en: "The ID of this choice" - - name: "isVoted" - type: "boolean" - optional: true - desc: - ja: "自分がこの選択肢に投票したかどうか" - en: "Whether you voted to this choice" - - name: "text" - type: "string" - optional: false - desc: - ja: "選択肢本文" - en: "The text of this choice" - - name: "votes" - type: "number" - optional: false - desc: - ja: "この選択肢に投票された数" - en: "The number voted for this choice" - - name: "geo" - type: "object" - optional: true - desc: - ja: "位置情報" - en: "Geo location" - defName: "geo" - def: - - name: "coordinates" - type: "number[]" - optional: false - desc: - ja: "座標。最初に経度:-180〜180で表す。最後に緯度:-90〜90で表す。" - - name: "altitude" - type: "number" - optional: false - desc: - ja: "高度。メートル単位で表す。" - - name: "accuracy" - type: "number" - optional: false - desc: - ja: "緯度、経度の精度。メートル単位で表す。" - - name: "altitudeAccuracy" - type: "number" - optional: false - desc: - ja: "高度の精度。メートル単位で表す。" - - name: "heading" - type: "number" - optional: false - desc: - ja: "方角。0〜360の角度で表す。0が北、90が東、180が南、270が西。" - - name: "speed" - type: "number" - optional: false - desc: - ja: "速度。メートル / 秒数で表す。" diff --git a/src/client/docs/api/gulpfile.ts b/src/client/docs/api/gulpfile.ts deleted file mode 100644 index 0eb8b88287..0000000000 --- a/src/client/docs/api/gulpfile.ts +++ /dev/null @@ -1,193 +0,0 @@ -/** - * Gulp tasks - */ - -import * as fs from 'fs'; -import * as path from 'path'; -import * as glob from 'glob'; -import * as gulp from 'gulp'; -import * as pug from 'pug'; -import * as yaml from 'js-yaml'; -import * as mkdirp from 'mkdirp'; - -import locales from '../../../../locales'; -import I18nReplacer from '../../../build/i18n'; -import fa from '../../../build/fa'; -import config from './../../../config'; - -import generateVars from '../vars'; - -const langs = Object.keys(locales); - -const kebab = (string: string) => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase(); - -// WIP type -const parseParam = (param: any) => { - const id = param.type.match(/^id\((.+?)\)|^id/); - const entity = param.type.match(/^entity\((.+?)\)/); - const isObject = /^object/.test(param.type); - const isDate = /^date/.test(param.type); - const isArray = /\[\]$/.test(param.type); - if (id) { - param.kind = 'id'; - param.type = 'string'; - param.entity = id[1]; - if (isArray) { - param.type += '[]'; - } - } - if (entity) { - param.kind = 'entity'; - param.type = 'object'; - param.entity = entity[1]; - if (isArray) { - param.type += '[]'; - } - } - if (isObject) { - param.kind = 'object'; - } - if (isDate) { - param.kind = 'date'; - param.type = 'string'; - if (isArray) { - param.type += '[]'; - } - } - - return param; -}; - -const sortParams = (params: Array<{name: string}>) => { - params.sort((a, b) => { - if (a.name < b.name) - return -1; - if (a.name > b.name) - return 1; - return 0; - }); - return params; -}; - -// WIP type -const extractDefs = (params: any[]) => { - let defs: any[] = []; - - params.forEach(param => { - if (param.def) { - defs.push({ - name: param.defName, - params: sortParams(param.def.map((p: any) => parseParam(p))) - }); - - const childDefs = extractDefs(param.def); - - defs = defs.concat(childDefs); - } - }); - - return sortParams(defs); -}; - -gulp.task('doc:api', [ - 'doc:api:endpoints', - 'doc:api:entities' -]); - -gulp.task('doc:api:endpoints', async () => { - const commonVars = await generateVars(); - glob('./src/client/docs/api/endpoints/**/*.yaml', (globErr, files) => { - if (globErr) { - console.error(globErr); - return; - } - //console.log(files); - files.forEach(file => { - const ep: any = yaml.safeLoad(fs.readFileSync(file, 'utf-8')); - const vars = { - endpoint: ep.endpoint, - url: { - host: config.api_url, - path: ep.endpoint - }, - desc: ep.desc, - // @ts-ignore - params: sortParams(ep.params.map(p => parseParam(p))), - paramDefs: extractDefs(ep.params), - // @ts-ignore - res: ep.res ? sortParams(ep.res.map(p => parseParam(p))) : null, - resDefs: ep.res ? extractDefs(ep.res) : null, - }; - langs.forEach(lang => { - pug.renderFile('./src/client/docs/api/endpoints/view.pug', Object.assign({}, vars, { - lang, - title: ep.endpoint, - src: `https://github.com/syuilo/misskey/tree/master/src/client/docs/api/endpoints/${ep.endpoint}.yaml`, - kebab, - common: commonVars - }), (renderErr, html) => { - if (renderErr) { - console.error(renderErr); - return; - } - const i18n = new I18nReplacer(lang); - html = html.replace(i18n.pattern, i18n.replacement); - html = fa(html); - const htmlPath = `./built/client/docs/${lang}/api/endpoints/${ep.endpoint}.html`; - mkdirp(path.dirname(htmlPath), (mkdirErr) => { - if (mkdirErr) { - console.error(mkdirErr); - return; - } - fs.writeFileSync(htmlPath, html, 'utf-8'); - }); - }); - }); - }); - }); -}); - -gulp.task('doc:api:entities', async () => { - const commonVars = await generateVars(); - glob('./src/client/docs/api/entities/**/*.yaml', (globErr, files) => { - if (globErr) { - console.error(globErr); - return; - } - files.forEach(file => { - const entity = yaml.safeLoad(fs.readFileSync(file, 'utf-8')) as any; - const vars = { - name: entity.name, - desc: entity.desc, - // WIP type - props: sortParams(entity.props.map((p: any) => parseParam(p))), - propDefs: extractDefs(entity.props), - }; - langs.forEach(lang => { - pug.renderFile('./src/client/docs/api/entities/view.pug', Object.assign({}, vars, { - lang, - title: entity.name, - src: `https://github.com/syuilo/misskey/tree/master/src/client/docs/api/entities/${kebab(entity.name)}.yaml`, - kebab, - common: commonVars - }), (renderErr, html) => { - if (renderErr) { - console.error(renderErr); - return; - } - const i18n = new I18nReplacer(lang); - html = html.replace(i18n.pattern, i18n.replacement); - html = fa(html); - const htmlPath = `./built/client/docs/${lang}/api/entities/${kebab(entity.name)}.html`; - mkdirp(path.dirname(htmlPath), (mkdirErr) => { - if (mkdirErr) { - console.error(mkdirErr); - return; - } - fs.writeFileSync(htmlPath, html, 'utf-8'); - }); - }); - }); - }); - }); -}); diff --git a/src/client/docs/api/mixins.pug b/src/client/docs/api/mixins.pug deleted file mode 100644 index 913135a85f..0000000000 --- a/src/client/docs/api/mixins.pug +++ /dev/null @@ -1,37 +0,0 @@ -mixin propTable(props) - table.props - thead: tr - th %i18n:docs.api.props.name% - th %i18n:docs.api.props.type% - th %i18n:docs.api.props.optional% - th %i18n:docs.api.props.description% - tbody - each prop in props - tr - td.name= prop.name - td.type - i= prop.type - if prop.kind == 'id' - if prop.entity - | ( - a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity - | ID) - else - | (ID) - else if prop.kind == 'entity' - | ( - a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity - | ) - else if prop.kind == 'object' - if prop.def - | ( - a(href=`#${prop.defName}`)= prop.defName - | ) - else if prop.kind == 'date' - | (Date) - td.optional - if prop.optional - | %i18n:docs.api.props.yes% - else - | %i18n:docs.api.props.no% - td.desc!= prop.desc[lang] || prop.desc['ja'] diff --git a/src/client/docs/follow.ja.pug b/src/client/docs/follow.ja.pug deleted file mode 100644 index f0e83bc8fd..0000000000 --- a/src/client/docs/follow.ja.pug +++ /dev/null @@ -1,9 +0,0 @@ -h1 フォロー -p ユーザーをフォローすると、タイムラインにそのユーザーの投稿が表示されるようになります。ただし、他のユーザーに対する返信は含まれません。 -p ユーザーをフォローするには、ユーザーページの「フォロー」ボタンをクリックします。フォローを解除するには、もう一度クリックします。 - -section - h2 ストーキング - p ユーザーをフォローしている状態では、さらに「ストーキング」モードをオンにすることができます。ストーキングを行うと、タイムラインにそのユーザーの全ての投稿が表示されるようになります。つまり、他のユーザーに対する返信も含まれることになります。 - p ストーキングするには、ユーザーページの「ストークする」をクリックします。ストーキングをやめるには、もう一度クリックします。 - p ストーキングしていることは相手に通知されません。 diff --git a/src/client/docs/gulpfile.ts b/src/client/docs/gulpfile.ts deleted file mode 100644 index 4683a04659..0000000000 --- a/src/client/docs/gulpfile.ts +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Gulp tasks - */ - -import * as fs from 'fs'; -import * as path from 'path'; -import * as glob from 'glob'; -import * as gulp from 'gulp'; -import * as pug from 'pug'; -import * as mkdirp from 'mkdirp'; -const stylus = require('gulp-stylus'); -const cssnano = require('gulp-cssnano'); - -import I18nReplacer from '../../build/i18n'; -import fa from '../../build/fa'; -import generateVars from './vars'; - -require('./api/gulpfile.ts'); - -gulp.task('doc', [ - 'doc:docs', - 'doc:api', - 'doc:styles' -]); - -gulp.task('doc:docs', async () => { - const commonVars = await generateVars(); - - glob('./src/client/docs/**/*.*.pug', (globErr, files) => { - if (globErr) { - console.error(globErr); - return; - } - files.forEach(file => { - const [, name, lang] = file.match(/docs\/(.+?)\.(.+?)\.pug$/); - const vars = { - common: commonVars, - lang: lang, - title: fs.readFileSync(file, 'utf-8').match(/^h1 (.+?)\r?\n/)[1], - src: `https://github.com/syuilo/misskey/tree/master/src/client/docs/${name}.${lang}.pug`, - }; - pug.renderFile(file, vars, (renderErr, content) => { - if (renderErr) { - console.error(renderErr); - return; - } - - pug.renderFile('./src/client/docs/layout.pug', Object.assign({}, vars, { - content - }), (renderErr2, html) => { - if (renderErr2) { - console.error(renderErr2); - return; - } - const i18n = new I18nReplacer(lang); - html = html.replace(i18n.pattern, i18n.replacement); - html = fa(html); - const htmlPath = `./built/client/docs/${lang}/${name}.html`; - mkdirp(path.dirname(htmlPath), (mkdirErr) => { - if (mkdirErr) { - console.error(mkdirErr); - return; - } - fs.writeFileSync(htmlPath, html, 'utf-8'); - }); - }); - }); - }); - }); -}); - -gulp.task('doc:styles', () => - gulp.src('./src/client/docs/**/*.styl') - .pipe(stylus()) - .pipe((cssnano as any)()) - .pipe(gulp.dest('./built/client/docs/assets/')) -); diff --git a/src/client/docs/index.en.pug b/src/client/docs/index.en.pug deleted file mode 100644 index 1fcc870d3d..0000000000 --- a/src/client/docs/index.en.pug +++ /dev/null @@ -1,3 +0,0 @@ -h1 Misskey Docs - -p Welcome to docs of Misskey. diff --git a/src/client/docs/index.ja.pug b/src/client/docs/index.ja.pug deleted file mode 100644 index 4a0bf7fa1d..0000000000 --- a/src/client/docs/index.ja.pug +++ /dev/null @@ -1,3 +0,0 @@ -h1 Misskey ドキュメント - -p Misskeyのドキュメントへようこそ diff --git a/src/client/docs/layout.pug b/src/client/docs/layout.pug deleted file mode 100644 index 1d9ebcb4cd..0000000000 --- a/src/client/docs/layout.pug +++ /dev/null @@ -1,41 +0,0 @@ -doctype html - -html(lang= lang) - head - meta(charset="UTF-8") - meta(name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no") - title - | #{title} | Misskey Docs - link(rel="stylesheet" href="/docs/assets/style.css") - block meta - - //- FontAwesome style - style #{common.facss} - - body - nav - ul - each doc in common.docs - li: a(href=`/docs/${lang}/${doc.name}`)= doc.title[lang] || doc.title['ja'] - section - h2 API - ul - li Entities - ul - each entity in common.entities - li: a(href=`/docs/${lang}/api/entities/${common.kebab(entity)}`)= entity - li Endpoints - ul - each endpoint in common.endpoints - li: a(href=`/docs/${lang}/api/endpoints/${common.kebab(endpoint)}`)= endpoint - main - article - block main - if content - | !{content} - - footer - p - | %i18n:docs.edit-this-page-on-github% - a(href=src target="_blank") %i18n:docs.edit-this-page-on-github-link% - small= common.copyright diff --git a/src/client/docs/license.en.pug b/src/client/docs/license.en.pug deleted file mode 100644 index 45d8b76473..0000000000 --- a/src/client/docs/license.en.pug +++ /dev/null @@ -1,17 +0,0 @@ -h1 License - -div!= common.license - -details - summary Libraries - - section - h2 Libraries - - each dependency, name in common.dependencies - details - summary= name - - section - h3= name - pre= dependency.licenseText diff --git a/src/client/docs/license.ja.pug b/src/client/docs/license.ja.pug deleted file mode 100644 index 6eb9ac308e..0000000000 --- a/src/client/docs/license.ja.pug +++ /dev/null @@ -1,17 +0,0 @@ -h1 ライセンス - -div!= common.license - -details - summary サードパーティ - - section - h2 サードパーティ - - each dependency, name in common.dependencies - details - summary= name - - section - h3= name - pre= dependency.licenseText diff --git a/src/client/docs/mute.ja.pug b/src/client/docs/mute.ja.pug deleted file mode 100644 index 807f7b67a7..0000000000 --- a/src/client/docs/mute.ja.pug +++ /dev/null @@ -1,13 +0,0 @@ -h1 ミュート - -p ユーザーページから、そのユーザーをミュートすることができます。 - -p ユーザーをミュートすると、そのユーザーに関する次のコンテンツがMisskeyに表示されなくなります: -ul - li タイムラインや投稿の検索結果内の、そのユーザーの投稿(およびそれらの投稿に対する返信やRenote) - li そのユーザーからの通知 - li メッセージ履歴一覧内の、そのユーザーとのメッセージ履歴 - -p ミュートを行ったことは相手に通知されず、ミュートされていることを知ることもできません。 - -p 設定>ミュート から、自分がミュートしているユーザー一覧を確認することができます。 diff --git a/src/client/docs/search.ja.pug b/src/client/docs/search.ja.pug deleted file mode 100644 index fc62d16cae..0000000000 --- a/src/client/docs/search.ja.pug +++ /dev/null @@ -1,120 +0,0 @@ -h1 検索 - -p 投稿を検索することができます。 -p - | キーワードを半角スペースで区切ると、and検索になります。 - | 例えば、「git コミット」と検索すると、「gitで編集したファイルの特定の行だけコミットする方法がわからない」などがマッチします。 - -section - h2 キーワードの除外 - p キーワードの前に「-」(ハイフン)をプリフィクスすると、そのキーワードを含まない投稿に限定します。 - p 例えば、「gitというキーワードを含むが、コミットというキーワードは含まない投稿」を検索したい場合、クエリは以下のようになります: - code git -コミット - -section - h2 完全一致 - p テキストを「"""」で囲むと、そのテキストと完全に一致する投稿を検索します。 - p 例えば、「"""にゃーん"""」と検索すると、「にゃーん」という投稿のみがヒットし、「にゃーん…」という投稿はヒットしません。 - -section - h2 タグ - p キーワードの前に「#」(シャープ)をプリフィクスすると、そのキーワードと一致するタグを持つ投稿に限定します。 - -section - h2 オプション - p - | オプションを使用して、より高度な検索を行えます。 - | オプションを指定するには、「オプション名:値」という形式でクエリに含めます。 - p 利用可能なオプション一覧です: - - table - thead - tr - th 名前 - th 説明 - tbody - tr - td user - td - | 指定されたユーザー名のユーザーの投稿に限定します。 - | 「,」(カンマ)で区切って、複数ユーザーを指定することもできます。 - br - | 例えば、 - code user:himawari,sakurako - | と検索すると「@himawariまたは@sakurakoの投稿」だけに限定します。 - | (つまりユーザーのホワイトリストです) - tr - td exclude_user - td - | 指定されたユーザー名のユーザーの投稿を除外します。 - | 「,」(カンマ)で区切って、複数ユーザーを指定することもできます。 - br - | 例えば、 - code exclude_user:akari,chinatsu - | と検索すると「@akariまたは@chinatsu以外の投稿」に限定します。 - | (つまりユーザーのブラックリストです) - tr - td follow - td - | true ... フォローしているユーザーに限定。 - br - | false ... フォローしていないユーザーに限定。 - br - | null ... 特に限定しない(デフォルト) - tr - td mute - td - | mute_all ... ミュートしているユーザーの投稿とその投稿に対する返信やRenoteを除外する(デフォルト) - br - | mute_related ... ミュートしているユーザーの投稿に対する返信やRenoteだけ除外する - br - | mute_direct ... ミュートしているユーザーの投稿だけ除外する - br - | disabled ... ミュートしているユーザーの投稿とその投稿に対する返信やRenoteも含める - br - | direct_only ... ミュートしているユーザーの投稿だけに限定 - br - | related_only ... ミュートしているユーザーの投稿に対する返信やRenoteだけに限定 - br - | all_only ... ミュートしているユーザーの投稿とその投稿に対する返信やRenoteに限定 - tr - td reply - td - | true ... 返信に限定。 - br - | false ... 返信でない投稿に限定。 - br - | null ... 特に限定しない(デフォルト) - tr - td renote - td - | true ... Renoteに限定。 - br - | false ... Renoteでない投稿に限定。 - br - | null ... 特に限定しない(デフォルト) - tr - td media - td - | true ... メディアが添付されている投稿に限定。 - br - | false ... メディアが添付されていない投稿に限定。 - br - | null ... 特に限定しない(デフォルト) - tr - td poll - td - | true ... 投票が添付されている投稿に限定。 - br - | false ... 投票が添付されていない投稿に限定。 - br - | null ... 特に限定しない(デフォルト) - tr - td until - td 上限の日時。(YYYY-MM-DD) - tr - td since - td 下限の日時。(YYYY-MM-DD) - - p 例えば、「@syuiloの2017年11月1日から2017年12月31日までの『Misskey』というテキストを含む返信ではない投稿」を検索したい場合、クエリは以下のようになります: - code user:syuilo since:2017-11-01 until:2017-12-31 reply:false Misskey diff --git a/src/client/docs/tou.ja.pug b/src/client/docs/tou.ja.pug deleted file mode 100644 index 7663258f82..0000000000 --- a/src/client/docs/tou.ja.pug +++ /dev/null @@ -1,3 +0,0 @@ -h1 利用規約 - -p 公序良俗に反する行為はおやめください。 diff --git a/src/client/docs/vars.ts b/src/client/docs/vars.ts deleted file mode 100644 index 93082767e3..0000000000 --- a/src/client/docs/vars.ts +++ /dev/null @@ -1,64 +0,0 @@ -import * as fs from 'fs'; -import * as util from 'util'; -import * as glob from 'glob'; -import * as yaml from 'js-yaml'; -import * as licenseChecker from 'license-checker'; -import * as tmp from 'tmp'; - -import { fa } from '../../build/fa'; -import config from '../../config'; -import { licenseHtml } from '../../build/license'; -const constants = require('../../const.json'); - -export default async function(): Promise<{ [key: string]: any }> { - const vars = {} as { [key: string]: any }; - - const endpoints = glob.sync('./src/client/docs/api/endpoints/**/*.yaml'); - vars['endpoints'] = endpoints.map(ep => { - const _ep = yaml.safeLoad(fs.readFileSync(ep, 'utf-8')) as any; - return _ep.endpoint; - }); - - const entities = glob.sync('./src/client/docs/api/entities/**/*.yaml'); - vars['entities'] = entities.map(x => { - const _x = yaml.safeLoad(fs.readFileSync(x, 'utf-8')) as any; - return _x.name; - }); - - const docs = glob.sync('./src/client/docs/**/*.*.pug'); - vars['docs'] = {}; - docs.forEach(x => { - const [, name, lang] = x.match(/docs\/(.+?)\.(.+?)\.pug$/); - if (vars['docs'][name] == null) { - vars['docs'][name] = { - name, - title: {} - }; - } - vars['docs'][name]['title'][lang] = fs.readFileSync(x, 'utf-8').match(/^h1 (.+?)\r?\n/)[1]; - }); - - vars['kebab'] = (string: string) => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase(); - - vars['config'] = config; - - vars['copyright'] = constants.copyright; - - vars['facss'] = fa.dom.css(); - - vars['license'] = licenseHtml; - - const tmpObj = tmp.fileSync(); - fs.writeFileSync(tmpObj.name, JSON.stringify({ - licenseText: '' - }), 'utf-8'); - const dependencies = await util.promisify(licenseChecker.init).bind(licenseChecker)({ - start: __dirname + '/../../../', - customPath: tmpObj.name - }); - tmpObj.removeCallback(); - - vars['dependencies'] = dependencies; - - return vars; -} diff --git a/src/config/load.ts b/src/config/load.ts index fea89b989a..44a24c96ae 100644 --- a/src/config/load.ts +++ b/src/config/load.ts @@ -26,7 +26,7 @@ export default function load() { const mixin = {} as Mixin; // Validate URLs - if (!isUrl(config.url)) urlError(config.url); + if (!isUrl(config.url)) throw `url="${config.url}" is not a valid URL`; const url = new URL(config.url); config.url = normalizeUrl(config.url); @@ -44,14 +44,12 @@ export default function load() { mixin.status_url = `${mixin.scheme}://${mixin.host}/status`; mixin.drive_url = `${mixin.scheme}://${mixin.host}/files`; + if (config.localDriveCapacityMb == null) config.localDriveCapacityMb = 256; + if (config.remoteDriveCapacityMb == null) config.remoteDriveCapacityMb = 8; + return Object.assign(config, mixin); } function normalizeUrl(url: string) { return url[url.length - 1] === '/' ? url.substr(0, url.length - 1) : url; } - -function urlError(url: string) { - console.error(`「${url}」は、正しいURLではありません。先頭に http:// または https:// をつけ忘れてないかなど確認してください。`); - process.exit(99); -} diff --git a/src/config/types.ts b/src/config/types.ts index 49eeac508b..f220e15822 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -14,6 +14,8 @@ export type Source = { * メンテナの連絡先(URLかmailto形式のURL) */ url: string; + repository_url?: string; + feedback_url?: string; }; name?: string; description?: string; @@ -34,18 +36,27 @@ export type Source = { pass: string; }; elasticsearch: { - enable: boolean; host: string; port: number; pass: string; }; - recaptcha: { + recaptcha?: { site_key: string; secret_key: string; }; + localDriveCapacityMb: number; + remoteDriveCapacityMb: number; preventCacheRemoteFiles: boolean; + drive?: { + storage: string; + bucket?: string; + prefix?: string; + baseUrl?: string; + config?: any; + }; + /** * ゴーストアカウントのID */ @@ -81,6 +92,8 @@ export type Source = { }; google_maps_api_key: string; + + clusterLimit?: number; }; /** diff --git a/src/daemons/notes-stats.ts b/src/daemons/notes-stats.ts index 021e6d64a7..136ccb60c2 100644 --- a/src/daemons/notes-stats.ts +++ b/src/daemons/notes-stats.ts @@ -17,4 +17,9 @@ export default function() { ev.on('requestNotesStatsLog', id => { ev.emit('notesStatsLog:' + id, log); }); + + process.on('exit', code => { + process.kill(p.pid); + }); + } diff --git a/src/daemons/server-stats.ts b/src/daemons/server-stats.ts index 5c793c6624..0c0a72f747 100644 --- a/src/daemons/server-stats.ts +++ b/src/daemons/server-stats.ts @@ -1,7 +1,8 @@ import * as os from 'os'; -const osUtils = require('os-utils'); +import * as sysUtils from 'systeminformation'; import * as diskusage from 'diskusage'; import Xev from 'xev'; +const osUtils = require('os-utils'); const ev = new Xev(); @@ -18,25 +19,58 @@ export default function() { }); async function tick() { - osUtils.cpuUsage((cpuUsage: number) => { - const disk = diskusage.checkSync(os.platform() == 'win32' ? 'c:' : '/'); - const stats = { - cpu_usage: cpuUsage, - mem: { - total: os.totalmem(), - free: os.freemem() - }, - disk, - os_uptime: os.uptime(), - process_uptime: process.uptime() - }; - ev.emit('serverStats', stats); - log.push(stats); - if (log.length > 50) log.shift(); - }); + const cpu = await cpuUsage(); + const usedmem = await usedMem(); + const totalmem = await totalMem(); + const disk = diskusage.checkSync(os.platform() == 'win32' ? 'c:' : '/'); + + const stats = { + cpu_usage: cpu, + mem: { + total: totalmem, + used: usedmem + }, + disk, + os_uptime: os.uptime(), + process_uptime: process.uptime() + }; + ev.emit('serverStats', stats); + log.push(stats); + if (log.length > 50) log.shift(); } tick(); setInterval(tick, interval); } + +// CPU STAT +function cpuUsage() { + return new Promise((res, rej) => { + osUtils.cpuUsage((cpuUsage: number) => { + res(cpuUsage); + }); + }); +} + +// MEMORY(excl buffer + cache) STAT +async function usedMem() { + try { + const data = await sysUtils.mem(); + return data.active; + } catch (error) { + console.error(error); + throw error; + } +} + +// TOTAL MEMORY STAT +async function totalMem() { + try { + const data = await sysUtils.mem(); + return data.total; + } catch (error) { + console.error(error); + throw error; + } +} diff --git a/src/db/elasticsearch.ts b/src/db/elasticsearch.ts index 957b7ad97d..4acff40793 100644 --- a/src/db/elasticsearch.ts +++ b/src/db/elasticsearch.ts @@ -1,22 +1,64 @@ import * as elasticsearch from 'elasticsearch'; import config from '../config'; -// Init ElasticSearch connection -const client = new elasticsearch.Client({ - host: `${config.elasticsearch.host}:${config.elasticsearch.port}` -}); - -// Send a HEAD request -client.ping({ - // Ping usually has a 3000ms timeout - requestTimeout: Infinity, - - // Undocumented params are appended to the query string - hello: 'elasticsearch!' -} as any, error => { - if (error) { - console.error('elasticsearch is down!'); +const index = { + settings: { + analysis: { + analyzer: { + bigram: { + tokenizer: 'bigram_tokenizer' + } + }, + tokenizer: { + bigram_tokenizer: { + type: 'nGram', + min_gram: 2, + max_gram: 2 + } + } + } + }, + mappings: { + note: { + properties: { + text: { + type: 'text', + index: true, + analyzer: 'bigram' + } + } + } } -}); +}; + +// Init ElasticSearch connection +const client = config.elasticsearch ? new elasticsearch.Client({ + host: `${config.elasticsearch.host}:${config.elasticsearch.port}` +}) : null; + +if (client) { + // Send a HEAD request + client.ping({ + // Ping usually has a 3000ms timeout + requestTimeout: 30000 + }, error => { + if (error) { + console.error('elasticsearch is down!'); + } else { + console.log('elasticsearch is available!'); + } + }); + + client.indices.exists({ + index: 'misskey' + }).then(exist => { + if (exist) return; + + client.indices.create({ + index: 'misskey', + body: index + }); + }); +} export default client; diff --git a/src/db/mongodb.ts b/src/db/mongodb.ts index 0df87ea3a4..034473b0d3 100644 --- a/src/db/mongodb.ts +++ b/src/db/mongodb.ts @@ -27,7 +27,7 @@ const nativeDbConn = async (): Promise<mongodb.Db> => { if (mdb) return mdb; const db = await ((): Promise<mongodb.Db> => new Promise((resolve, reject) => { - (mongodb as any).MongoClient.connect(uri, (e: Error, client: any) => { + mongodb.MongoClient.connect(uri, { useNewUrlParser: true }, (e: Error, client: any) => { if (e) return reject(e); resolve(client.db(config.mongodb.db)); }); diff --git a/src/docs/about.en.md b/src/docs/about.en.md new file mode 100644 index 0000000000..bb1c51927b --- /dev/null +++ b/src/docs/about.en.md @@ -0,0 +1,3 @@ +# About Misskey + +Misskey is a mini blog SNS. diff --git a/src/docs/about.ja.md b/src/docs/about.ja.md new file mode 100644 index 0000000000..1b06361f0f --- /dev/null +++ b/src/docs/about.ja.md @@ -0,0 +1,3 @@ +# Misskeyについて + +MisskeyはミニブログSNSです。 diff --git a/src/docs/api.ja.md b/src/docs/api.ja.md new file mode 100644 index 0000000000..ecc80cc05e --- /dev/null +++ b/src/docs/api.ja.md @@ -0,0 +1,80 @@ +# Misskey API + +MisskeyのWeb APIを使って、プログラムからMisskeyの様々な機能にアクセスすることができます。 +APIを自分のアカウントから利用する場合(自分のアカウントのみ操作したい場合)と、アプリケーションから利用する場合(不特定のアカウントを操作したい場合)とで利用手順が異なりますので、それぞれのケースについて説明します。 + +## 自分の所有するアカウントからAPIにアクセスする場合 +「設定 > API」で、APIにアクセスするのに必要なAPIキーを取得してください。 +APIにアクセスする際には、リクエストにAPIキーを「i」というパラメータ名で含めます。 + +<div class="ui info warn"> + <p><i class="fas fa-exclamation-triangle"></i> アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。</p> +</div> + +APIの詳しい使用法は「Misskey APIの利用」セクションをご覧ください。 + +## アプリケーションからAPIにアクセスする場合 +直接ユーザーのAPIキーをアプリケーションが扱うのは危険なので、 +アプリケーションからAPIを利用する際には、アプリケーションとアプリケーションを利用するユーザーが結び付けられた専用のトークン(アクセストークン)をMisskeyに発行してもらい、 +そのトークンをリクエストのパラメータに含める必要があります。 + +<div class="ui info"> + <p><i class="fas fa-info-circle"></i> アクセストークンは、ユーザーが自分のアカウントにあなたのアプリケーションがアクセスすることを許可した場合のみ発行されます</p> +</div> + +### 1.アプリケーションを登録する +まず、あなたのアプリケーションやWebサービス(以後、あなたのアプリと呼びます)をMisskeyに登録します。 +[デベロッパーセンター](/dev)にアクセスし、「アプリ > アプリ作成」からアプリを作成してください。 +フォームの記入欄の説明は以下の通りです: + +| 名前 | 説明 | +|---|---| +| アプリケーション名 | あなたのアプリの名称。 | +| アプリの概要 | あなたのアプリの簡単な説明や紹介。 | +| コールバックURL | ユーザーが後述する認証フォームで認証を終えた際にリダイレクトするURLを設定できます。あなたのアプリがWebサービスである場合に有用です。 | +| 権限 | あなたのアプリが要求する権限。ここで要求した機能だけがAPIからアクセスできます。 | + +登録が済むとあなたのアプリのシークレットキーが入手できます。このシークレットキーは後で使用します。 + +<div class="ui info warn"> + <p><i class="fas fa-exclamation-triangle"></i> アプリに成りすまされる可能性があるため、極力このシークレットキーは公開しないようにしてください。</p> +</div> + +### 2.ユーザーに認証させる +アプリを使ってもらうには、ユーザーにアカウントへのアクセスの許可をもらう必要があります。 + +認証セッションを開始するには、%API_URL%/auth/session/generate へパラメータに appSecret としてシークレットキーを含めたリクエストを送信します。 +リクエスト形式はJSONで、メソッドはPOSTです。 +レスポンスとして認証セッションのトークンや認証フォームのURLが取得できるので、認証フォームのURLをブラウザで表示し、ユーザーにフォームを提示してください。 + +あなたのアプリがコールバックURLを設定している場合、 +ユーザーがあなたのアプリの連携を許可すると設定しているコールバックURLに token という名前でセッションのトークンが含まれたクエリを付けてリダイレクトします。 + +あなたのアプリがコールバックURLを設定していない場合、ユーザーがあなたのアプリの連携を許可したことを(何らかの方法で(たとえばボタンを押させるなど))確認出来るようにしてください。 + +### 3.ユーザーのアクセストークンを取得する +ユーザーが連携を許可したら、%API_URL%/auth/session/userkey へ次のパラメータを含むリクエストを送信します: + +| 名前 | 型 | 説明 | +|---|---|---| +| appSecret | string | アプリのシークレットキー | +| token | string | セッションのトークン | + +上手くいけば、認証したユーザーのアクセストークンがレスポンスとして取得できます。おめでとうございます! + +アクセストークンが取得できたら、「ユーザーのアクセストークン+あなたのアプリのシークレットキーをsha256したもの」を「i」というパラメータでリクエストに含めると、APIにアクセスすることができます。 + +「i」パラメータの生成方法を擬似コードで表すと次のようになります: +<pre><code>const i = sha256(accessToken + secretKey);</code></pre> + +APIの詳しい使用法は「Misskey APIの利用」セクションをご覧ください。 + +## Misskey APIの利用 +APIはすべてリクエストのパラメータ・レスポンスともにJSON形式です。また、すべてのエンドポイントはPOSTメソッドのみ受け付けます。 + +ストリーミングAPIも提供しています。 + +APIリファレンスもご確認ください。 + +### レートリミット +Misskey APIにはレートリミットがあり、短時間のうちに多数のリクエストを送信すると、一定時間APIを利用することができなくなることがあります。 diff --git a/src/client/docs/api/endpoints/style.styl b/src/docs/api/endpoints/style.styl similarity index 87% rename from src/client/docs/api/endpoints/style.styl rename to src/docs/api/endpoints/style.styl index 2af9fe9a77..e7e32b3395 100644 --- a/src/client/docs/api/endpoints/style.styl +++ b/src/docs/api/endpoints/style.styl @@ -6,12 +6,14 @@ color #fff background #222e40 border-radius 4px + overflow auto + white-space nowrap > .method display inline-block margin 0 8px 0 0 padding 0 6px - color #f4fcff + color #fff background #17afc7 border-radius 4px user-select none diff --git a/src/docs/api/endpoints/view.pug b/src/docs/api/endpoints/view.pug new file mode 100644 index 0000000000..76e1183302 --- /dev/null +++ b/src/docs/api/endpoints/view.pug @@ -0,0 +1,76 @@ +extends ../../base +include ../mixins + +block meta + link(rel="stylesheet" href="/docs/assets/api/endpoints/style.css") + +block main + h1= title + + p#url + span.method POST + span.host + = endpointUrl.host + | / + span.path= endpointUrl.path + + if endpoint.desc + p#desc= endpoint.desc[lang] || endpoint.desc['ja'] + + if endpoint.requireCredential + div.ui.info: p + i.fas.fa-id-card-alt(style="margin-right: 4px") + = i18n('docs.api.endpoints.require-credential') + + if endpoint.kind + div.ui.info: p + i.fas.fa-unlock-alt(style="margin-right: 4px") + != i18n('docs.api.endpoints.require-permission').replace('{permission}', `<code>${endpoint.kind}</code>`) + + if endpoint.limit + div.ui.info.warn: p + i.far.fa-clock(style="margin-right: 4px") + b!= i18n('docs.api.endpoints.has-limit') + if endpoint.limit.duration + != i18n('docs.api.endpoints.duration-limit').replace('{duration}', endpoint.limit.duration).replace('{max}', endpoint.limit.max) + if endpoint.limit.minInterval + != i18n('docs.api.endpoints.min-interval-limit').replace('{interval}', endpoint.limit.minInterval) + + if params && Object.keys(params).length > 0 + section + h2= i18n('docs.api.endpoints.params') + +propTable(params) + + if paramDefs + each paramDef in paramDefs + section(id= paramDef.name) + h3= paramDef.name + +propTable(paramDef.params) + if params && Object.keys(params).length == 0 + section + h2= i18n('docs.api.endpoints.params') + p= i18n('docs.api.endpoints.no-params') + + if res + section + h2= i18n('docs.api.endpoints.res') + + if resProps + +propTable(resProps) + + if resDefs + each resDef in resDefs + section(id= resDef.name) + h3= resDef.name + +propTable(resDef.props) + else + if res.type.startsWith('entity') + a(href=`/docs/${lang}/api/entities/${kebab(res.entity)}`)= res.entity + +block footer + div.ui.info: p + i.fas.fa-info-circle(style="margin-right: 4px") + = i18n('docs.api.endpoints.generated') + p + = i18n('docs.api.endpoints.show-src') + a(href=src target="_blank")= i18n('docs.api.endpoints.show-src-link') diff --git a/src/client/docs/api/entities/drive-file.yaml b/src/docs/api/entities/drive-file.yaml similarity index 83% rename from src/client/docs/api/entities/drive-file.yaml rename to src/docs/api/entities/drive-file.yaml index 02ab0d608e..2d14c6e1f5 100644 --- a/src/client/docs/api/entities/drive-file.yaml +++ b/src/docs/api/entities/drive-file.yaml @@ -5,69 +5,86 @@ desc: en: "A file of Drive." props: - - name: "id" + id: type: "id" optional: false desc: ja: "ファイルID" en: "The ID of this file" - - name: "createdAt" + + createdAt: type: "date" optional: false desc: ja: "アップロード日時" en: "The upload date of this file" - - name: "userId" + + userId: type: "id(User)" optional: false desc: ja: "所有者ID" en: "The ID of the owner of this file" - - name: "user" + + user: type: "entity(User)" optional: true desc: ja: "所有者" en: "The owner of this file" - - name: "name" + + name: type: "string" optional: false desc: ja: "ファイル名" en: "The name of this file" - - name: "md5" + + md5: type: "string" optional: false desc: ja: "ファイルのMD5ハッシュ値" en: "The md5 hash value of this file" - - name: "type" + + type: type: "string" optional: false desc: ja: "ファイルの種類" en: "The type of this file" - - name: "datasize" + + datasize: type: "number" optional: false desc: ja: "ファイルサイズ(bytes)" en: "The size of this file (bytes)" - - name: "url" + + url: type: "string" optional: false desc: ja: "ファイルのURL" en: "The URL of this file" - - name: "folderId" + + folderId: type: "id(DriveFolder)" optional: true desc: ja: "フォルダID" en: "The ID of the folder of this file" - - name: "folder" + + folder: type: "entity(DriveFolder)" optional: true desc: ja: "フォルダ" en: "The folder of this file" + + sensitive: + type: "boolean" + optional: true + desc: + ja: "このメディアが「閲覧注意」(NSFW)かどうか" + en: "Whether this media is NSFW" diff --git a/src/client/docs/api/entities/note.yaml b/src/docs/api/entities/note.yaml similarity index 82% rename from src/client/docs/api/entities/note.yaml rename to src/docs/api/entities/note.yaml index 6fd26543bb..04cb3c9824 100644 --- a/src/client/docs/api/entities/note.yaml +++ b/src/docs/api/entities/note.yaml @@ -5,163 +5,185 @@ desc: en: "A note." props: - - name: "id" + id: type: "id" optional: false desc: ja: "投稿ID" en: "The ID of this note" - - name: "createdAt" + + createdAt: type: "date" optional: false desc: ja: "投稿日時" en: "The posted date of this note" - - name: "viaMobile" + + viaMobile: type: "boolean" optional: true desc: ja: "モバイル端末から投稿したか否か(自己申告であることに留意)" en: "Whether this note sent via a mobile device" - - name: "text" + + text: type: "string" optional: true desc: - ja: "投稿の本文 (ローカルの場合Markdown風のフォーマット)" - en: "The text of this note (in Markdown like format if local)" - - name: "mediaIds" + ja: "投稿の本文" + en: "The text of this note" + + mediaIds: type: "id(DriveFile)[]" optional: true desc: ja: "添付されているメディアのID (なければレスポンスでは空配列)" en: "The IDs of the attached media (empty array for response if no media is attached)" - - name: "media" + + media: type: "entity(DriveFile)[]" optional: true desc: ja: "添付されているメディア" en: "The attached media" - - name: "userId" + + userId: type: "id(User)" optional: false desc: ja: "投稿者ID" en: "The ID of author of this note" - - name: "user" + + user: type: "entity(User)" optional: true desc: ja: "投稿者" en: "The author of this note" - - name: "myReaction" + + myReaction: type: "string" optional: true desc: ja: "この投稿に対する自分の<a href='/docs/api/reactions'>リアクション</a>" en: "The your <a href='/docs/api/reactions'>reaction</a> of this note" - - name: "reactionCounts" + + reactionCounts: type: "object" optional: false desc: ja: "<a href='/docs/api/reactions'>リアクション</a>をキーとし、この投稿に対するそのリアクションの数を値としたオブジェクト" - - name: "replyId" + + replyId: type: "id(Note)" optional: true desc: ja: "返信した投稿のID" en: "The ID of the replyed note" - - name: "reply" + + reply: type: "entity(Note)" optional: true desc: ja: "返信した投稿" en: "The replyed note" - - name: "renoteId" + + renoteId: type: "id(Note)" optional: true desc: ja: "引用した投稿のID" en: "The ID of the quoted note" - - name: "renote" + + renote: type: "entity(Note)" optional: true desc: ja: "引用した投稿" en: "The quoted note" - - name: "poll" + + poll: type: "object" optional: true desc: ja: "投票" en: "The poll" - defName: "poll" - def: - - name: "choices" + + props: + choices: type: "object[]" optional: false desc: ja: "投票の選択肢" en: "The choices of this poll" - defName: "choice" - def: - - name: "id" + + props: + id: type: "number" optional: false desc: ja: "選択肢ID" en: "The ID of this choice" - - name: "isVoted" + + isVoted: type: "boolean" optional: true desc: ja: "自分がこの選択肢に投票したかどうか" en: "Whether you voted to this choice" - - name: "text" + + text: type: "string" optional: false desc: ja: "選択肢本文" en: "The text of this choice" - - name: "votes" + + votes: type: "number" optional: false desc: ja: "この選択肢に投票された数" en: "The number voted for this choice" - - name: "geo" + geo: type: "object" optional: true desc: ja: "位置情報" en: "Geo location" - defName: "geo" - def: - - name: "coordinates" + + props: + coordinates: type: "number[]" optional: false desc: ja: "座標。最初に経度:-180〜180で表す。最後に緯度:-90〜90で表す。" - - name: "altitude" + + altitude: type: "number" optional: false desc: ja: "高度。メートル単位で表す。" - - name: "accuracy" + + accuracy: type: "number" optional: false desc: ja: "緯度、経度の精度。メートル単位で表す。" - - name: "altitudeAccuracy" + + altitudeAccuracy: type: "number" optional: false desc: ja: "高度の精度。メートル単位で表す。" - - name: "heading" + + heading: type: "number" optional: false desc: ja: "方角。0〜360の角度で表す。0が北、90が東、180が南、270が西。" - - name: "speed" + + speed: type: "number" optional: false desc: diff --git a/src/client/docs/api/entities/style.styl b/src/docs/api/entities/style.styl similarity index 100% rename from src/client/docs/api/entities/style.styl rename to src/docs/api/entities/style.styl diff --git a/src/client/docs/api/entities/user.yaml b/src/docs/api/entities/user.yaml similarity index 54% rename from src/client/docs/api/entities/user.yaml rename to src/docs/api/entities/user.yaml index cccf42f221..c245974568 100644 --- a/src/client/docs/api/entities/user.yaml +++ b/src/docs/api/entities/user.yaml @@ -5,169 +5,170 @@ desc: en: "A user." props: - - name: "id" + id: type: "id" optional: false desc: ja: "ユーザーID" en: "The ID of this user" - - name: "createdAt" + + createdAt: type: "date" optional: false desc: ja: "アカウント作成日時" en: "The registered date of this user" - - name: "username" + + username: type: "string" optional: false desc: ja: "ユーザー名" en: "The username of this user" - - name: "description" + + description: type: "string" optional: false desc: ja: "アカウントの説明(自己紹介)" en: "The description of this user" - - name: "avatarId" + + avatarId: type: "id(DriveFile)" optional: true desc: ja: "アバターのID" en: "The ID of the avatar of this user" - - name: "avatarUrl" + + avatarUrl: type: "string" optional: false desc: ja: "アバターのURL" en: "The URL of the avatar of this user" - - name: "bannerId" + + bannerId: type: "id(DriveFile)" optional: true desc: ja: "バナーのID" en: "The ID of the banner of this user" - - name: "bannerUrl" + + bannerUrl: type: "string" optional: false desc: ja: "バナーのURL" en: "The URL of the banner of this user" - - name: "followersCount" + + followersCount: type: "number" optional: false desc: ja: "フォロワーの数" en: "The number of the followers for this user" - - name: "followingCount" + + followingCount: type: "number" optional: false desc: ja: "フォローしているユーザーの数" en: "The number of the following users for this user" - - name: "isFollowing" + + isFollowing: type: "boolean" optional: true desc: ja: "自分がこのユーザーをフォローしているか" - - name: "isFollowed" + + isFollowed: type: "boolean" optional: true desc: ja: "自分がこのユーザーにフォローされているか" - - name: "isMuted" + + isMuted: type: "boolean" optional: true desc: ja: "自分がこのユーザーをミュートしているか" en: "Whether you muted this user" - - name: "notesCount" + + notesCount: type: "number" optional: false desc: ja: "投稿の数" en: "The number of the notes of this user" - - name: "pinnedNote" + + pinnedNote: type: "entity(Note)" optional: true desc: ja: "ピン留めされた投稿" en: "The pinned note of this user" - - name: "pinnedNoteId" + + pinnedNoteId: type: "id(Note)" optional: true desc: ja: "ピン留めされた投稿のID" en: "The ID of the pinned note of this user" - - name: "driveCapacity" - type: "number" - optional: false - desc: - ja: "ドライブの容量(bytes)" - en: "The capacity of drive of this user (bytes)" - - name: "host" + + host: type: "string | null" optional: false desc: ja: "ホスト (例: example.com:3000)" en: "Host (e.g. example.com:3000)" - - name: "account" + + twitter: + type: "object" + optional: true + desc: + ja: "連携されているTwitterアカウント情報" + en: "The info of the connected twitter account of this user" + + props: + userId: + type: "string" + optional: false + desc: + ja: "ユーザーID" + en: "The user ID" + + screenName: + type: "string" + optional: false + desc: + ja: "ユーザー名" + en: "The screen name of this user" + + isBot: + type: "boolean" + optional: true + desc: + ja: "botか否か(自己申告であることに留意)" + en: "Whether is bot or not" + + profile: type: "object" optional: false desc: - ja: "このサーバーにおけるアカウント" - en: "The account of this user on this server" - defName: "account" - def: - - name: "lastUsedAt" - type: "date" - optional: false - desc: - ja: "最終利用日時" - en: "The last used date of this user" - - name: "isBot" - type: "boolean" + ja: "プロフィール" + en: "The profile of this user" + + props: + location: + type: "string" optional: true desc: - ja: "botか否か(自己申告であることに留意)" - en: "Whether is bot or not" - - name: "twitter" - type: "object" + ja: "場所" + en: "The location of this user" + + birthday: + type: "string" optional: true desc: - ja: "連携されているTwitterアカウント情報" - en: "The info of the connected twitter account of this user" - defName: "twitter" - def: - - name: "userId" - type: "string" - optional: false - desc: - ja: "ユーザーID" - en: "The user ID" - - name: "screenName" - type: "string" - optional: false - desc: - ja: "ユーザー名" - en: "The screen name of this user" - - name: "profile" - type: "object" - optional: false - desc: - ja: "プロフィール" - en: "The profile of this user" - defName: "profile" - def: - - name: "location" - type: "string" - optional: true - desc: - ja: "場所" - en: "The location of this user" - - name: "birthday" - type: "string" - optional: true - desc: - ja: "誕生日 (YYYY-MM-DD)" - en: "The birthday of this user (YYYY-MM-DD)" + ja: "誕生日 (YYYY-MM-DD)" + en: "The birthday of this user (YYYY-MM-DD)" diff --git a/src/client/docs/api/entities/view.pug b/src/docs/api/entities/view.pug similarity index 74% rename from src/client/docs/api/entities/view.pug rename to src/docs/api/entities/view.pug index ac938151a7..d5c192f438 100644 --- a/src/client/docs/api/entities/view.pug +++ b/src/docs/api/entities/view.pug @@ -1,4 +1,4 @@ -extends ../../layout.pug +extends ../../base include ../mixins block meta @@ -10,11 +10,11 @@ block main p#desc= desc[lang] || desc['ja'] section - h2 %i18n:docs.api.entities.properties% + h2= i18n('docs.api.entities.properties') +propTable(props) if propDefs each propDef in propDefs section(id= propDef.name) h3= propDef.name - +propTable(propDef.params) + +propTable(propDef.props) diff --git a/src/docs/api/mixins.pug b/src/docs/api/mixins.pug new file mode 100644 index 0000000000..925aab2934 --- /dev/null +++ b/src/docs/api/mixins.pug @@ -0,0 +1,34 @@ +mixin type(prop) + i= prop.type + if prop.kind == 'id' + if prop.entity + | ( + a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity + | ID) + else + | (ID) + else if prop.kind == 'entity' + | ( + a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity + | ) + else if prop.kind == 'object' + if prop.hasDef + | ( + a(href=`#${prop.name}`)= prop.name + | ) + else if prop.kind == 'date' + | (Date) + +mixin propTable(props) + table.props + thead: tr + th= i18n('docs.api.props.name') + th= i18n('docs.api.props.type') + th= i18n('docs.api.props.description') + tbody + each prop in props + tr + td.name= prop.name + td.type + +type(prop) + td.desc!= prop.desc ? prop.desc[lang] || prop.desc['ja'] : null diff --git a/src/client/docs/api/style.styl b/src/docs/api/style.styl similarity index 100% rename from src/client/docs/api/style.styl rename to src/docs/api/style.styl diff --git a/src/docs/article.pug b/src/docs/article.pug new file mode 100644 index 0000000000..38494fec6c --- /dev/null +++ b/src/docs/article.pug @@ -0,0 +1,9 @@ +extends ./base + +block main + != html + +block footer + p + = i18n('docs.edit-this-page-on-github') + a(href=src target="_blank")= i18n('docs.edit-this-page-on-github-link') diff --git a/src/docs/base.pug b/src/docs/base.pug new file mode 100644 index 0000000000..aeafaeffff --- /dev/null +++ b/src/docs/base.pug @@ -0,0 +1,61 @@ +doctype html + +html(lang= lang) + head + meta(charset="UTF-8") + meta(name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no") + title + | #{title} | Misskey Docs + link(rel="stylesheet" href="/docs/assets/style.css") + link(rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css") + script(src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js") + link(rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous") + block meta + + body + nav + ul + each doc in docs + li: a(href=`/docs/${lang}/${doc.name}`)= doc.title[lang] || doc.title['ja'] + section + h2 API + ul + li Entities + ul + each entity in entities + li: a(href=`/docs/${lang}/api/entities/${kebab(entity)}`)= entity + li Endpoints + ul + each endpoint in endpoints + li: a(href=`/docs/${lang}/api/endpoints/${kebab(endpoint.name)}`)= endpoint.name + main + article + block main + if content + | !{content} + + aside. + <div id="disqus_thread"></div> + <script> + + /** + * RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS. + * LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/ + /* + var disqus_config = function () { + this.page.url = PAGE_URL; // Replace PAGE_URL with your page's canonical URL variable + this.page.identifier = "#{ id }"; // Replace PAGE_IDENTIFIER with your page's unique identifier variable + }; + */ + (function() { // DON'T EDIT BELOW THIS LINE + var d = document, s = d.createElement('script'); + s.src = 'https://misskey.disqus.com/embed.js'; + s.setAttribute('data-timestamp', +new Date()); + (d.head || d.body).appendChild(s); + })(); + </script> + <noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> + + footer + block footer + small= copyright diff --git a/src/docs/follow.ja.md b/src/docs/follow.ja.md new file mode 100644 index 0000000000..a883435ab4 --- /dev/null +++ b/src/docs/follow.ja.md @@ -0,0 +1,8 @@ +# フォロー +ユーザーをフォローすると、タイムラインにそのユーザーの投稿が表示されるようになります。ただし、他のユーザーに対する返信は含まれません。 +ユーザーをフォローするには、ユーザーページの「フォロー」ボタンをクリックします。フォローを解除するには、もう一度クリックします。 + +## ストーキング +ユーザーをフォローしている状態では、さらに「ストーキング」モードをオンにすることができます。ストーキングを行うと、タイムラインにそのユーザーの全ての投稿が表示されるようになります。つまり、他のユーザーに対する返信も含まれることになります。 +ストーキングするには、ユーザーページの「ストークする」をクリックします。ストーキングをやめるには、もう一度クリックします。 +ストーキングしていることは相手に通知されません。 diff --git a/src/docs/mute.ja.md b/src/docs/mute.ja.md new file mode 100644 index 0000000000..6a9608662a --- /dev/null +++ b/src/docs/mute.ja.md @@ -0,0 +1,13 @@ +# ミュート + +ユーザーをミュートすると、そのユーザーに関する次のコンテンツがMisskeyに表示されなくなります: + +* タイムラインや投稿の検索結果内の、そのユーザーの投稿(およびそれらの投稿に対する返信やRenote) +* そのユーザーからの通知 +* メッセージ履歴一覧内の、そのユーザーとのメッセージ履歴 + +ユーザーをミュートするには、対象のユーザーのユーザーページに表示されている「ミュート」ボタンを押します。 + +ミュートを行ったことは相手に通知されず、ミュートされていることを知ることもできません。 + +設定>ミュート から、自分がミュートしているユーザー一覧を確認することができます。 diff --git a/src/docs/reversi-bot.ja.md b/src/docs/reversi-bot.ja.md new file mode 100644 index 0000000000..6fe62003df --- /dev/null +++ b/src/docs/reversi-bot.ja.md @@ -0,0 +1,165 @@ +# MisskeyリバーシBotの開発 +Misskeyのリバーシ機能に対応したBotの開発方法をここに記します。 + +1. `reversi`ストリームに以下のパラメータを付けて接続する: + * `i`: botアカウントのAPIキー + +2. 対局への招待が来たら、ストリームから`invited`イベントが流れてくる + * イベントの中身に、`parent`という名前で対局へ誘ってきたユーザーの情報が含まれている + +3. `reversi/match`へ、`user_id`として`parent`の`id`が含まれたリクエストを送信する + +4. 上手くいくとゲーム情報が返ってくるので、`reversi-game`ストリームへ、以下のパラメータを付けて接続する: + * `i`: botアカウントのAPIキー + * `game`: `game`の`id` + +5. この間、相手がゲームの設定を変更するとその都度`update-settings`イベントが流れてくるので、必要であれば何かしらの処理を行う + +6. 設定に満足したら、`{ type: 'accept' }`メッセージをストリームに送信する + +7. ゲームが開始すると、`started`イベントが流れてくる + * イベントの中身にはゲーム情報が含まれている + +8. 石を打つには、ストリームに`{ type: 'set', pos: <位置> }`を送信する(位置の計算方法は後述) + +9. 相手または自分が石を打つと、ストリームから`set`イベントが流れてくる + * `color`として石の色が含まれている + * `pos`として位置情報が含まれている + +## 位置の計算法 +8x8のマップを考える場合、各マスの位置(Posと呼びます)は次のようになっています: +``` ++--+--+--+--+--+--+--+--+ +| 0| 1| 2| 3| 4| 5| 6| 7| ++--+--+--+--+--+--+--+--+ +| 8| 9|10|11|12|13|14|15| ++--+--+--+--+--+--+--+--+ +|16|17|18|19|20|21|22|23| +... +``` + +### X,Y座標 から Pos に変換する +``` +pos = x + (y * mapWidth) +``` +`mapWidth`は、ゲーム情報の`settings.map`から、次のようにして計算できます: +``` +mapWidth = settings.map[0].length +``` + +### Pos から X,Y座標 に変換する +``` +x = pos % mapWidth +y = Math.floor(pos / mapWidth) +``` + +## マップ情報 +マップ情報は、ゲーム情報の`settings.map`に入っています。 +文字列の配列になっており、ひとつひとつの文字がマス情報を表しています。 +それをもとにマップのデザインを知る事が出来ます: +* `(スペース)` ... マス無し +* `-` ... マス +* `b` ... 初期配置される黒石 +* `w` ... 初期配置される白石 + +例えば、4*4の次のような単純なマップがあるとします: +```text ++---+---+---+---+ +| | | | | ++---+---+---+---+ +| | ○ | ● | | ++---+---+---+---+ +| | ● | ○ | | ++---+---+---+---+ +| | | | | ++---+---+---+---+ +``` + +この場合、マップデータはこのようになります: +```javascript +['----', '-wb-', '-bw-', '----'] +``` + +## ユーザーにフォームを提示して対話可能Botを作成する +ユーザーとのコミュニケーションを行うため、ゲームの設定画面でユーザーにフォームを提示することができます。 +例えば、Botの強さをユーザーが設定できるようにする、といったシナリオが考えられます。 + +フォームを提示するには、`reversi-game`ストリームに次のメッセージを送信します: +```javascript +{ + type: 'init-form', + body: [フォームコントロールの配列] +} +``` + +フォームコントロールの配列については今から説明します。 +フォームコントロールは、次のようなオブジェクトです: +```javascript +{ + id: 'button1', + type: 'button', + label: 'Enable hoge', + value: false +} +``` +`id` ... コントロールのID。 +`type` ... コントロールの種類。後述します。 +`label` ... コントロールと一緒に表記するテキスト。 +`value` ... コントロールのデフォルト値。 + +### フォームの操作を受け取る +ユーザーがフォームを操作すると、ストリームから`update-form`イベントが流れてきます。 +イベントの中身には、コントロールのIDと、ユーザーが設定した値が含まれています。 +例えば、上で示したボタンをユーザーがオンにしたとすると、次のイベントが流れてきます: +```javascript +{ + id: 'button1', + value: true +} +``` + +### フォームコントロールの種類 +#### ボタン +type: `button` +ボタンを表示します。何かの機能をオン/オフさせたい場合に有用です。 + +##### プロパティ +`desc` ... ボタンの詳細な説明。 + +#### ラジオボタン +type: `radio` +ラジオボタンを表示します。選択肢を提示するのに有用です。例えば、Botの強さを設定させるなどです。 + +##### プロパティ +`items` ... ラジオボタンの選択肢。例: +```javascript +items: [{ + label: '弱', + value: 1 +}, { + label: '中', + value: 2 +}, { + label: '強', + value: 3 +}] +``` + +#### テキストボックス +type: `textbox` +テキストボックスを表示します。ユーザーになにか入力させる一般的な用途に利用できます。 + +## ユーザーにメッセージを表示する +設定画面でユーザーと対話する、フォーム以外のもうひとつの方法がこれです。ユーザーになにかメッセージを表示することができます。 +例えば、ユーザーがBotの対応していないモードやマップを選択したとき、警告を表示するなどです。 +メッセージを表示するには、次のメッセージをストリームに送信します: +```javascript +{ + type: 'message', + body: { + text: 'メッセージ内容', + type: 'メッセージの種類' + } +} +``` +メッセージの種類: `success`, `info`, `warning`, `error`。 diff --git a/src/docs/stream.ja.md b/src/docs/stream.ja.md new file mode 100644 index 0000000000..c720299932 --- /dev/null +++ b/src/docs/stream.ja.md @@ -0,0 +1,183 @@ +# ストリーミングAPI + +ストリーミングAPIを使うと、リアルタイムで様々な情報(例えばタイムラインに新しい投稿が流れてきた、メッセージが届いた、フォローされた、など)を受け取ったり、HTTPリクエストを発生させることなくAPIにアクセスしたりすることができます。 + +ストリーミングAPIは複数の種類がありますが、ここではメインとなる「ホームストリーム」について説明します。 + +## ストリームに接続する + +以下のURLに**websocket**接続します。 +``` +%URL% +``` + +接続する際は、`i`というパラメータ名で認証情報を含めます。例: +``` +%URL%/?i=xxxxxxxxxxxxxxx +``` + +認証情報は、自分のAPIキーや、アプリケーションからストリームに接続する際はユーザーのアクセストークンのことを指します。 + +<div class="ui info"> + <p><i class="fas fa-info-circle"></i> 認証情報の取得については、<a href="./api">こちらのドキュメント</a>をご確認ください。</p> +</div> + + +## ストリームを経由してAPIリクエストする + +ストリームを経由してAPIリクエストすると、HTTPリクエストを発生させずにAPIを利用できます。そのため、コードを簡潔にできたり、パフォーマンスの向上を見込めるかもしれません。 + +ストリームを経由してAPIリクエストするには、次のようなメッセージをストリームに送信します: +```json +{ + type: 'api', + id: 'xxxxxxxxxxxxxxxx', + endpoint: 'notes/create', + data: { + text: 'yee haw!' + } +} +``` + +`id`には、APIのレスポンスを識別するための、APIリクエストごとの一意なIDを設定する必要があります。UUIDや、簡単な乱数のようなもので構いません。 + +`endpoint`には、あなたがリクエストしたいAPIのエンドポイントを指定します。 + +`data`には、エンドポイントのパラメータを含めます。 + +<div class="ui info"> + <p><i class="fas fa-info-circle"></i> APIのエンドポイントやパラメータについてはAPIリファレンスをご確認ください。</p> +</div> + +### レスポンスの受信 + +APIへリクエストすると、レスポンスがストリームから次のような形式で流れてきます。 + +```json +{ + type: 'api-res:xxxxxxxxxxxxxxxx', + body: { + ... + } +} +``` + +`xxxxxxxxxxxxxxxx`の部分には、リクエストの際に設定された`id`が含まれています。これにより、どのリクエストに対するレスポンスなのか判別することができます。 + +`body`には、レスポンスが含まれています。 + +## 投稿のキャプチャ + +Misskeyは投稿のキャプチャと呼ばれる仕組みを提供しています。これは、指定した投稿のイベントをストリームで受け取る機能です。 + +例えばタイムラインを取得してユーザーに表示したとします。ここで誰かがそのタイムラインに含まれるどれかの投稿に対してリアクションしたとします。 + +しかし、クライアントからするとある投稿にリアクションが付いたことなどは知る由がないため、リアルタイムでリアクションをタイムライン上の投稿に反映して表示するといったことができません。 + +この問題を解決するために、Misskeyは投稿のキャプチャ機構を用意しています。投稿をキャプチャすると、その投稿に関するイベントを受け取ることができるため、リアルタイムでリアクションを反映させたりすることが可能になります。 + +### 投稿をキャプチャする + +投稿をキャプチャするには、ストリームに次のようなメッセージを送信します: + +```json +{ + type: 'capture', + id: 'xxxxxxxxxxxxxxxx' +} +``` + +`id`には、キャプチャしたい投稿の`id`を設定します。 + +このメッセージを送信すると、Misskeyにキャプチャを要請したことになり、以後、その投稿に関するイベントが流れてくるようになります。 + +例えば投稿にリアクションが付いたとすると、次のようなメッセージが流れてきます: + +```json +{ + type: 'note-updated', + body: { + note: { + ... + } + } +} +``` + +`body`内の`note`には、その投稿の最新の情報が含まれています。 + +--- + +このように、投稿の情報が更新されると、`note-updated`イベントが流れてくるようになります。`note-updated`イベントが発生するのは、以下の場合です: + +- 投稿にリアクションが付いた +- 投稿に添付されたアンケートに投票がされた +- 投稿が削除された + +### 投稿のキャプチャを解除する + +その投稿がもう画面に表示されなくなったりして、その投稿に関するイベントをもう受け取る必要がなくなったときは、キャプチャの解除を申請してください。 + +次のメッセージを送信します: + +```json +{ + type: 'decapture', + id: 'xxxxxxxxxxxxxxxx' +} +``` + +`id`には、キャプチャを解除したい投稿の`id`を設定します。 + +このメッセージを送信すると、以後、その投稿に関するイベントは流れてこないようになります。 + +## 流れてくるイベント一覧 + +流れてくるすべてのメッセージはJSON形式で、必ず`type`というプロパティが含まれています。これにより、メッセージの種類(イベント)を判別することができます。 + +### `note` + +タイムラインに新しい投稿が流れてきたときに発生するイベントです。 + +`body`プロパティの中に、投稿情報が含まれています。 + +### `renote` + +自分の投稿がRenoteされた時に発生するイベントです。自分自身の投稿をRenoteしたときは発生しません。 + +`body`プロパティの中に、Renoteされた投稿情報が含まれています。 + +### `mention` + +誰かからメンションされたときに発生するイベントです。 + +`body`プロパティの中に、投稿情報が含まれています。 + +### `read_all_notifications` + +自分宛ての通知がすべて既読になったことを表すイベントです。このイベントを利用して、「通知があることを示すアイコン」のようなものをオフにしたりする等のケースが想定されます。 + +### `meUpdated` + +自分の情報が更新されたことを表すイベントです。 + +`body`プロパティの中に、最新の自分のアカウントの情報が含まれています。 + +### `follow` + +自分が誰かをフォローしたときに発生するイベントです。 + +`body`プロパティの中に、フォローしたユーザーの情報が含まれています。 + +### `unfollow` + +自分が誰かのフォローを解除したときに発生するイベントです。 + +`body`プロパティの中に、フォロー解除したユーザーの情報が含まれています。 + +### `followed` + +自分が誰かにフォローされたときに発生するイベントです。 + +`body`プロパティの中に、フォローしてきたユーザーの情報が含まれています。 + diff --git a/src/client/docs/style.styl b/src/docs/style.styl similarity index 77% rename from src/client/docs/style.styl rename to src/docs/style.styl index bc165f8728..b01fe493ac 100644 --- a/src/client/docs/style.styl +++ b/src/docs/style.styl @@ -1,4 +1,4 @@ -@import "../style" +@import "../client/style" @import "./ui" body @@ -7,13 +7,10 @@ body word-break break-word main - margin 0 0 0 256px + margin 0 0 0 330px padding 64px - width 100% - max-width 768px - - section - margin 32px 0 + width 850px + max-width calc(100% - 330px) h1 margin 0 0 24px 0 @@ -22,28 +19,38 @@ main border-bottom solid 2px #eee h2 - margin 0 0 24px 0 + margin 1em 0 24px 0 padding 0 0 16px 0 font-size 1.4em border-bottom solid 1px #eee h3 - margin 0 + margin 1em 0 0 0 padding 0 font-size 1.25em h4 - margin 0 + margin 1em 0 0 0 p margin 1em 0 line-height 1.6em - footer + hr + border none + border-bottom solid 2px #eee + + > aside + margin-top 32px + padding-top 32px + border-top solid 2px #eee + + > footer margin 32px 0 0 0 border-top solid 2px #eee > small + display block margin 16px 0 0 0 color #aaa @@ -53,13 +60,17 @@ nav z-index 10000 top 0 left 0 - width 256px + width 330px height 100% overflow auto padding 32px background #fff border-right solid 2px #eee + ul + padding 0 + margin 0 + @media (max-width 1025px) main margin 0 @@ -81,7 +92,6 @@ nav padding 16px table - display block width 100% max-width 100% overflow auto @@ -106,10 +116,9 @@ table min-width 128px code - display inline-block - padding 8px 10px + padding 4px 8px font-family Consolas, 'Courier New', Courier, Monaco, monospace - color #295c92 + //color #295c92 background #f2f2f2 border-radius 4px @@ -118,3 +127,4 @@ pre > code display block + padding 16px diff --git a/src/docs/timelines.ja.md b/src/docs/timelines.ja.md new file mode 100644 index 0000000000..36ba61bd2d --- /dev/null +++ b/src/docs/timelines.ja.md @@ -0,0 +1,15 @@ +# タイムラインの比較 + +https://docs.google.com/spreadsheets/d/1lxQ2ugKrhz58Bg96HTDK_2F98BUritkMyIiBkOByjHA/edit?usp=sharing + +## ホーム +自分のフォローしているユーザーの投稿 + +## ローカル +全てのローカルユーザーの「ホーム」指定されていない投稿 + +## ソーシャル +自分のフォローしているユーザーの投稿と、全てのローカルユーザーの「ホーム」指定されていない投稿 + +## グローバル +全てのローカルユーザーの「ホーム」指定されていない投稿と、サーバーに届いた全てのリモートユーザーの「ホーム」指定されていない投稿 diff --git a/src/client/docs/ui.styl b/src/docs/ui.styl similarity index 100% rename from src/client/docs/ui.styl rename to src/docs/ui.styl diff --git a/src/drive/gen-thumbnail.ts b/src/drive/gen-thumbnail.ts deleted file mode 100644 index 455705cd3a..0000000000 --- a/src/drive/gen-thumbnail.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as stream from 'stream'; -import * as Gm from 'gm'; -import { IDriveFile, getDriveFileBucket } from '../models/drive-file'; - -const gm = Gm.subClass({ - imageMagick: true -}); - -export default async function(file: IDriveFile): Promise<stream.Readable> { - if (!/^image\/.*$/.test(file.contentType)) return null; - - const bucket = await getDriveFileBucket(); - const readable = bucket.openDownloadStream(file._id); - - const g = gm(readable); - - const stream = g - .resize(256, 256) - .compress('jpeg') - .quality(70) - .interlace('line') - .stream(); - - return stream; -} diff --git a/src/reversi/core.ts b/src/games/reversi/core.ts similarity index 99% rename from src/reversi/core.ts rename to src/games/reversi/core.ts index 37f62a43d5..92b7c3799c 100644 --- a/src/reversi/core.ts +++ b/src/games/reversi/core.ts @@ -1,3 +1,5 @@ +// MISSKEY REVERSI ENGINE + /** * true ... 黒 * false ... 白 @@ -18,7 +20,7 @@ export type Undo = { /** * 色 */ - color: Color, + color: Color; /** * どこに打ったか diff --git a/src/reversi/maps.ts b/src/games/reversi/maps.ts similarity index 100% rename from src/reversi/maps.ts rename to src/games/reversi/maps.ts diff --git a/src/index.ts b/src/index.ts index c89252dfc2..18eff8176c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,59 +8,68 @@ import * as os from 'os'; import * as cluster from 'cluster'; import * as debug from 'debug'; import chalk from 'chalk'; -// import portUsed = require('tcp-port-used'); +import * as portscanner from 'portscanner'; import isRoot = require('is-root'); import Xev from 'xev'; +import * as program from 'commander'; -import Logger from './utils/logger'; -import ProgressBar from './utils/cli/progressbar'; -import EnvironmentInfo from './utils/environmentInfo'; -import MachineInfo from './utils/machineInfo'; -import DependencyInfo from './utils/dependencyInfo'; +import Logger from './misc/logger'; +import ProgressBar from './misc/cli/progressbar'; +import EnvironmentInfo from './misc/environmentInfo'; +import MachineInfo from './misc/machineInfo'; +import DependencyInfo from './misc/dependencyInfo'; import serverStats from './daemons/server-stats'; import notesStats from './daemons/notes-stats'; - import loadConfig from './config/load'; import { Config } from './config/types'; -import parseOpt from './parse-opt'; - const clusterLog = debug('misskey:cluster'); const ev = new Xev(); -process.title = 'Misskey'; - if (process.env.NODE_ENV != 'production') { - process.env.DEBUG = 'misskey:*'; + debug.enable('misskey'); } -// https://github.com/Automattic/kue/issues/822 -require('events').EventEmitter.prototype._maxListeners = 512; +const pkg = require('../package.json'); + +//#region Command line argument definitions +program + .version(pkg.version) + .option('--no-daemons', 'Disable daemon processes (for debbuging)') + .option('--disable-clustering', 'Disable clustering') + .parse(process.argv); +//#endregion -// Start app main(); /** * Init process */ function main() { - const opt = parseOpt(process.argv, 2); + process.title = `Misskey (${ cluster.isMaster ? 'master' : 'worker' })`; - if (cluster.isMaster) { - masterMain(opt); + if (cluster.isMaster || program.disableClustering) { + masterMain(); - ev.mount(); - serverStats(); - notesStats(); - } else { - workerMain(opt); + if (cluster.isMaster) { + ev.mount(); + } + + if (program.daemons) { + serverStats(); + notesStats(); + } + } + + if (cluster.isWorker || program.disableClustering) { + workerMain(); } } /** * Init master process */ -async function masterMain(opt: any) { +async function masterMain() { let config: Config; try { @@ -68,42 +77,31 @@ async function masterMain(opt: any) { config = await init(); } catch (e) { console.error(e); - Logger.error(chalk.red('Fatal error occurred during initializing :(')); + Logger.error('Fatal error occurred during initialization'); process.exit(1); } - Logger.info(chalk.green('Successfully initialized :)')); + Logger.succ('Misskey initialized'); - spawnWorkers(() => { - if (!opt['only-processor']) { - Logger.info(chalk.bold.green( - `Now listening on port ${chalk.underline(config.port.toString())}`)); + if (!program.disableClustering) { + await spawnWorkers(config.clusterLimit); + Logger.succ('All workers started'); + } - Logger.info(chalk.bold.green(config.url)); - } - - if (!opt['only-server']) { - Logger.info(chalk.bold.green('Now processing jobs')); - } - }); + Logger.info(`Now listening on port ${config.port} on ${config.url}`); } /** * Init worker process */ -async function workerMain(opt: any) { - if (!opt['only-processor']) { - // start server - await require('./server').default(); - } +async function workerMain() { + // start server + await require('./server').default(); - if (!opt['only-server']) { - // start processor - require('./queue').default(); + if (cluster.isWorker) { + // Send a 'ready' message to parent process + process.send('ready'); } - - // Send a 'ready' message to parent process - process.send('ready'); } /** @@ -111,10 +109,10 @@ async function workerMain(opt: any) { */ async function init(): Promise<Config> { Logger.info('Welcome to Misskey!'); - Logger.info('Initializing...'); - EnvironmentInfo.show(); + (new Logger('Deps')).info(`Node.js ${process.version}`); MachineInfo.show(); + EnvironmentInfo.show(); new DependencyInfo().showAll(); const configLogger = new Logger('Config'); @@ -123,58 +121,74 @@ async function init(): Promise<Config> { try { config = loadConfig(); } catch (exception) { - if (exception.code === 'ENOENT') { - throw 'Configuration not found - Please run "npm run config" command.'; + if (typeof exception === 'string') { + configLogger.error(exception); + process.exit(1); + } + if (exception.code === 'ENOENT') { + configLogger.error('Configuration file not found'); + process.exit(1); } - throw exception; } - configLogger.info('Successfully loaded'); - configLogger.info(`maintainer: ${config.maintainer}`); + configLogger.succ('Loaded'); if (process.platform === 'linux' && !isRoot() && config.port < 1024) { - throw 'You need root privileges to listen on port below 1024 on Linux'; + Logger.error('You need root privileges to listen on port below 1024 on Linux'); + process.exit(1); } - // Check if a port is being used - /* https://github.com/stdarg/tcp-port-used/issues/3 - if (await portUsed.check(config.port)) { - throw `Port ${config.port} is already used`; + if (await portscanner.checkPortStatus(config.port, '127.0.0.1') === 'open') { + Logger.error(`Port ${config.port} is already in use`); + process.exit(1); } - */ // Try to connect to MongoDB - const mongoDBLogger = new Logger('MongoDB'); - const db = require('./db/mongodb').default; - mongoDBLogger.info('Successfully connected'); - db.close(); + checkMongoDb(config); return config; } -function spawnWorkers(onComplete: Function) { - // Count the machine's CPUs - const cpuCount = os.cpus().length; +function checkMongoDb(config: Config) { + const mongoDBLogger = new Logger('MongoDB'); + mongoDBLogger.info(`Host: ${config.mongodb.host}`); + mongoDBLogger.info(`Port: ${config.mongodb.port}`); + mongoDBLogger.info(`DB: ${config.mongodb.db}`); + if (config.mongodb.user) mongoDBLogger.info(`User: ${config.mongodb.user}`); + if (config.mongodb.pass) mongoDBLogger.info(`Pass: ****`); + require('./db/mongodb'); + mongoDBLogger.succ('Connectivity confirmed'); +} - const progress = new ProgressBar(cpuCount, 'Starting workers'); +function spawnWorkers(limit: number) { + return new Promise(res => { + // Count the machine's CPUs + const cpuCount = os.cpus().length; - // Create a worker for each CPU - for (let i = 0; i < cpuCount; i++) { - const worker = cluster.fork(); - worker.on('message', message => { - if (message === 'ready') { - progress.increment(); - } + const count = limit || cpuCount; + + const progress = new ProgressBar(count, 'Starting workers'); + + // Create a worker for each CPU + for (let i = 0; i < count; i++) { + const worker = cluster.fork(); + worker.on('message', message => { + if (message === 'ready') { + progress.increment(); + } + }); + } + + // On all workers started + progress.on('complete', () => { + res(); }); - } - - // On all workers started - progress.on('complete', () => { - onComplete(); }); } +//#region Events + // Listen new workers cluster.on('fork', worker => { clusterLog(`Process forked: [${worker.id}]`); @@ -203,5 +217,7 @@ process.on('uncaughtException', err => { // Dying away... process.on('exit', code => { - Logger.info(`The process is going exit (${code})`); + Logger.info(`The process is going to exit with code ${code}`); }); + +//#endregion diff --git a/src/mfm/html-to-mfm.ts b/src/mfm/html-to-mfm.ts index 540635036a..daa228ec51 100644 --- a/src/mfm/html-to-mfm.ts +++ b/src/mfm/html-to-mfm.ts @@ -1,6 +1,8 @@ const parse5 = require('parse5'); export default function(html: string): string { + if (html == null) return null; + const dom = parse5.parseFragment(html); let text = ''; diff --git a/src/mfm/parse/elements/mention.ts b/src/mfm/parse/elements/mention.ts index eda60b530a..a95ec00384 100644 --- a/src/mfm/parse/elements/mention.ts +++ b/src/mfm/parse/elements/mention.ts @@ -1,7 +1,7 @@ /** * Mention */ -import parseAcct from '../../../acct/parse'; +import parseAcct from '../../../misc/acct/parse'; export type TextElementMention = { type: 'mention' diff --git a/src/acct/parse.ts b/src/misc/acct/parse.ts similarity index 100% rename from src/acct/parse.ts rename to src/misc/acct/parse.ts diff --git a/src/misc/acct/render.ts b/src/misc/acct/render.ts new file mode 100644 index 0000000000..92ee2010a6 --- /dev/null +++ b/src/misc/acct/render.ts @@ -0,0 +1,8 @@ +type UserLike = { + host: string; + username: string; +}; + +export default (user: UserLike) => { + return user.host === null ? user.username : `${user.username}@${user.host}`; +}; diff --git a/src/cafy-id.ts b/src/misc/cafy-id.ts similarity index 77% rename from src/cafy-id.ts rename to src/misc/cafy-id.ts index dac0f97bd2..f3e1f5251b 100644 --- a/src/cafy-id.ts +++ b/src/misc/cafy-id.ts @@ -1,5 +1,5 @@ import * as mongo from 'mongodb'; -import { Query } from 'cafy'; +import { Context } from 'cafy'; export const isAnId = (x: any) => mongo.ObjectID.isValid(x); export const isNotAnId = (x: any) => !isAnId(x); @@ -7,7 +7,7 @@ export const isNotAnId = (x: any) => !isAnId(x); /** * ID */ -export default class ID extends Query<mongo.ObjectID> { +export default class ID extends Context<mongo.ObjectID> { constructor() { super(); @@ -26,4 +26,8 @@ export default class ID extends Query<mongo.ObjectID> { return true; }); } + + public getType() { + return super.getType('string'); + } } diff --git a/src/utils/cli/progressbar.ts b/src/misc/cli/progressbar.ts similarity index 100% rename from src/utils/cli/progressbar.ts rename to src/misc/cli/progressbar.ts diff --git a/src/utils/dependencyInfo.ts b/src/misc/dependencyInfo.ts similarity index 84% rename from src/utils/dependencyInfo.ts rename to src/misc/dependencyInfo.ts index 89af0d20fb..09d2828222 100644 --- a/src/utils/dependencyInfo.ts +++ b/src/misc/dependencyInfo.ts @@ -9,9 +9,8 @@ export default class { } public showAll(): void { - this.show('MongoDB', 'mongo --version', x => x.match(/^MongoDB shell version:? (.*)\r?\n/)); + this.show('MongoDB', 'mongo --version', x => x.match(/^MongoDB shell version:? v(.*)\r?\n/)); this.show('Redis', 'redis-server --version', x => x.match(/v=([0-9\.]*)/)); - this.show('ImageMagick', 'magick -version', x => x.match(/^Version: ImageMagick (.+?)\r?\n/)); } public show(serviceName: string, command: string, transform: (x: string) => RegExpMatchArray): void { @@ -21,7 +20,7 @@ export default class { const x = execSync(command, { stdio: ['pipe', 'pipe', 'ignore'] }); const ver = transform(x.toString()); if (ver != null) { - this.logger.info(`${serviceName} ${ver[1]} found`); + this.logger.succ(`${serviceName} ${ver[1]} found`); } else { this.logger.warn(`${serviceName} not found`); this.logger.warn(`Regexp used for version check of ${serviceName} is probably messed up`); diff --git a/src/utils/environmentInfo.ts b/src/misc/environmentInfo.ts similarity index 78% rename from src/utils/environmentInfo.ts rename to src/misc/environmentInfo.ts index e6084cde0e..cee42ef9c0 100644 --- a/src/utils/environmentInfo.ts +++ b/src/misc/environmentInfo.ts @@ -1,4 +1,5 @@ import Logger from './logger'; +import isRoot = require('is-root'); export default class { public static show(): void { @@ -10,5 +11,7 @@ export default class { logger.warn('The environment is not in production mode'); logger.warn('Do not use for production purpose'); } + + logger.info(`You ${isRoot() ? '' : 'do not '}have root privileges`); } } diff --git a/src/build/fa.ts b/src/misc/fa.ts similarity index 100% rename from src/build/fa.ts rename to src/misc/fa.ts diff --git a/src/renderers/get-note-summary.ts b/src/misc/get-note-summary.ts similarity index 100% rename from src/renderers/get-note-summary.ts rename to src/misc/get-note-summary.ts diff --git a/src/renderers/get-notification-summary.ts b/src/misc/get-notification-summary.ts similarity index 95% rename from src/renderers/get-notification-summary.ts rename to src/misc/get-notification-summary.ts index f9c5a55879..71d4973ce9 100644 --- a/src/renderers/get-notification-summary.ts +++ b/src/misc/get-notification-summary.ts @@ -1,4 +1,4 @@ -import getUserName from '../renderers/get-user-name'; +import getUserName from './get-user-name'; import getNoteSummary from './get-note-summary'; import getReactionEmoji from './get-reaction-emoji'; diff --git a/src/renderers/get-reaction-emoji.ts b/src/misc/get-reaction-emoji.ts similarity index 100% rename from src/renderers/get-reaction-emoji.ts rename to src/misc/get-reaction-emoji.ts diff --git a/src/renderers/get-user-name.ts b/src/misc/get-user-name.ts similarity index 100% rename from src/renderers/get-user-name.ts rename to src/misc/get-user-name.ts diff --git a/src/renderers/get-user-summary.ts b/src/misc/get-user-summary.ts similarity index 93% rename from src/renderers/get-user-summary.ts rename to src/misc/get-user-summary.ts index 1bd9a7fb47..09cf5ebadc 100644 --- a/src/renderers/get-user-summary.ts +++ b/src/misc/get-user-summary.ts @@ -1,5 +1,5 @@ import { IUser, isLocalUser } from '../models/user'; -import getAcct from '../acct/render'; +import getAcct from './acct/render'; import getUserName from './get-user-name'; /** diff --git a/src/build/i18n.ts b/src/misc/i18n.ts similarity index 70% rename from src/build/i18n.ts rename to src/misc/i18n.ts index dc48251c95..a07af3e939 100644 --- a/src/build/i18n.ts +++ b/src/misc/i18n.ts @@ -2,7 +2,7 @@ * Replace i18n texts */ -import locale, { isAvailableLanguage, LocaleObject } from '../../locales'; +const locale = require('../../locales'); export default class Replacer { private lang: string; @@ -16,8 +16,8 @@ export default class Replacer { this.replacement = this.replacement.bind(this); } - private get(path: string, key: string): string { - if (!isAvailableLanguage(this.lang)) { + public get(path: string, key: string): string { + if (!(this.lang in locale)) { console.warn(`lang '${this.lang}' is not supported`); return key; // Fallback } @@ -28,9 +28,9 @@ export default class Replacer { if (path) { if (text.hasOwnProperty(path)) { - text = text[path] as LocaleObject; + text = text[path]; } else { - console.warn(`path '${path}' not found in '${this.lang}'`); + if (this.lang === 'ja') console.warn(`path '${path}' not found`); return key; // Fallback } } @@ -38,7 +38,7 @@ export default class Replacer { // Check the key existance const error = key.split('.').some(k => { if (text.hasOwnProperty(k)) { - text = (text as LocaleObject)[k]; + text = text[k]; return false; } else { return true; @@ -46,10 +46,10 @@ export default class Replacer { }); if (error) { - console.warn(`key '${key}' not found in '${path}' of '${this.lang}'`); + if (this.lang === 'ja') console.warn(`key '${key}' not found in '${path}'`); return key; // Fallback } else if (typeof text !== 'string') { - console.warn(`key '${key}' is not string in '${path}' of '${this.lang}'`); + if (this.lang === 'ja') console.warn(`key '${key}' is not string in '${path}'`); return key; // Fallback } else { return text; diff --git a/src/misc/is-quote.ts b/src/misc/is-quote.ts new file mode 100644 index 0000000000..420f03a489 --- /dev/null +++ b/src/misc/is-quote.ts @@ -0,0 +1,5 @@ +import { INote } from '../models/note'; + +export default function(note: INote): boolean { + return note.renoteId != null && (note.text != null || note.poll != null || (note.mediaIds != null && note.mediaIds.length > 0)); +} diff --git a/src/build/license.ts b/src/misc/license.ts similarity index 100% rename from src/build/license.ts rename to src/misc/license.ts diff --git a/src/misc/logger.ts b/src/misc/logger.ts new file mode 100644 index 0000000000..04385251e4 --- /dev/null +++ b/src/misc/logger.ts @@ -0,0 +1,53 @@ +import chalk from 'chalk'; +import * as dateformat from 'dateformat'; + +export default class Logger { + private domain: string; + + constructor(domain: string) { + this.domain = domain; + } + + public static log(level: string, message: string): void { + const time = dateformat(new Date(), 'HH:MM:ss'); + console.log(`[${time} ${level}] ${message}`); + } + + public static error(message: string): void { + (new Logger('')).error(message); + } + + public static warn(message: string): void { + (new Logger('')).warn(message); + } + + public static succ(message: string): void { + (new Logger('')).succ(message); + } + + public static info(message: string): void { + (new Logger('')).info(message); + } + + public log(level: string, message: string) { + const domain = this.domain.length > 0 ? `[${this.domain}] ` : ''; + Logger.log(level, `${domain}${message}`); + } + + public error(message: string): void { // 実行を継続できない状況で使う + this.log(chalk.red.bold('ERROR'), chalk.red.bold(message)); + } + + public warn(message: string): void { // 実行を継続できるが改善すべき状況で使う + this.log(chalk.yellow.bold('WARN'), chalk.yellow.bold(message)); + } + + public succ(message: string): void { // 何かに成功した状況で使う + this.log(chalk.blue.bold('INFO'), chalk.green.bold(message)); + } + + public info(message: string): void { // それ以外 + this.log(chalk.blue.bold('INFO'), message); + } + +} diff --git a/src/utils/machineInfo.ts b/src/misc/machineInfo.ts similarity index 84% rename from src/utils/machineInfo.ts rename to src/misc/machineInfo.ts index 0c189cc7ca..6049bcfc9c 100644 --- a/src/utils/machineInfo.ts +++ b/src/misc/machineInfo.ts @@ -9,8 +9,7 @@ export default class { logger.info(`Hostname: ${os.hostname()}`); logger.info(`Platform: ${process.platform}`); logger.info(`Architecture: ${process.arch}`); - logger.info(`Node.js: ${process.version}`); - logger.info(`CPU: ${os.cpus().length}core`); + logger.info(`CPU: ${os.cpus().length} core`); logger.info(`MEM: ${totalmem}GB (available: ${freemem}GB)`); } } diff --git a/src/models/drive-file.ts b/src/models/drive-file.ts index 2bdf38f484..33c0451905 100644 --- a/src/models/drive-file.ts +++ b/src/models/drive-file.ts @@ -31,8 +31,17 @@ export type IMetadata = { comment: string; uri?: string; url?: string; + src?: string; deletedAt?: Date; - isMetaOnly?: boolean; + withoutChunks?: boolean; + storage?: string; + storageProps?: any; + isSensitive?: boolean; + + /** + * 外部の(信頼されていない)URLへの直リンクか否か + */ + isRemote?: boolean; }; export type IDriveFile = { @@ -154,9 +163,8 @@ export const pack = ( _target = Object.assign(_target, _file.metadata); - _target.src = _file.metadata.url; - _target.url = _file.metadata.isMetaOnly ? _file.metadata.url : `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}`; - _target.isRemote = _file.metadata.isMetaOnly; + _target.url = _file.metadata.url ? _file.metadata.url : `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}`; + _target.isRemote = _file.metadata.isRemote; if (_target.properties == null) _target.properties = {}; diff --git a/src/models/follow-request.ts b/src/models/follow-request.ts index fdb20011f4..8ed131c80e 100644 --- a/src/models/follow-request.ts +++ b/src/models/follow-request.ts @@ -17,10 +17,12 @@ export type IFollowRequest = { _followee: { host: string; inbox?: string; + sharedInbox?: string; }, _follower: { host: string; inbox?: string; + sharedInbox?: string; } }; diff --git a/src/models/following.ts b/src/models/following.ts index 4712379a70..8aa588f557 100644 --- a/src/models/following.ts +++ b/src/models/following.ts @@ -16,10 +16,12 @@ export type IFollowing = { _followee: { host: string; inbox?: string; + sharedInbox?: string; }, _follower: { host: string; inbox?: string; + sharedInbox?: string; } }; diff --git a/src/models/reversi-game.ts b/src/models/games/reversi/game.ts similarity index 96% rename from src/models/reversi-game.ts rename to src/models/games/reversi/game.ts index cf497f0568..8255db0584 100644 --- a/src/models/reversi-game.ts +++ b/src/models/games/reversi/game.ts @@ -1,7 +1,7 @@ import * as mongo from 'mongodb'; const deepcopy = require('deepcopy'); -import db from '../db/mongodb'; -import { IUser, pack as packUser } from './user'; +import db from '../../../db/mongodb'; +import { IUser, pack as packUser } from '../../user'; const ReversiGame = db.get<IReversiGame>('reversiGames'); export default ReversiGame; diff --git a/src/models/reversi-matching.ts b/src/models/games/reversi/matching.ts similarity index 91% rename from src/models/reversi-matching.ts rename to src/models/games/reversi/matching.ts index 90227bd121..e94b832cb0 100644 --- a/src/models/reversi-matching.ts +++ b/src/models/games/reversi/matching.ts @@ -1,7 +1,7 @@ import * as mongo from 'mongodb'; const deepcopy = require('deepcopy'); -import db from '../db/mongodb'; -import { IUser, pack as packUser } from './user'; +import db from '../../../db/mongodb'; +import { IUser, pack as packUser } from '../../user'; const Matching = db.get<IMatching>('reversiMatchings'); export default Matching; diff --git a/src/models/hashtag.ts b/src/models/hashtag.ts new file mode 100644 index 0000000000..f5b6156055 --- /dev/null +++ b/src/models/hashtag.ts @@ -0,0 +1,13 @@ +import * as mongo from 'mongodb'; +import db from '../db/mongodb'; + +const Hashtag = db.get<IHashtags>('hashtags'); +Hashtag.createIndex('tag', { unique: true }); +Hashtag.createIndex('mentionedUserIdsCount'); +export default Hashtag; + +export interface IHashtags { + tag: string; + mentionedUserIds: mongo.ObjectID[]; + mentionedUserIdsCount: number; +} diff --git a/src/models/user.ts b/src/models/user.ts index 0d1be439e9..fdbb245faa 100644 --- a/src/models/user.ts +++ b/src/models/user.ts @@ -43,7 +43,6 @@ type IUserBase = { followingCount: number; name?: string; notesCount: number; - driveCapacity: number; username: string; usernameLower: string; avatarId: mongo.ObjectID; @@ -51,6 +50,7 @@ type IUserBase = { avatarUrl?: string; bannerUrl?: string; wallpaperId: mongo.ObjectID; + wallpaperUrl?: string; data: any; description: string; pinnedNoteId: mongo.ObjectID; @@ -77,7 +77,6 @@ export interface ILocalUser extends IUserBase { host: null; keypair: string; email: string; - links: string[]; password: string; token: string; twitter: { @@ -97,7 +96,8 @@ export interface ILocalUser extends IUserBase { lastUsedAt: Date; isBot: boolean; isCat: boolean; - isPro: boolean; + isAdmin?: boolean; + isVerified?: boolean; twoFactorSecret: string; twoFactorEnabled: boolean; twoFactorTempSecret?: string; @@ -109,6 +109,7 @@ export interface ILocalUser extends IUserBase { export interface IRemoteUser extends IUserBase { inbox: string; + sharedInbox?: string; endpoints: string[]; uri: string; url?: string; @@ -400,25 +401,22 @@ export const pack = ( } if (_user.avatarUrl == null) { - _user.avatarUrl = _user.avatarId != null - ? `${config.drive_url}/${_user.avatarId}` - : `${config.drive_url}/default-avatar.jpg`; + _user.avatarUrl = `${config.drive_url}/default-avatar.jpg`; + + // 互換性のため + if (_user.avatarId) { + _user.avatarUrl = `${config.drive_url}/${_user.avatarId}`; + } } - if (_user.bannerUrl == null) { - _user.bannerUrl = _user.bannerId != null - ? `${config.drive_url}/${_user.bannerId}` - : null; + // 互換性のため + if (_user.bannerId && _user.bannerUrl == null) { + _user.bannerUrl = `${config.drive_url}/${_user.bannerId}`; } - _user.wallpaperUrl = _user.wallpaperId != null - ? `${config.drive_url}/${_user.wallpaperId}` - : null; - if (!meId || !meId.equals(_user.id) || !opts.detail) { delete _user.avatarId; delete _user.bannerId; - delete _user.driveCapacity; delete _user.hasUnreadMessagingMessage; delete _user.hasUnreadNotification; } diff --git a/src/publishers/notify.ts b/src/notify.ts similarity index 78% rename from src/publishers/notify.ts rename to src/notify.ts index 5b25fbf8aa..ea7423655e 100644 --- a/src/publishers/notify.ts +++ b/src/notify.ts @@ -1,10 +1,10 @@ import * as mongo from 'mongodb'; -import Notification from '../models/notification'; -import Mute from '../models/mute'; -import { pack } from '../models/notification'; -import stream from './stream'; -import User from '../models/user'; -import pushSw from '../publishers/push-sw'; +import Notification from './models/notification'; +import Mute from './models/mute'; +import { pack } from './models/notification'; +import { publishUserStream } from './stream'; +import User from './models/user'; +import pushSw from './push-sw'; export default ( notifiee: mongo.ObjectID, @@ -30,7 +30,7 @@ export default ( const packed = await pack(notification); // Publish notification event - stream(notifiee, 'notification', packed); + publishUserStream(notifiee, 'notification', packed); // Update flag User.update({ _id: notifiee }, { @@ -54,7 +54,7 @@ export default ( } //#endregion - stream(notifiee, 'unread_notification', packed); + publishUserStream(notifiee, 'unread_notification', packed); pushSw(notifiee, 'notification', packed); } diff --git a/src/parse-opt.ts b/src/parse-opt.ts deleted file mode 100644 index 29e5959c3e..0000000000 --- a/src/parse-opt.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as nopt from 'nopt'; - -export default (vector: any, index: any) => { - const parsed = nopt({ - 'only-processor': Boolean, - 'only-server': Boolean - }, { - p: ['--only-processor'], - s: ['--only-server'] - }, vector, index); - - if (parsed['only-processor'] && parsed['only-server']) { - throw 'only-processor option and only-server option cannot be set at the same time'; - } - - return parsed; -}; diff --git a/src/publishers/stream.ts b/src/publishers/stream.ts deleted file mode 100644 index b573b65a65..0000000000 --- a/src/publishers/stream.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as mongo from 'mongodb'; -import * as redis from 'redis'; -import config from '../config'; - -type ID = string | mongo.ObjectID; - -class MisskeyEvent { - private redisClient: redis.RedisClient; - - constructor() { - // Connect to Redis - this.redisClient = redis.createClient( - config.redis.port, config.redis.host); - } - - public publishUserStream(userId: ID, type: string, value?: any): void { - this.publish(`user-stream:${userId}`, type, typeof value === 'undefined' ? null : value); - } - - public publishDriveStream(userId: ID, type: string, value?: any): void { - this.publish(`drive-stream:${userId}`, type, typeof value === 'undefined' ? null : value); - } - - public publishNoteStream(noteId: ID, type: string, value?: any): void { - this.publish(`note-stream:${noteId}`, type, typeof value === 'undefined' ? null : value); - } - - public publishUserListStream(listId: ID, type: string, value?: any): void { - this.publish(`user-list-stream:${listId}`, type, typeof value === 'undefined' ? null : value); - } - - public publishMessagingStream(userId: ID, otherpartyId: ID, type: string, value?: any): void { - this.publish(`messaging-stream:${userId}-${otherpartyId}`, type, typeof value === 'undefined' ? null : value); - } - - public publishMessagingIndexStream(userId: ID, type: string, value?: any): void { - this.publish(`messaging-index-stream:${userId}`, type, typeof value === 'undefined' ? null : value); - } - - public publishReversiStream(userId: ID, type: string, value?: any): void { - this.publish(`reversi-stream:${userId}`, type, typeof value === 'undefined' ? null : value); - } - - public publishReversiGameStream(gameId: ID, type: string, value?: any): void { - this.publish(`reversi-game-stream:${gameId}`, type, typeof value === 'undefined' ? null : value); - } - - public publishLocalTimelineStream(note: any): void { - this.redisClient.publish('misskey:local-timeline', JSON.stringify(note)); - } - - public publishGlobalTimelineStream(note: any): void { - this.redisClient.publish('misskey:global-timeline', JSON.stringify(note)); - } - - private publish(channel: string, type: string, value?: any): void { - const message = value == null ? - { type: type } : - { type: type, body: value }; - - this.redisClient.publish(`misskey:${channel}`, JSON.stringify(message)); - } -} - -const ev = new MisskeyEvent(); - -export default ev.publishUserStream.bind(ev); - -export const publishLocalTimelineStream = ev.publishLocalTimelineStream.bind(ev); -export const publishGlobalTimelineStream = ev.publishGlobalTimelineStream.bind(ev); -export const publishDriveStream = ev.publishDriveStream.bind(ev); -export const publishUserListStream = ev.publishUserListStream.bind(ev); -export const publishNoteStream = ev.publishNoteStream.bind(ev); -export const publishMessagingStream = ev.publishMessagingStream.bind(ev); -export const publishMessagingIndexStream = ev.publishMessagingIndexStream.bind(ev); -export const publishReversiStream = ev.publishReversiStream.bind(ev); -export const publishReversiGameStream = ev.publishReversiGameStream.bind(ev); diff --git a/src/publishers/push-sw.ts b/src/push-sw.ts similarity index 93% rename from src/publishers/push-sw.ts rename to src/push-sw.ts index b0b4701155..cfed5f03cd 100644 --- a/src/publishers/push-sw.ts +++ b/src/push-sw.ts @@ -1,7 +1,7 @@ const push = require('web-push'); import * as mongo from 'mongodb'; -import Subscription from '../models/sw-subscription'; -import config from '../config'; +import Subscription from './models/sw-subscription'; +import config from './config'; if (config.sw) { // アプリケーションの連絡先と、サーバーサイドの鍵ペアの情報を登録 diff --git a/src/queue/index.ts b/src/queue/index.ts index 1efd6e54ef..5a48dbe648 100644 --- a/src/queue/index.ts +++ b/src/queue/index.ts @@ -1,45 +1,15 @@ -import { createQueue } from 'kue'; - -import config from '../config'; import http from './processors/http'; import { ILocalUser } from '../models/user'; -const queue = createQueue({ - redis: { - port: config.redis.port, - host: config.redis.host, - auth: config.redis.pass - } -}); - -export function createHttp(data: any) { - return queue - .create('http', data) - .removeOnComplete(true) - .events(false) - .attempts(8) - .backoff({ delay: 16384, type: 'exponential' }); +export function createHttpJob(data: any) { + return http({ data }, () => {}); } export function deliver(user: ILocalUser, content: any, to: any) { - createHttp({ - title: 'deliver', + createHttpJob({ type: 'deliver', user, content, to - }).save(); -} - -export default function() { - /* - 256 is the default concurrency limit of Mozilla Firefox and Google - Chromium. - a8af215e691f3a2205a3758d2d96e9d328e100ff - chromium/src.git - Git at Google - https://chromium.googlesource.com/chromium/src.git/+/a8af215e691f3a2205a3758d2d96e9d328e100ff - Network.http.max-connections - MozillaZine Knowledge Base - http://kb.mozillazine.org/Network.http.max-connections - */ - //queue.process('http', 256, http); - queue.process('http', 128, http); + }); } diff --git a/src/queue/processors/http/deliver.ts b/src/queue/processors/http/deliver.ts index 946d2f65bd..e06866da4e 100644 --- a/src/queue/processors/http/deliver.ts +++ b/src/queue/processors/http/deliver.ts @@ -1,8 +1,8 @@ -import * as kue from 'kue'; +import * as bq from 'bee-queue'; import request from '../../../remote/activitypub/request'; -export default async (job: kue.Job, done: any): Promise<void> => { +export default async (job: bq.Job, done: any): Promise<void> => { try { await request(job.data.user, job.data.to, job.data.content); done(); diff --git a/src/queue/processors/http/process-inbox.ts b/src/queue/processors/http/process-inbox.ts index 0da442aefb..0738853dd1 100644 --- a/src/queue/processors/http/process-inbox.ts +++ b/src/queue/processors/http/process-inbox.ts @@ -1,8 +1,8 @@ -import * as kue from 'kue'; +import * as bq from 'bee-queue'; import * as debug from 'debug'; const httpSignature = require('http-signature'); -import parseAcct from '../../../acct/parse'; +import parseAcct from '../../../misc/acct/parse'; import User, { IRemoteUser } from '../../../models/user'; import perform from '../../../remote/activitypub/perform'; import { resolvePerson } from '../../../remote/activitypub/models/person'; @@ -10,7 +10,7 @@ import { resolvePerson } from '../../../remote/activitypub/models/person'; const log = debug('misskey:queue:inbox'); // ユーザーのinboxにアクティビティが届いた時の処理 -export default async (job: kue.Job, done: any): Promise<void> => { +export default async (job: bq.Job, done: any): Promise<void> => { const signature = job.data.signature; const activity = job.data.activity; diff --git a/src/remote/activitypub/kernel/accept/follow.ts b/src/remote/activitypub/kernel/accept/follow.ts index 0f414ba321..07c820c28a 100644 --- a/src/remote/activitypub/kernel/accept/follow.ts +++ b/src/remote/activitypub/kernel/accept/follow.ts @@ -5,7 +5,7 @@ import accept from '../../../../services/following/requests/accept'; import { IFollow } from '../../type'; export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => { - const id = typeof activity.object == 'string' ? activity.object : activity.object.id; + const id = typeof activity.actor == 'string' ? activity.actor : activity.actor.id; if (!id.startsWith(config.url + '/')) { return null; diff --git a/src/remote/activitypub/kernel/reject/follow.ts b/src/remote/activitypub/kernel/reject/follow.ts index c139865d0e..35cd2ec0c9 100644 --- a/src/remote/activitypub/kernel/reject/follow.ts +++ b/src/remote/activitypub/kernel/reject/follow.ts @@ -5,7 +5,7 @@ import reject from '../../../../services/following/requests/reject'; import { IFollow } from '../../type'; export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => { - const id = typeof activity.object == 'string' ? activity.object : activity.object.id; + const id = typeof activity.actor == 'string' ? activity.actor : activity.actor.id; if (!id.startsWith(config.url + '/')) { return null; diff --git a/src/remote/activitypub/kernel/undo/follow.ts b/src/remote/activitypub/kernel/undo/follow.ts index 7377984616..f112ee8bfb 100644 --- a/src/remote/activitypub/kernel/undo/follow.ts +++ b/src/remote/activitypub/kernel/undo/follow.ts @@ -31,7 +31,7 @@ export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => { }); if (req) { - await cancelRequest(actor, followee); + await cancelRequest(followee, actor); } else { await unfollow(actor, followee); } diff --git a/src/remote/activitypub/models/image.ts b/src/remote/activitypub/models/image.ts index fb17a7c9e5..8b33187ef5 100644 --- a/src/remote/activitypub/models/image.ts +++ b/src/remote/activitypub/models/image.ts @@ -16,7 +16,7 @@ export async function createImage(actor: IRemoteUser, value: any): Promise<IDriv return null; } - const image = await new Resolver().resolve(value); + const image = await new Resolver().resolve(value) as any; if (image.url == null) { throw new Error('invalid image: url not privided'); @@ -24,7 +24,7 @@ export async function createImage(actor: IRemoteUser, value: any): Promise<IDriv log(`Creating the Image: ${image.url}`); - return await uploadFromUrl(image.url, actor, null, image.url); + return await uploadFromUrl(image.url, actor, null, image.url, image.sensitive); } /** diff --git a/src/remote/activitypub/models/person.ts b/src/remote/activitypub/models/person.ts index 83afd68268..c292d02419 100644 --- a/src/remote/activitypub/models/person.ts +++ b/src/remote/activitypub/models/person.ts @@ -14,6 +14,34 @@ import htmlToMFM from '../../../mfm/html-to-mfm'; const log = debug('misskey:activitypub'); +function validatePerson(x: any) { + if (x == null) { + return new Error('invalid person: object is null'); + } + + if (x.type != 'Person' && x.type != 'Service') { + return new Error(`invalid person: object is not a person or service '${x.type}'`); + } + + if (typeof x.preferredUsername !== 'string') { + return new Error('invalid person: preferredUsername is not a string'); + } + + if (typeof x.inbox !== 'string') { + return new Error('invalid person: inbox is not a string'); + } + + if (!validateUsername(x.preferredUsername)) { + return new Error('invalid person: invalid username'); + } + + if (!isValidName(x.name == '' ? null : x.name)) { + return new Error('invalid person: invalid name'); + } + + return null; +} + /** * Personをフェッチします。 * @@ -47,28 +75,10 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs const object = await resolver.resolve(value) as any; - if (object == null) { - throw new Error('invalid person: object is null'); - } + const err = validatePerson(object); - if (object.type != 'Person' && object.type != 'Service') { - throw new Error(`invalid person: object is not a person or service '${object.type}'`); - } - - if (typeof object.preferredUsername !== 'string') { - throw new Error('invalid person: preferredUsername is not a string'); - } - - if (typeof object.inbox !== 'string') { - throw new Error('invalid person: inbox is not a string'); - } - - if (!validateUsername(object.preferredUsername)) { - throw new Error('invalid person: invalid username'); - } - - if (!isValidName(object.name == '' ? null : object.name)) { - throw new Error('invalid person: invalid name'); + if (err) { + throw err; } const person: IPerson = object; @@ -107,7 +117,6 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs followingCount, notesCount, name: person.name, - driveCapacity: 1024 * 1024 * 8, // 8MiB isLocked: person.manuallyApprovesFollowers, username: person.preferredUsername, usernameLower: person.preferredUsername.toLowerCase(), @@ -117,6 +126,7 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs publicKeyPem: person.publicKey.publicKeyPem }, inbox: person.inbox, + sharedInbox: person.sharedInbox, endpoints: person.endpoints, uri: person.id, url: person.url, @@ -152,8 +162,8 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs const avatarId = avatar ? avatar._id : null; const bannerId = banner ? banner._id : null; - const avatarUrl = avatar && avatar.metadata.isMetaOnly ? avatar.metadata.url : null; - const bannerUrl = banner && banner.metadata.isMetaOnly ? banner.metadata.url : null; + const avatarUrl = avatar && avatar.metadata.url ? avatar.metadata.url : null; + const bannerUrl = banner && banner.metadata.url ? banner.metadata.url : null; await User.update({ _id: user._id }, { $set: { @@ -198,12 +208,10 @@ export async function updatePerson(value: string | IObject, resolver?: Resolver) const object = await resolver.resolve(value) as any; - if ( - object == null || - object.type !== 'Person' - ) { - log(`invalid person: ${JSON.stringify(object, null, 2)}`); - throw new Error('invalid person'); + const err = validatePerson(object); + + if (err) { + throw err; } const person: IPerson = object; @@ -239,10 +247,12 @@ export async function updatePerson(value: string | IObject, resolver?: Resolver) await User.update({ _id: exist._id }, { $set: { updatedAt: new Date(), + inbox: person.inbox, + sharedInbox: person.sharedInbox, avatarId: avatar ? avatar._id : null, bannerId: banner ? banner._id : null, - avatarUrl: avatar && avatar.metadata.isMetaOnly ? avatar.metadata.url : null, - bannerUrl: banner && banner.metadata.isMetaOnly ? banner.metadata.url : null, + avatarUrl: avatar && avatar.metadata.url ? avatar.metadata.url : null, + bannerUrl: banner && banner.metadata.url ? banner.metadata.url : null, description: htmlToMFM(person.summary), followersCount, followingCount, diff --git a/src/remote/activitypub/renderer/image.ts b/src/remote/activitypub/renderer/image.ts index cf91ce3a0c..69bddd9188 100644 --- a/src/remote/activitypub/renderer/image.ts +++ b/src/remote/activitypub/renderer/image.ts @@ -1,7 +1,8 @@ import config from '../../../config'; import { IDriveFile } from '../../../models/drive-file'; -export default (fileId: IDriveFile['_id']) => ({ +export default (file: IDriveFile) => ({ type: 'Image', - url: `${config.drive_url}/${fileId}` + url: `${config.drive_url}/${file._id}`, + sensitive: file.metadata.isSensitive }); diff --git a/src/remote/activitypub/renderer/person.ts b/src/remote/activitypub/renderer/person.ts index d4b3f40e41..7d828f97ae 100644 --- a/src/remote/activitypub/renderer/person.ts +++ b/src/remote/activitypub/renderer/person.ts @@ -4,10 +4,16 @@ import config from '../../../config'; import { ILocalUser } from '../../../models/user'; import toHtml from '../../../mfm/html'; import parse from '../../../mfm/parse'; +import DriveFile from '../../../models/drive-file'; -export default (user: ILocalUser) => { +export default async (user: ILocalUser) => { const id = `${config.url}/users/${user._id}`; + const [avatar, banner] = await Promise.all([ + DriveFile.findOne({ _id: user.avatarId }), + DriveFile.findOne({ _id: user.bannerId }) + ]); + return { type: user.isBot ? 'Service' : 'Person', id, @@ -18,8 +24,8 @@ export default (user: ILocalUser) => { preferredUsername: user.username, name: user.name, summary: toHtml(parse(user.description)), - icon: user.avatarId && renderImage(user.avatarId), - image: user.bannerId && renderImage(user.bannerId), + icon: user.avatarId && renderImage(avatar), + image: user.bannerId && renderImage(banner), manuallyApprovesFollowers: user.isLocked, publicKey: renderKey(user) }; diff --git a/src/remote/activitypub/type.ts b/src/remote/activitypub/type.ts index 13e1969b4e..9761b66dc3 100644 --- a/src/remote/activitypub/type.ts +++ b/src/remote/activitypub/type.ts @@ -47,6 +47,7 @@ export interface IPerson extends IObject { preferredUsername: string; manuallyApprovesFollowers: boolean; inbox: string; + sharedInbox?: string; publicKey: any; followers: any; following: any; diff --git a/src/server/activitypub.ts b/src/server/activitypub.ts index f8a01a6ffe..2d9a4746c6 100644 --- a/src/server/activitypub.ts +++ b/src/server/activitypub.ts @@ -3,7 +3,7 @@ import * as Router from 'koa-router'; const json = require('koa-json-body'); const httpSignature = require('http-signature'); -import { createHttp } from '../queue'; +import { createHttpJob } from '../queue'; import pack from '../remote/activitypub/renderer'; import Note from '../models/note'; import User, { isLocalUser, ILocalUser, IUser } from '../models/user'; @@ -11,7 +11,6 @@ import renderNote from '../remote/activitypub/renderer/note'; import renderKey from '../remote/activitypub/renderer/key'; import renderPerson from '../remote/activitypub/renderer/person'; import renderOrderedCollection from '../remote/activitypub/renderer/ordered-collection'; -import parseAcct from '../acct/parse'; import config from '../config'; // Init router @@ -31,11 +30,11 @@ function inbox(ctx: Router.IRouterContext) { return; } - createHttp({ + createHttpJob({ type: 'processInbox', activity: ctx.request.body, signature - }).save(); + }); ctx.status = 202; } @@ -112,13 +111,13 @@ router.get('/users/:user/publickey', async ctx => { }); // user -function userInfo(ctx: Router.IRouterContext, user: IUser) { +async function userInfo(ctx: Router.IRouterContext, user: IUser) { if (user === null) { ctx.status = 404; return; } - ctx.body = pack(renderPerson(user as ILocalUser)); + ctx.body = pack(await renderPerson(user as ILocalUser)); } router.get('/users/:user', async ctx => { @@ -129,7 +128,7 @@ router.get('/users/:user', async ctx => { host: null }); - userInfo(ctx, user); + await userInfo(ctx, user); }); router.get('/@:user', async (ctx, next) => { @@ -140,7 +139,7 @@ router.get('/@:user', async (ctx, next) => { host: null }); - userInfo(ctx, user); + await userInfo(ctx, user); }); //#endregion diff --git a/src/server/api/api-handler.ts b/src/server/api/api-handler.ts index e716dcdc01..128c1a98d2 100644 --- a/src/server/api/api-handler.ts +++ b/src/server/api/api-handler.ts @@ -1,12 +1,12 @@ import * as Koa from 'koa'; -import { Endpoint } from './endpoints'; +import { IEndpoint } from './endpoints'; import authenticate from './authenticate'; import call from './call'; import { IUser } from '../../models/user'; import { IApp } from '../../models/app'; -export default async (endpoint: Endpoint, ctx: Koa.Context) => { +export default async (endpoint: IEndpoint, ctx: Koa.Context) => { const body = ctx.is('multipart/form-data') ? (ctx.req as any).body : ctx.request.body; const reply = (x?: any, y?: any) => { @@ -37,7 +37,7 @@ export default async (endpoint: Endpoint, ctx: Koa.Context) => { // API invoking try { - res = await call(endpoint, user, app, body, (ctx.req as any).file); + res = await call(endpoint.name, user, app, body, (ctx.req as any).file); } catch (e) { reply(400, e); return; diff --git a/src/server/api/call.ts b/src/server/api/call.ts index fd3cea7743..1d0e858762 100644 --- a/src/server/api/call.ts +++ b/src/server/api/call.ts @@ -1,28 +1,33 @@ -import endpoints, { Endpoint } from './endpoints'; +import { performance } from 'perf_hooks'; import limitter from './limitter'; import { IUser } from '../../models/user'; import { IApp } from '../../models/app'; +import endpoints from './endpoints'; -export default (endpoint: string | Endpoint, user: IUser, app: IApp, data: any, file?: any) => new Promise<any>(async (ok, rej) => { +export default (endpoint: string, user: IUser, app: IApp, data: any, file?: any) => new Promise<any>(async (ok, rej) => { const isSecure = user != null && app == null; - const ep = typeof endpoint == 'string' ? endpoints.find(e => e.name == endpoint) : endpoint; + const ep = endpoints.find(e => e.name === endpoint); - if (ep.secure && !isSecure) { + if (ep.meta.secure && !isSecure) { return rej('ACCESS_DENIED'); } - if (ep.withCredential && user == null) { + if (ep.meta.requireCredential && user == null) { return rej('SIGNIN_REQUIRED'); } - if (app && ep.kind) { - if (!app.permission.some(p => p === ep.kind)) { + if (ep.meta.requireCredential && user.isSuspended) { + return rej('YOUR_ACCOUNT_HAS_BEEN_SUSPENDED'); + } + + if (app && ep.meta.kind) { + if (!app.permission.some(p => p === ep.meta.kind)) { return rej('PERMISSION_DENIED'); } } - if (ep.withCredential && ep.limit) { + if (ep.meta.requireCredential && ep.meta.limit) { try { await limitter(ep, user); // Rate limit } catch (e) { @@ -31,9 +36,9 @@ export default (endpoint: string | Endpoint, user: IUser, app: IApp, data: any, } } - let exec = require(`${__dirname}/endpoints/${ep.name}`); + let exec = ep.exec; - if (ep.withFile && file) { + if (ep.meta.requireFile && file) { exec = exec.bind(null, file); } @@ -41,7 +46,15 @@ export default (endpoint: string | Endpoint, user: IUser, app: IApp, data: any, // API invoking try { + const before = performance.now(); res = await exec(data, user, app); + const after = performance.now(); + + const time = after - before; + + if (time > 1000) { + console.warn(`SLOW API CALL DETECTED: ${ep.name} (${ time }ms)`); + } } catch (e) { rej(e); return; diff --git a/src/server/api/common/get-friends.ts b/src/server/api/common/get-friends.ts index 50ba71ea96..e0b05f73df 100644 --- a/src/server/api/common/get-friends.ts +++ b/src/server/api/common/get-friends.ts @@ -23,12 +23,16 @@ export const getFriendIds = async (me: mongodb.ObjectID, includeMe = true) => { return myfollowingIds; }; -export const getFriends = async (me: mongodb.ObjectID, includeMe = true) => { +export const getFriends = async (me: mongodb.ObjectID, includeMe = true, remoteOnly = false) => { + const q: any = remoteOnly ? { + followerId: me, + '_followee.host': { $ne: null } + } : { + followerId: me + }; // Fetch relation to other users who the I follows const followings = await Following - .find({ - followerId: me - }); + .find(q); // ID list of other users who the I follows const myfollowings = followings.map(following => ({ diff --git a/src/server/api/common/read-messaging-message.ts b/src/server/api/common/read-messaging-message.ts index fd5e9f242c..005240a37c 100644 --- a/src/server/api/common/read-messaging-message.ts +++ b/src/server/api/common/read-messaging-message.ts @@ -1,13 +1,13 @@ import * as mongo from 'mongodb'; import Message from '../../../models/messaging-message'; import { IMessagingMessage as IMessage } from '../../../models/messaging-message'; -import publishUserStream from '../../../publishers/stream'; -import { publishMessagingStream } from '../../../publishers/stream'; -import { publishMessagingIndexStream } from '../../../publishers/stream'; +import { publishUserStream } from '../../../stream'; +import { publishMessagingStream } from '../../../stream'; +import { publishMessagingIndexStream } from '../../../stream'; import User from '../../../models/user'; /** - * Mark as read message(s) + * Mark messages as read */ export default ( user: string | mongo.ObjectID, @@ -42,12 +42,12 @@ export default ( recipientId: userId, isRead: false }, { - $set: { - isRead: true - } - }, { - multi: true - }); + $set: { + isRead: true + } + }, { + multi: true + }); // Publish event publishMessagingStream(otherpartyId, userId, 'read', ids.map(id => id.toString())); @@ -59,8 +59,8 @@ export default ( recipientId: userId, isRead: false }, { - limit: 1 - }); + limit: 1 + }); if (count == 0) { // Update flag diff --git a/src/server/api/common/read-notification.ts b/src/server/api/common/read-notification.ts index 6505c58c39..0b0f3e4e5a 100644 --- a/src/server/api/common/read-notification.ts +++ b/src/server/api/common/read-notification.ts @@ -1,11 +1,11 @@ import * as mongo from 'mongodb'; import { default as Notification, INotification } from '../../../models/notification'; -import publishUserStream from '../../../publishers/stream'; +import { publishUserStream } from '../../../stream'; import Mute from '../../../models/mute'; import User from '../../../models/user'; /** - * Mark as read notification(s) + * Mark notifications as read */ export default ( user: string | mongo.ObjectID, @@ -38,12 +38,12 @@ export default ( _id: { $in: ids }, isRead: false }, { - $set: { - isRead: true - } - }, { - multi: true - }); + $set: { + isRead: true + } + }, { + multi: true + }); // Calc count of my unread notifications const count = await Notification @@ -54,8 +54,8 @@ export default ( }, isRead: false }, { - limit: 1 - }); + limit: 1 + }); if (count == 0) { // Update flag diff --git a/src/server/api/endpoints.ts b/src/server/api/endpoints.ts index 146de67253..332a051ae1 100644 --- a/src/server/api/endpoints.ts +++ b/src/server/api/endpoints.ts @@ -1,20 +1,18 @@ -const ms = require('ms'); +import * as path from 'path'; +import * as glob from 'glob'; -/** - * エンドポイントを表します。 - */ -export type Endpoint = { +export interface IEndpointMeta { + desc?: any; - /** - * エンドポイント名 - */ - name: string; + params?: any; + + res?: any; /** * このエンドポイントにリクエストするのにユーザー情報が必須か否か * 省略した場合は false として解釈されます。 */ - withCredential?: boolean; + requireCredential?: boolean; /** * エンドポイントのリミテーションに関するやつ @@ -50,7 +48,7 @@ export type Endpoint = { * ファイルの添付を必要とするか否か * 省略した場合は false として解釈されます。 */ - withFile?: boolean; + requireFile?: boolean; /** * サードパーティアプリからはリクエストすることができないか否か @@ -63,590 +61,26 @@ export type Endpoint = { * パーミッションの実現に利用されます。 */ kind?: string; -}; +} -const endpoints: Endpoint[] = [ - { - name: 'meta' - }, - { - name: 'stats' - }, - { - name: 'username/available' - }, - { - name: 'my/apps', - withCredential: true - }, - { - name: 'app/create', - withCredential: true, - limit: { - duration: ms('1day'), - max: 3 - } - }, - { - name: 'app/show' - }, - { - name: 'app/name_id/available' - }, - { - name: 'auth/session/generate' - }, - { - name: 'auth/session/show' - }, - { - name: 'auth/session/userkey' - }, - { - name: 'auth/accept', - withCredential: true, - secure: true - }, - { - name: 'auth/deny', - withCredential: true, - secure: true - }, - { - name: 'aggregation/notes', - }, - { - name: 'aggregation/users', - }, - { - name: 'aggregation/users/activity', - }, - { - name: 'aggregation/users/note', - }, - { - name: 'aggregation/users/followers' - }, - { - name: 'aggregation/users/following' - }, - { - name: 'aggregation/users/reaction' - }, - { - name: 'aggregation/notes/renote' - }, - { - name: 'aggregation/notes/reply' - }, - { - name: 'aggregation/notes/reaction' - }, - { - name: 'aggregation/notes/reactions' - }, +export interface IEndpoint { + name: string; + exec: any; + meta: IEndpointMeta; +} - { - name: 'sw/register', - withCredential: true - }, +const files = glob.sync('**/*.js', { + cwd: path.resolve(__dirname + '/endpoints/') +}); - { - name: 'i', - withCredential: true - }, - { - name: 'i/2fa/register', - withCredential: true, - secure: true - }, - { - name: 'i/2fa/unregister', - withCredential: true, - secure: true - }, - { - name: 'i/2fa/done', - withCredential: true, - secure: true - }, - { - name: 'i/update', - withCredential: true, - limit: { - duration: ms('1day'), - max: 50 - }, - kind: 'account-write' - }, - { - name: 'i/update_home', - withCredential: true, - secure: true - }, - { - name: 'i/update_mobile_home', - withCredential: true, - secure: true - }, - { - name: 'i/update_widget', - withCredential: true, - secure: true - }, - { - name: 'i/change_password', - withCredential: true, - secure: true - }, - { - name: 'i/regenerate_token', - withCredential: true, - secure: true - }, - { - name: 'i/update_client_setting', - withCredential: true, - secure: true - }, - { - name: 'i/pin', - kind: 'account-write' - }, - { - name: 'i/appdata/get', - withCredential: true - }, - { - name: 'i/appdata/set', - withCredential: true - }, - { - name: 'i/signin_history', - withCredential: true, - kind: 'account-read' - }, - { - name: 'i/authorized_apps', - withCredential: true, - secure: true - }, +const endpoints: IEndpoint[] = files.map(f => { + const ep = require('./endpoints/' + f); - { - name: 'i/notifications', - withCredential: true, - kind: 'notification-read' - }, - - { - name: 'i/favorites', - withCredential: true, - kind: 'favorites-read' - }, - - { - name: 'reversi/match', - withCredential: true - }, - - { - name: 'reversi/match/cancel', - withCredential: true - }, - - { - name: 'reversi/invitations', - withCredential: true - }, - - { - name: 'reversi/games', - withCredential: true - }, - - { - name: 'reversi/games/show' - }, - - { - name: 'mute/create', - withCredential: true, - kind: 'account/write' - }, - { - name: 'mute/delete', - withCredential: true, - kind: 'account/write' - }, - { - name: 'mute/list', - withCredential: true, - kind: 'account/read' - }, - - { - name: 'notifications/delete', - withCredential: true, - kind: 'notification-write' - }, - { - name: 'notifications/delete_all', - withCredential: true, - kind: 'notification-write' - }, - { - name: 'notifications/mark_as_read_all', - withCredential: true, - kind: 'notification-write' - }, - - { - name: 'drive', - withCredential: true, - kind: 'drive-read' - }, - { - name: 'drive/stream', - withCredential: true, - kind: 'drive-read' - }, - { - name: 'drive/files', - withCredential: true, - kind: 'drive-read' - }, - { - name: 'drive/files/create', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 100 - }, - withFile: true, - kind: 'drive-write' - }, - { - name: 'drive/files/upload_from_url', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 10 - }, - kind: 'drive-write' - }, - { - name: 'drive/files/show', - withCredential: true, - kind: 'drive-read' - }, - { - name: 'drive/files/find', - withCredential: true, - kind: 'drive-read' - }, - { - name: 'drive/files/delete', - withCredential: true, - kind: 'drive-write' - }, - { - name: 'drive/files/update', - withCredential: true, - kind: 'drive-write' - }, - { - name: 'drive/folders', - withCredential: true, - kind: 'drive-read' - }, - { - name: 'drive/folders/create', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 50 - }, - kind: 'drive-write' - }, - { - name: 'drive/folders/show', - withCredential: true, - kind: 'drive-read' - }, - { - name: 'drive/folders/find', - withCredential: true, - kind: 'drive-read' - }, - { - name: 'drive/folders/update', - withCredential: true, - kind: 'drive-write' - }, - - { - name: 'users' - }, - { - name: 'users/show' - }, - { - name: 'users/search' - }, - { - name: 'users/search_by_username' - }, - { - name: 'users/notes' - }, - { - name: 'users/following' - }, - { - name: 'users/followers' - }, - { - name: 'users/recommendation', - withCredential: true, - kind: 'account-read' - }, - { - name: 'users/get_frequently_replied_users' - }, - - { - name: 'users/lists/show', - withCredential: true, - kind: 'account-read' - }, - { - name: 'users/lists/create', - withCredential: true, - kind: 'account-write' - }, - { - name: 'users/lists/push', - withCredential: true, - kind: 'account-write' - }, - { - name: 'users/lists/list', - withCredential: true, - kind: 'account-read' - }, - - { - name: 'following/create', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 100 - }, - kind: 'following-write' - }, - { - name: 'following/delete', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 100 - }, - kind: 'following-write' - }, - { - name: 'following/requests/accept', - withCredential: true, - kind: 'following-write' - }, - { - name: 'following/requests/reject', - withCredential: true, - kind: 'following-write' - }, - { - name: 'following/requests/cancel', - withCredential: true, - kind: 'following-write' - }, - { - name: 'following/requests/list', - withCredential: true, - kind: 'following-read' - }, - { - name: 'following/stalk', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 100 - }, - kind: 'following-write' - }, - { - name: 'following/unstalk', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 100 - }, - kind: 'following-write' - }, - - { - name: 'notes' - }, - { - name: 'notes/show' - }, - { - name: 'notes/replies' - }, - { - name: 'notes/conversation' - }, - { - name: 'notes/create', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 300, - minInterval: ms('1second') - }, - kind: 'note-write' - }, - { - name: 'notes/delete', - withCredential: true, - kind: 'note-write' - }, - { - name: 'notes/renotes' - }, - { - name: 'notes/search' - }, - { - name: 'notes/search_by_tag' - }, - { - name: 'notes/timeline', - withCredential: true, - limit: { - duration: ms('10minutes'), - max: 100 - } - }, - { - name: 'notes/local-timeline', - limit: { - duration: ms('10minutes'), - max: 100 - } - }, - { - name: 'notes/global-timeline', - limit: { - duration: ms('10minutes'), - max: 100 - } - }, - { - name: 'notes/user-list-timeline', - withCredential: true, - limit: { - duration: ms('10minutes'), - max: 100 - } - }, - { - name: 'notes/mentions', - withCredential: true, - limit: { - duration: ms('10minutes'), - max: 100 - } - }, - { - name: 'notes/trend', - withCredential: true - }, - { - name: 'notes/categorize', - withCredential: true - }, - { - name: 'notes/reactions', - withCredential: true - }, - { - name: 'notes/reactions/create', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 300 - }, - kind: 'reaction-write' - }, - { - name: 'notes/reactions/delete', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 100 - }, - kind: 'reaction-write' - }, - { - name: 'notes/favorites/create', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 100 - }, - kind: 'favorite-write' - }, - { - name: 'notes/favorites/delete', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 100 - }, - kind: 'favorite-write' - }, - { - name: 'notes/polls/vote', - withCredential: true, - limit: { - duration: ms('1hour'), - max: 100 - }, - kind: 'vote-write' - }, - { - name: 'notes/polls/recommendation', - withCredential: true - }, - - { - name: 'hashtags/trend' - }, - - { - name: 'messaging/history', - withCredential: true, - kind: 'messaging-read' - }, - { - name: 'messaging/messages', - withCredential: true, - kind: 'messaging-read' - }, - { - name: 'messaging/messages/create', - withCredential: true, - kind: 'messaging-write' - } -]; + return { + name: f.replace('.js', ''), + exec: ep.default, + meta: ep.meta || {} + }; +}); export default endpoints; diff --git a/src/server/api/endpoints/aggregation/posts.ts b/src/server/api/endpoints/aggregation/posts.ts index 48e344312d..629bb19108 100644 --- a/src/server/api/endpoints/aggregation/posts.ts +++ b/src/server/api/endpoints/aggregation/posts.ts @@ -4,9 +4,9 @@ import Note from '../../../../models/note'; /** * Aggregate notes */ -module.exports = (params: any) => new Promise(async (res, rej) => { +export default (params: any) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit); + const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit); if (limitErr) return rej('invalid limit param'); const datas = await Note diff --git a/src/server/api/endpoints/aggregation/users.ts b/src/server/api/endpoints/aggregation/users.ts index c084404d0a..f1e41cf170 100644 --- a/src/server/api/endpoints/aggregation/users.ts +++ b/src/server/api/endpoints/aggregation/users.ts @@ -4,9 +4,9 @@ import User from '../../../../models/user'; /** * Aggregate users */ -module.exports = (params: any) => new Promise(async (res, rej) => { +export default (params: any) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit); + const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit); if (limitErr) return rej('invalid limit param'); const users = await User diff --git a/src/server/api/endpoints/aggregation/users/activity.ts b/src/server/api/endpoints/aggregation/users/activity.ts index d4c716d65b..0ec3f0db76 100644 --- a/src/server/api/endpoints/aggregation/users/activity.ts +++ b/src/server/api/endpoints/aggregation/users/activity.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import User from '../../../../../models/user'; import Note from '../../../../../models/note'; @@ -7,9 +7,9 @@ import Note from '../../../../../models/note'; /** * Aggregate activity of a user */ -module.exports = (params: any) => new Promise(async (res, rej) => { +export default (params: any) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 365, limitErr] = $.num.optional().range(1, 365).get(params.limit); + const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'userId' parameter diff --git a/src/server/api/endpoints/aggregation/users/followers.ts b/src/server/api/endpoints/aggregation/users/followers.ts index 847f376079..94eb83febc 100644 --- a/src/server/api/endpoints/aggregation/users/followers.ts +++ b/src/server/api/endpoints/aggregation/users/followers.ts @@ -1,14 +1,14 @@ /** * Module dependencies */ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import User from '../../../../../models/user'; import FollowedLog from '../../../../../models/followed-log'; /** * Aggregate followers of a user */ -module.exports = (params: any) => new Promise(async (res, rej) => { +export default (params: any) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/aggregation/users/following.ts b/src/server/api/endpoints/aggregation/users/following.ts index 6c52752f98..d2e4d256fe 100644 --- a/src/server/api/endpoints/aggregation/users/following.ts +++ b/src/server/api/endpoints/aggregation/users/following.ts @@ -1,14 +1,14 @@ /** * Module dependencies */ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import User from '../../../../../models/user'; import FollowingLog from '../../../../../models/following-log'; /** * Aggregate following of a user */ -module.exports = (params: any) => new Promise(async (res, rej) => { +export default (params: any) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/aggregation/users/post.ts b/src/server/api/endpoints/aggregation/users/post.ts index 28ba1482bf..090f6d2f09 100644 --- a/src/server/api/endpoints/aggregation/users/post.ts +++ b/src/server/api/endpoints/aggregation/users/post.ts @@ -1,11 +1,11 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import User from '../../../../../models/user'; import Note from '../../../../../models/note'; /** * Aggregate note of a user */ -module.exports = (params: any) => new Promise(async (res, rej) => { +export default (params: any) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/aggregation/users/reaction.ts b/src/server/api/endpoints/aggregation/users/reaction.ts index adb5acfb4e..ce9e150966 100644 --- a/src/server/api/endpoints/aggregation/users/reaction.ts +++ b/src/server/api/endpoints/aggregation/users/reaction.ts @@ -1,11 +1,11 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import User from '../../../../../models/user'; import Reaction from '../../../../../models/note-reaction'; /** * Aggregate reaction of a user */ -module.exports = (params: any) => new Promise(async (res, rej) => { +export default (params: any) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/app/create.ts b/src/server/api/endpoints/app/create.ts index c7bc91a079..5df8bd2f25 100644 --- a/src/server/api/endpoints/app/create.ts +++ b/src/server/api/endpoints/app/create.ts @@ -3,63 +3,14 @@ import $ from 'cafy'; import App, { isValidNameId, pack } from '../../../../models/app'; import { ILocalUser } from '../../../../models/user'; -/** - * @swagger - * /app/create: - * note: - * summary: Create an application - * parameters: - * - $ref: "#/parameters/AccessToken" - * - - * name: nameId - * description: Application unique name - * in: formData - * required: true - * type: string - * - - * name: name - * description: Application name - * in: formData - * required: true - * type: string - * - - * name: description - * description: Application description - * in: formData - * required: true - * type: string - * - - * name: permission - * description: Permissions that application has - * in: formData - * required: true - * type: array - * items: - * type: string - * collectionFormat: csv - * - - * name: callbackUrl - * description: URL called back after authentication - * in: formData - * required: false - * type: string - * - * responses: - * 200: - * description: Created application's information - * schema: - * $ref: "#/definitions/Application" - * - * default: - * description: Failed - * schema: - * $ref: "#/definitions/Error" - */ +export const meta = { + requireCredential: true +}; /** * Create an app */ -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'nameId' parameter const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId); if (nameIdErr) return rej('invalid nameId param'); @@ -78,7 +29,7 @@ module.exports = async (params: any, user: ILocalUser) => new Promise(async (res // Get 'callbackUrl' parameter // TODO: Check it is valid url - const [callbackUrl = null, callbackUrlErr] = $.str.optional().nullable().get(params.callbackUrl); + const [callbackUrl = null, callbackUrlErr] = $.str.optional.nullable.get(params.callbackUrl); if (callbackUrlErr) return rej('invalid callbackUrl param'); // Generate secret diff --git a/src/server/api/endpoints/app/name_id/available.ts b/src/server/api/endpoints/app/name_id/available.ts index 58101a7e6a..2cd56e92d6 100644 --- a/src/server/api/endpoints/app/name_id/available.ts +++ b/src/server/api/endpoints/app/name_id/available.ts @@ -5,42 +5,13 @@ import $ from 'cafy'; import App from '../../../../../models/app'; import { isValidNameId } from '../../../../../models/app'; -/** - * @swagger - * /app/nameId/available: - * note: - * summary: Check available nameId on creation an application - * parameters: - * - - * name: nameId - * description: Application unique name - * in: formData - * required: true - * type: string - * - * responses: - * 200: - * description: Success - * schema: - * type: object - * properties: - * available: - * description: Whether nameId is available - * type: boolean - * - * default: - * description: Failed - * schema: - * $ref: "#/definitions/Error" - */ - /** * Check available nameId of app * * @param {any} params * @return {Promise<any>} */ -module.exports = async (params: any) => new Promise(async (res, rej) => { +export default async (params: any) => new Promise(async (res, rej) => { // Get 'nameId' parameter const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId); if (nameIdErr) return rej('invalid nameId param'); diff --git a/src/server/api/endpoints/app/show.ts b/src/server/api/endpoints/app/show.ts index 2b98a3f142..6668d0f243 100644 --- a/src/server/api/endpoints/app/show.ts +++ b/src/server/api/endpoints/app/show.ts @@ -1,49 +1,19 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import App, { pack, IApp } from '../../../../models/app'; import { ILocalUser } from '../../../../models/user'; -/** - * @swagger - * /app/show: - * note: - * summary: Show an application's information - * description: Require appId or nameId - * parameters: - * - - * name: appId - * description: Application ID - * in: formData - * type: string - * - - * name: nameId - * description: Application unique name - * in: formData - * type: string - * - * responses: - * 200: - * description: Success - * schema: - * $ref: "#/definitions/Application" - * - * default: - * description: Failed - * schema: - * $ref: "#/definitions/Error" - */ - /** * Show an app */ -module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { +export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { const isSecure = user != null && app == null; // Get 'appId' parameter - const [appId, appIdErr] = $.type(ID).optional().get(params.appId); + const [appId, appIdErr] = $.type(ID).optional.get(params.appId); if (appIdErr) return rej('invalid appId param'); // Get 'nameId' parameter - const [nameId, nameIdErr] = $.str.optional().get(params.nameId); + const [nameId, nameIdErr] = $.str.optional.get(params.nameId); if (nameIdErr) return rej('invalid nameId param'); if (appId === undefined && nameId === undefined) { diff --git a/src/server/api/endpoints/auth/accept.ts b/src/server/api/endpoints/auth/accept.ts index fc6cbc473d..fee68a20a6 100644 --- a/src/server/api/endpoints/auth/accept.ts +++ b/src/server/api/endpoints/auth/accept.ts @@ -6,33 +6,15 @@ import AuthSess from '../../../../models/auth-session'; import AccessToken from '../../../../models/access-token'; import { ILocalUser } from '../../../../models/user'; -/** - * @swagger - * /auth/accept: - * note: - * summary: Accept a session - * parameters: - * - $ref: "#/parameters/NativeToken" - * - - * name: token - * description: Session Token - * in: formData - * required: true - * type: string - * responses: - * 204: - * description: OK - * - * default: - * description: Failed - * schema: - * $ref: "#/definitions/Error" - */ +export const meta = { + requireCredential: true, + secure: true +}; /** * Accept */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'token' parameter const [token, tokenErr] = $.str.get(params.token); if (tokenErr) return rej('invalid token param'); diff --git a/src/server/api/endpoints/auth/session/generate.ts b/src/server/api/endpoints/auth/session/generate.ts index 5a4d99ff3b..bd1face9e3 100644 --- a/src/server/api/endpoints/auth/session/generate.ts +++ b/src/server/api/endpoints/auth/session/generate.ts @@ -7,44 +7,13 @@ import App from '../../../../../models/app'; import AuthSess from '../../../../../models/auth-session'; import config from '../../../../../config'; -/** - * @swagger - * /auth/session/generate: - * note: - * summary: Generate a session - * parameters: - * - - * name: appSecret - * description: App Secret - * in: formData - * required: true - * type: string - * - * responses: - * 200: - * description: OK - * schema: - * type: object - * properties: - * token: - * type: string - * description: Session Token - * url: - * type: string - * description: Authentication form's URL - * default: - * description: Failed - * schema: - * $ref: "#/definitions/Error" - */ - /** * Generate a session * * @param {any} params * @return {Promise<any>} */ -module.exports = (params: any) => new Promise(async (res, rej) => { +export default (params: any) => new Promise(async (res, rej) => { // Get 'appSecret' parameter const [appSecret, appSecretErr] = $.str.get(params.appSecret); if (appSecretErr) return rej('invalid appSecret param'); diff --git a/src/server/api/endpoints/auth/session/show.ts b/src/server/api/endpoints/auth/session/show.ts index 3d3b6bbf61..f2cbfe388e 100644 --- a/src/server/api/endpoints/auth/session/show.ts +++ b/src/server/api/endpoints/auth/session/show.ts @@ -2,50 +2,10 @@ import $ from 'cafy'; import AuthSess, { pack } from '../../../../../models/auth-session'; import { ILocalUser } from '../../../../../models/user'; -/** - * @swagger - * /auth/session/show: - * note: - * summary: Show a session information - * parameters: - * - - * name: token - * description: Session Token - * in: formData - * required: true - * type: string - * - * responses: - * 200: - * description: OK - * schema: - * type: object - * properties: - * createdAt: - * type: string - * format: date-time - * description: Date and time of the session creation - * appId: - * type: string - * description: Application ID - * token: - * type: string - * description: Session Token - * userId: - * type: string - * description: ID of user who create the session - * app: - * $ref: "#/definitions/Application" - * default: - * description: Failed - * schema: - * $ref: "#/definitions/Error" - */ - /** * Show a session */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'token' parameter const [token, tokenErr] = $.str.get(params.token); if (tokenErr) return rej('invalid token param'); diff --git a/src/server/api/endpoints/auth/session/userkey.ts b/src/server/api/endpoints/auth/session/userkey.ts index 3ea48fbe34..97f28464a5 100644 --- a/src/server/api/endpoints/auth/session/userkey.ts +++ b/src/server/api/endpoints/auth/session/userkey.ts @@ -7,49 +7,13 @@ import AuthSess from '../../../../../models/auth-session'; import AccessToken from '../../../../../models/access-token'; import { pack } from '../../../../../models/user'; -/** - * @swagger - * /auth/session/userkey: - * note: - * summary: Get an access token(userkey) - * parameters: - * - - * name: appSecret - * description: App Secret - * in: formData - * required: true - * type: string - * - - * name: token - * description: Session Token - * in: formData - * required: true - * type: string - * - * responses: - * 200: - * description: OK - * schema: - * type: object - * properties: - * userkey: - * type: string - * description: Access Token - * user: - * $ref: "#/definitions/User" - * default: - * description: Failed - * schema: - * $ref: "#/definitions/Error" - */ - /** * Generate a session * * @param {any} params * @return {Promise<any>} */ -module.exports = (params: any) => new Promise(async (res, rej) => { +export default (params: any) => new Promise(async (res, rej) => { // Get 'appSecret' parameter const [appSecret, appSecretErr] = $.str.get(params.appSecret); if (appSecretErr) return rej('invalid appSecret param'); diff --git a/src/server/api/endpoints/drive.ts b/src/server/api/endpoints/drive.ts index 9caad273c8..8ad961494f 100644 --- a/src/server/api/endpoints/drive.ts +++ b/src/server/api/endpoints/drive.ts @@ -1,10 +1,19 @@ import DriveFile from '../../../models/drive-file'; import { ILocalUser } from '../../../models/user'; +import config from '../../../config'; -/** - * Get drive information - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'ドライブの情報を取得します。', + en: 'Get drive information.' + }, + + requireCredential: true, + + kind: 'drive-read' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Calculate drive usage const usage = await DriveFile .aggregate([{ @@ -30,7 +39,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) }); res({ - capacity: user.driveCapacity, + capacity: 1024 * 1024 * config.localDriveCapacityMb, usage: usage }); }); diff --git a/src/server/api/endpoints/drive/files.ts b/src/server/api/endpoints/drive/files.ts index efce750747..063b4adde1 100644 --- a/src/server/api/endpoints/drive/files.ts +++ b/src/server/api/endpoints/drive/files.ts @@ -1,21 +1,29 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import DriveFile, { pack } from '../../../../models/drive-file'; import { ILocalUser } from '../../../../models/user'; -/** - * Get drive files - */ -module.exports = async (params: any, user: ILocalUser) => { +export const meta = { + desc: { + ja: 'ドライブのファイル一覧を取得します。', + en: 'Get files of drive.' + }, + + requireCredential: true, + + kind: 'drive-read' +}; + +export default async (params: any, user: ILocalUser) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) throw 'invalid limit param'; // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) throw 'invalid sinceId param'; // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) throw 'invalid untilId param'; // Check if both of sinceId and untilId is specified @@ -24,11 +32,11 @@ module.exports = async (params: any, user: ILocalUser) => { } // Get 'folderId' parameter - const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId); + const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId); if (folderIdErr) throw 'invalid folderId param'; // Get 'type' parameter - const [type, typeErr] = $.str.optional().match(/^[a-zA-Z\/\-\*]+$/).get(params.type); + const [type, typeErr] = $.str.optional.match(/^[a-zA-Z\/\-\*]+$/).get(params.type); if (typeErr) throw 'invalid type param'; // Construct query diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts index db2626af09..41b7e04b46 100644 --- a/src/server/api/endpoints/drive/files/create.ts +++ b/src/server/api/endpoints/drive/files/create.ts @@ -1,13 +1,50 @@ import * as fs from 'fs'; -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +const ms = require('ms'); +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import { validateFileName, pack } from '../../../../../models/drive-file'; import create from '../../../../../services/drive/add-file'; import { ILocalUser } from '../../../../../models/user'; +import getParams from '../../../get-params'; + +export const meta = { + desc: { + ja: 'ドライブにファイルをアップロードします。', + en: 'Upload a file to drive.' + }, + + requireCredential: true, + + limit: { + duration: ms('1hour'), + max: 100 + }, + + requireFile: true, + + kind: 'drive-write', + + params: { + folderId: $.type(ID).optional.nullable.note({ + default: null, + desc: { + ja: 'フォルダID' + } + }), + + isSensitive: $.bool.optional.note({ + default: false, + desc: { + ja: 'このメディアが「閲覧注意」(NSFW)かどうか', + en: 'Whether this media is NSFW' + } + }) + } +}; /** * Create a file */ -module.exports = async (file: any, params: any, user: ILocalUser): Promise<any> => { +export default async (file: any, params: any, user: ILocalUser): Promise<any> => { if (file == null) { throw 'file is required'; } @@ -27,17 +64,19 @@ module.exports = async (file: any, params: any, user: ILocalUser): Promise<any> name = null; } - // Get 'folderId' parameter - const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId); - if (folderIdErr) throw 'invalid folderId param'; - function cleanup() { fs.unlink(file.path, () => {}); } + const [ps, psErr] = getParams(meta, params); + if (psErr) { + cleanup(); + throw psErr; + } + try { // Create file - const driveFile = await create(user, file.path, name, null, folderId); + const driveFile = await create(user, file.path, name, null, ps.folderId, false, false, null, null, ps.isSensitive); cleanup(); diff --git a/src/server/api/endpoints/drive/files/delete.ts b/src/server/api/endpoints/drive/files/delete.ts index 17eb0eb4b9..02cd96dd8f 100644 --- a/src/server/api/endpoints/drive/files/delete.ts +++ b/src/server/api/endpoints/drive/files/delete.ts @@ -1,13 +1,21 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import DriveFile from '../../../../../models/drive-file'; import del from '../../../../../services/drive/delete-file'; -import { publishDriveStream } from '../../../../../publishers/stream'; +import { publishDriveStream } from '../../../../../stream'; import { ILocalUser } from '../../../../../models/user'; -/** - * Delete a file - */ -module.exports = async (params: any, user: ILocalUser) => { +export const meta = { + desc: { + ja: 'ドライブのファイルを削除します。', + en: 'Delete a file of drive.' + }, + + requireCredential: true, + + kind: 'drive-write' +}; + +export default async (params: any, user: ILocalUser) => { // Get 'fileId' parameter const [fileId, fileIdErr] = $.type(ID).get(params.fileId); if (fileIdErr) throw 'invalid fileId param'; diff --git a/src/server/api/endpoints/drive/files/find.ts b/src/server/api/endpoints/drive/files/find.ts index 75ab91f0a1..aa44ee688e 100644 --- a/src/server/api/endpoints/drive/files/find.ts +++ b/src/server/api/endpoints/drive/files/find.ts @@ -1,17 +1,20 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import DriveFile, { pack } from '../../../../../models/drive-file'; import { ILocalUser } from '../../../../../models/user'; -/** - * Find a file(s) - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + + kind: 'drive-read' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'name' parameter const [name, nameErr] = $.str.get(params.name); if (nameErr) return rej('invalid name param'); // Get 'folderId' parameter - const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId); + const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId); if (folderIdErr) return rej('invalid folderId param'); // Issue query diff --git a/src/server/api/endpoints/drive/files/show.ts b/src/server/api/endpoints/drive/files/show.ts index e7dca486c5..6a66c7a272 100644 --- a/src/server/api/endpoints/drive/files/show.ts +++ b/src/server/api/endpoints/drive/files/show.ts @@ -1,11 +1,19 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import DriveFile, { pack } from '../../../../../models/drive-file'; import { ILocalUser } from '../../../../../models/user'; -/** - * Show a file - */ -module.exports = async (params: any, user: ILocalUser) => { +export const meta = { + desc: { + ja: '指定したドライブのファイルの情報を取得します。', + en: 'Get specified file of drive.' + }, + + requireCredential: true, + + kind: 'drive-read' +}; + +export default async (params: any, user: ILocalUser) => { // Get 'fileId' parameter const [fileId, fileIdErr] = $.type(ID).get(params.fileId); if (fileIdErr) throw 'invalid fileId param'; diff --git a/src/server/api/endpoints/drive/files/update.ts b/src/server/api/endpoints/drive/files/update.ts index 825683b214..bac04bae78 100644 --- a/src/server/api/endpoints/drive/files/update.ts +++ b/src/server/api/endpoints/drive/files/update.ts @@ -1,21 +1,60 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import DriveFolder from '../../../../../models/drive-folder'; import DriveFile, { validateFileName, pack } from '../../../../../models/drive-file'; -import { publishDriveStream } from '../../../../../publishers/stream'; +import { publishDriveStream } from '../../../../../stream'; import { ILocalUser } from '../../../../../models/user'; +import getParams from '../../../get-params'; -/** - * Update a file - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { - // Get 'fileId' parameter - const [fileId, fileIdErr] = $.type(ID).get(params.fileId); - if (fileIdErr) return rej('invalid fileId param'); +export const meta = { + desc: { + ja: '指定したドライブのファイルの情報を更新します。', + en: 'Update specified file of drive.' + }, + + requireCredential: true, + + kind: 'drive-write', + + params: { + fileId: $.type(ID).note({ + desc: { + ja: '対象のファイルID' + } + }), + + folderId: $.type(ID).optional.nullable.note({ + default: undefined, + desc: { + ja: 'フォルダID' + } + }), + + name: $.str.optional.pipe(validateFileName).note({ + default: undefined, + desc: { + ja: 'ファイル名', + en: 'Name of the file' + } + }), + + isSensitive: $.bool.optional.note({ + default: undefined, + desc: { + ja: 'このメディアが「閲覧注意」(NSFW)かどうか', + en: 'Whether this media is NSFW' + } + }) + } +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) return rej(psErr); // Fetch file const file = await DriveFile .findOne({ - _id: fileId, + _id: ps.fileId, 'metadata.userId': user._id }); @@ -23,23 +62,18 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) return rej('file-not-found'); } - // Get 'name' parameter - const [name, nameErr] = $.str.optional().pipe(validateFileName).get(params.name); - if (nameErr) return rej('invalid name param'); - if (name) file.filename = name; + if (ps.name) file.filename = ps.name; - // Get 'folderId' parameter - const [folderId, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId); - if (folderIdErr) return rej('invalid folderId param'); + if (ps.isSensitive) file.metadata.isSensitive = ps.isSensitive; - if (folderId !== undefined) { - if (folderId === null) { + if (ps.folderId !== undefined) { + if (ps.folderId === null) { file.metadata.folderId = null; } else { // Fetch folder const folder = await DriveFolder .findOne({ - _id: folderId, + _id: ps.folderId, userId: user._id }); @@ -54,7 +88,8 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) await DriveFile.update(file._id, { $set: { filename: file.filename, - 'metadata.folderId': file.metadata.folderId + 'metadata.folderId': file.metadata.folderId, + 'metadata.isSensitive': file.metadata.isSensitive } }); diff --git a/src/server/api/endpoints/drive/files/upload_from_url.ts b/src/server/api/endpoints/drive/files/upload_from_url.ts index cb617d851f..d634cf46db 100644 --- a/src/server/api/endpoints/drive/files/upload_from_url.ts +++ b/src/server/api/endpoints/drive/files/upload_from_url.ts @@ -1,22 +1,35 @@ -/** - * Module dependencies - */ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; +const ms = require('ms'); import { pack } from '../../../../../models/drive-file'; import uploadFromUrl from '../../../../../services/drive/upload-from-url'; import { ILocalUser } from '../../../../../models/user'; +export const meta = { + desc: { + ja: 'ドライブに指定されたURLに存在するファイルをアップロードします。' + }, + + limit: { + duration: ms('1hour'), + max: 10 + }, + + requireCredential: true, + + kind: 'drive-write' +}; + /** * Create a file from a URL */ -module.exports = async (params: any, user: ILocalUser): Promise<any> => { +export default async (params: any, user: ILocalUser): Promise<any> => { // Get 'url' parameter // TODO: Validate this url const [url, urlErr] = $.str.get(params.url); if (urlErr) throw 'invalid url param'; // Get 'folderId' parameter - const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId); + const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId); if (folderIdErr) throw 'invalid folderId param'; return pack(await uploadFromUrl(url, user, folderId)); diff --git a/src/server/api/endpoints/drive/folders.ts b/src/server/api/endpoints/drive/folders.ts index 3413778950..de398eb720 100644 --- a/src/server/api/endpoints/drive/folders.ts +++ b/src/server/api/endpoints/drive/folders.ts @@ -1,21 +1,29 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import DriveFolder, { pack } from '../../../../models/drive-folder'; import { ILocalUser } from '../../../../models/user'; -/** - * Get drive folders - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'ドライブのフォルダ一覧を取得します。', + en: 'Get folders of drive.' + }, + + requireCredential: true, + + kind: 'drive-read' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Check if both of sinceId and untilId is specified @@ -24,7 +32,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) } // Get 'folderId' parameter - const [folderId = null, folderIdErr] = $.type(ID).optional().nullable().get(params.folderId); + const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId); if (folderIdErr) return rej('invalid folderId param'); // Construct query diff --git a/src/server/api/endpoints/drive/folders/create.ts b/src/server/api/endpoints/drive/folders/create.ts index 8f06b0f668..03f9504774 100644 --- a/src/server/api/endpoints/drive/folders/create.ts +++ b/src/server/api/endpoints/drive/folders/create.ts @@ -1,18 +1,26 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder'; -import { publishDriveStream } from '../../../../../publishers/stream'; +import { publishDriveStream } from '../../../../../stream'; import { ILocalUser } from '../../../../../models/user'; -/** - * Create drive folder - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'ドライブのフォルダを作成します。', + en: 'Create a folder of drive.' + }, + + requireCredential: true, + + kind: 'drive-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'name' parameter - const [name = '無題のフォルダー', nameErr] = $.str.optional().pipe(isValidFolderName).get(params.name); + const [name = '無題のフォルダー', nameErr] = $.str.optional.pipe(isValidFolderName).get(params.name); if (nameErr) return rej('invalid name param'); // Get 'parentId' parameter - const [parentId = null, parentIdErr] = $.type(ID).optional().nullable().get(params.parentId); + const [parentId = null, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId); if (parentIdErr) return rej('invalid parentId param'); // If the parent folder is specified diff --git a/src/server/api/endpoints/drive/folders/find.ts b/src/server/api/endpoints/drive/folders/find.ts index b3238b5c32..ec3c1d2e36 100644 --- a/src/server/api/endpoints/drive/folders/find.ts +++ b/src/server/api/endpoints/drive/folders/find.ts @@ -1,17 +1,20 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import DriveFolder, { pack } from '../../../../../models/drive-folder'; import { ILocalUser } from '../../../../../models/user'; -/** - * Find a folder(s) - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + + kind: 'drive-read' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'name' parameter const [name, nameErr] = $.str.get(params.name); if (nameErr) return rej('invalid name param'); // Get 'parentId' parameter - const [parentId = null, parentIdErr] = $.type(ID).optional().nullable().get(params.parentId); + const [parentId = null, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId); if (parentIdErr) return rej('invalid parentId param'); // Issue query diff --git a/src/server/api/endpoints/drive/folders/show.ts b/src/server/api/endpoints/drive/folders/show.ts index c9b4930a76..6a6c879a01 100644 --- a/src/server/api/endpoints/drive/folders/show.ts +++ b/src/server/api/endpoints/drive/folders/show.ts @@ -1,11 +1,18 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import DriveFolder, { pack } from '../../../../../models/drive-folder'; import { ILocalUser } from '../../../../../models/user'; -/** - * Show a folder - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定したドライブのフォルダの情報を取得します。' + }, + + requireCredential: true, + + kind: 'drive-read' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'folderId' parameter const [folderId, folderIdErr] = $.type(ID).get(params.folderId); if (folderIdErr) return rej('invalid folderId param'); diff --git a/src/server/api/endpoints/drive/folders/update.ts b/src/server/api/endpoints/drive/folders/update.ts index f126c09f5b..1b449428a6 100644 --- a/src/server/api/endpoints/drive/folders/update.ts +++ b/src/server/api/endpoints/drive/folders/update.ts @@ -1,12 +1,20 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder'; -import { publishDriveStream } from '../../../../../publishers/stream'; +import { publishDriveStream } from '../../../../../stream'; import { ILocalUser } from '../../../../../models/user'; -/** - * Update a folder - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定したドライブのフォルダの情報を更新します。', + en: 'Update specified folder of drive.' + }, + + requireCredential: true, + + kind: 'drive-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'folderId' parameter const [folderId, folderIdErr] = $.type(ID).get(params.folderId); if (folderIdErr) return rej('invalid folderId param'); @@ -23,12 +31,12 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) } // Get 'name' parameter - const [name, nameErr] = $.str.optional().pipe(isValidFolderName).get(params.name); + const [name, nameErr] = $.str.optional.pipe(isValidFolderName).get(params.name); if (nameErr) return rej('invalid name param'); if (name) folder.name = name; // Get 'parentId' parameter - const [parentId, parentIdErr] = $.type(ID).optional().nullable().get(params.parentId); + const [parentId, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId); if (parentIdErr) return rej('invalid parentId param'); if (parentId !== undefined) { if (parentId === null) { diff --git a/src/server/api/endpoints/drive/stream.ts b/src/server/api/endpoints/drive/stream.ts index 515f74645a..53f94a2639 100644 --- a/src/server/api/endpoints/drive/stream.ts +++ b/src/server/api/endpoints/drive/stream.ts @@ -1,21 +1,24 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import DriveFile, { pack } from '../../../../models/drive-file'; import { ILocalUser } from '../../../../models/user'; -/** - * Get drive stream - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + + kind: 'drive-read' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Check if both of sinceId and untilId is specified @@ -24,7 +27,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) } // Get 'type' parameter - const [type, typeErr] = $.str.optional().match(/^[a-zA-Z\/\-\*]+$/).get(params.type); + const [type, typeErr] = $.str.optional.match(/^[a-zA-Z\/\-\*]+$/).get(params.type); if (typeErr) return rej('invalid type param'); // Construct query diff --git a/src/server/api/endpoints/following/create.ts b/src/server/api/endpoints/following/create.ts index 3e45b8da53..ebe319e0cf 100644 --- a/src/server/api/endpoints/following/create.ts +++ b/src/server/api/endpoints/following/create.ts @@ -1,12 +1,26 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +const ms = require('ms'); import User, { pack, ILocalUser } from '../../../../models/user'; import Following from '../../../../models/following'; import create from '../../../../services/following/create'; -/** - * Follow a user - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定したユーザーをフォローします。', + en: 'Follow a user.' + }, + + limit: { + duration: ms('1hour'), + max: 100 + }, + + requireCredential: true, + + kind: 'following-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const follower = user; // Get 'userId' parameter diff --git a/src/server/api/endpoints/following/delete.ts b/src/server/api/endpoints/following/delete.ts index 0af8813cf9..4806fe4e39 100644 --- a/src/server/api/endpoints/following/delete.ts +++ b/src/server/api/endpoints/following/delete.ts @@ -1,12 +1,26 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +const ms = require('ms'); import User, { pack, ILocalUser } from '../../../../models/user'; import Following from '../../../../models/following'; import deleteFollowing from '../../../../services/following/delete'; -/** - * Unfollow a user - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定したユーザーのフォローを解除します。', + en: 'Unfollow a user.' + }, + + limit: { + duration: ms('1hour'), + max: 100 + }, + + requireCredential: true, + + kind: 'following-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const follower = user; // Get 'userId' parameter diff --git a/src/server/api/endpoints/following/requests/accept.ts b/src/server/api/endpoints/following/requests/accept.ts index a09e32e4d9..b3bf2dd667 100644 --- a/src/server/api/endpoints/following/requests/accept.ts +++ b/src/server/api/endpoints/following/requests/accept.ts @@ -1,11 +1,19 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import acceptFollowRequest from '../../../../../services/following/requests/accept'; import User, { ILocalUser } from '../../../../../models/user'; -/** - * Accept a follow request - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '自分に届いた、指定したフォローリクエストを承認します。', + en: 'Accept a follow request.' + }, + + requireCredential: true, + + kind: 'following-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [followerId, followerIdErr] = $.type(ID).get(params.userId); if (followerIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/following/requests/cancel.ts b/src/server/api/endpoints/following/requests/cancel.ts index f2a40854c2..9bfc40ce65 100644 --- a/src/server/api/endpoints/following/requests/cancel.ts +++ b/src/server/api/endpoints/following/requests/cancel.ts @@ -1,11 +1,19 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import cancelFollowRequest from '../../../../../services/following/requests/cancel'; import User, { pack, ILocalUser } from '../../../../../models/user'; -/** - * Cancel a follow request - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '自分が作成した、指定したフォローリクエストをキャンセルします。', + en: 'Cancel a follow request.' + }, + + requireCredential: true, + + kind: 'following-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [followeeId, followeeIdErr] = $.type(ID).get(params.userId); if (followeeIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/following/requests/list.ts b/src/server/api/endpoints/following/requests/list.ts index 287c5a8e46..b06a158c08 100644 --- a/src/server/api/endpoints/following/requests/list.ts +++ b/src/server/api/endpoints/following/requests/list.ts @@ -2,10 +2,18 @@ import FollowRequest, { pack } from '../../../../../models/follow-request'; import { ILocalUser } from '../../../../../models/user'; -/** - * Get all pending received follow requests - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '自分に届いたフォローリクエストの一覧を取得します。', + en: 'Get all pending received follow requests.' + }, + + requireCredential: true, + + kind: 'following-read' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const reqs = await FollowRequest.find({ followeeId: user._id }); diff --git a/src/server/api/endpoints/following/requests/reject.ts b/src/server/api/endpoints/following/requests/reject.ts index 69dddf1355..a232549bb8 100644 --- a/src/server/api/endpoints/following/requests/reject.ts +++ b/src/server/api/endpoints/following/requests/reject.ts @@ -1,11 +1,19 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import rejectFollowRequest from '../../../../../services/following/requests/reject'; import User, { ILocalUser } from '../../../../../models/user'; -/** - * Reject a follow request - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '自分に届いた、指定したフォローリクエストを拒否します。', + en: 'Reject a follow request.' + }, + + requireCredential: true, + + kind: 'following-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [followerId, followerIdErr] = $.type(ID).get(params.userId); if (followerIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/following/stalk.ts b/src/server/api/endpoints/following/stalk.ts index b9d19d57b4..79a3fb976c 100644 --- a/src/server/api/endpoints/following/stalk.ts +++ b/src/server/api/endpoints/following/stalk.ts @@ -1,11 +1,19 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Following from '../../../../models/following'; import { ILocalUser } from '../../../../models/user'; -/** - * Stalk a user - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定したユーザーをストーキングします。', + en: 'Stalk a user.' + }, + + requireCredential: true, + + kind: 'following-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const follower = user; // Get 'userId' parameter diff --git a/src/server/api/endpoints/following/unstalk.ts b/src/server/api/endpoints/following/unstalk.ts index 255f22ca1f..71a7a97eeb 100644 --- a/src/server/api/endpoints/following/unstalk.ts +++ b/src/server/api/endpoints/following/unstalk.ts @@ -1,11 +1,19 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Following from '../../../../models/following'; import { ILocalUser } from '../../../../models/user'; -/** - * Unstalk a user - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定したユーザーのストーキングをやめます。', + en: 'Unstalk a user.' + }, + + requireCredential: true, + + kind: 'following-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const follower = user; // Get 'userId' parameter diff --git a/src/server/api/endpoints/reversi/games.ts b/src/server/api/endpoints/games/reversi/games.ts similarity index 60% rename from src/server/api/endpoints/reversi/games.ts rename to src/server/api/endpoints/games/reversi/games.ts index 1455f191f7..2838940b5c 100644 --- a/src/server/api/endpoints/reversi/games.ts +++ b/src/server/api/endpoints/games/reversi/games.ts @@ -1,22 +1,25 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; -import ReversiGame, { pack } from '../../../../models/reversi-game'; -import { ILocalUser } from '../../../../models/user'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; +import ReversiGame, { pack } from '../../../../../models/games/reversi/game'; +import { ILocalUser } from '../../../../../models/user'; -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'my' parameter - const [my = false, myErr] = $.bool.optional().get(params.my); + const [my = false, myErr] = $.bool.optional.get(params.my); if (myErr) return rej('invalid my param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Check if both of sinceId and untilId is specified diff --git a/src/server/api/endpoints/reversi/games/show.ts b/src/server/api/endpoints/games/reversi/games/show.ts similarity index 63% rename from src/server/api/endpoints/reversi/games/show.ts rename to src/server/api/endpoints/games/reversi/games/show.ts index d70ee547a2..8d7cd987a0 100644 --- a/src/server/api/endpoints/reversi/games/show.ts +++ b/src/server/api/endpoints/games/reversi/games/show.ts @@ -1,9 +1,9 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; -import ReversiGame, { pack } from '../../../../../models/reversi-game'; -import Reversi from '../../../../../reversi/core'; -import { ILocalUser } from '../../../../../models/user'; +import $ from 'cafy'; import ID from '../../../../../../misc/cafy-id'; +import ReversiGame, { pack } from '../../../../../../models/games/reversi/game'; +import Reversi from '../../../../../../games/reversi/core'; +import { ILocalUser } from '../../../../../../models/user'; -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'gameId' parameter const [gameId, gameIdErr] = $.type(ID).get(params.gameId); if (gameIdErr) return rej('invalid gameId param'); diff --git a/src/server/api/endpoints/games/reversi/invitations.ts b/src/server/api/endpoints/games/reversi/invitations.ts new file mode 100644 index 0000000000..3962282759 --- /dev/null +++ b/src/server/api/endpoints/games/reversi/invitations.ts @@ -0,0 +1,20 @@ +import Matching, { pack as packMatching } from '../../../../../models/games/reversi/matching'; +import { ILocalUser } from '../../../../../models/user'; + +export const meta = { + requireCredential: true +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + // Find session + const invitations = await Matching.find({ + childId: user._id + }, { + sort: { + _id: -1 + } + }); + + // Reponse + res(Promise.all(invitations.map(async (i) => await packMatching(i, user)))); +}); diff --git a/src/server/api/endpoints/reversi/match.ts b/src/server/api/endpoints/games/reversi/match.ts similarity index 73% rename from src/server/api/endpoints/reversi/match.ts rename to src/server/api/endpoints/games/reversi/match.ts index 907df7cf43..aba400af1d 100644 --- a/src/server/api/endpoints/reversi/match.ts +++ b/src/server/api/endpoints/games/reversi/match.ts @@ -1,11 +1,15 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; -import Matching, { pack as packMatching } from '../../../../models/reversi-matching'; -import ReversiGame, { pack as packGame } from '../../../../models/reversi-game'; -import User, { ILocalUser } from '../../../../models/user'; -import publishUserStream, { publishReversiStream } from '../../../../publishers/stream'; -import { eighteight } from '../../../../reversi/maps'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; +import Matching, { pack as packMatching } from '../../../../../models/games/reversi/matching'; +import ReversiGame, { pack as packGame } from '../../../../../models/games/reversi/game'; +import User, { ILocalUser } from '../../../../../models/user'; +import { publishUserStream, publishReversiStream } from '../../../../../stream'; +import { eighteight } from '../../../../../games/reversi/maps'; -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [childId, childIdErr] = $.type(ID).get(params.userId); if (childIdErr) return rej('invalid userId param'); diff --git a/src/server/api/endpoints/games/reversi/match/cancel.ts b/src/server/api/endpoints/games/reversi/match/cancel.ts new file mode 100644 index 0000000000..d5c186409c --- /dev/null +++ b/src/server/api/endpoints/games/reversi/match/cancel.ts @@ -0,0 +1,14 @@ +import Matching from '../../../../../../models/games/reversi/matching'; +import { ILocalUser } from '../../../../../../models/user'; + +export const meta = { + requireCredential: true +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + await Matching.remove({ + parentId: user._id + }); + + res(); +}); diff --git a/src/server/api/endpoints/hashtags/search.ts b/src/server/api/endpoints/hashtags/search.ts new file mode 100644 index 0000000000..262370cacc --- /dev/null +++ b/src/server/api/endpoints/hashtags/search.ts @@ -0,0 +1,52 @@ +import $ from 'cafy'; +import Hashtag from '../../../../models/hashtag'; +import getParams from '../../get-params'; +const escapeRegexp = require('escape-regexp'); + +export const meta = { + desc: { + ja: 'ハッシュタグを検索します。' + }, + + requireCredential: false, + + params: { + limit: $.num.optional.range(1, 100).note({ + default: 10, + desc: { + ja: '最大数' + } + }), + + query: $.str.note({ + desc: { + ja: 'クエリ' + } + }), + + offset: $.num.optional.min(0).note({ + default: 0, + desc: { + ja: 'オフセット' + } + }) + } +}; + +export default (params: any) => new Promise(async (res, rej) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) throw psErr; + + const hashtags = await Hashtag + .find({ + tag: new RegExp('^' + escapeRegexp(ps.query.toLowerCase())) + }, { + sort: { + count: -1 + }, + limit: ps.limit, + skip: ps.offset + }); + + res(hashtags.map(tag => tag.tag)); +}); diff --git a/src/server/api/endpoints/hashtags/trend.ts b/src/server/api/endpoints/hashtags/trend.ts index 17af9d6a9a..01dfccc71c 100644 --- a/src/server/api/endpoints/hashtags/trend.ts +++ b/src/server/api/endpoints/hashtags/trend.ts @@ -15,7 +15,7 @@ const max = 5; /** * Get trends of hashtags */ -module.exports = () => new Promise(async (res, rej) => { +export default () => new Promise(async (res, rej) => { //#region 1. 直近Aの内に投稿されたハッシュタグ(とユーザーのペア)を集計 const data = await Note.aggregate([{ $match: { diff --git a/src/server/api/endpoints/i.ts b/src/server/api/endpoints/i.ts index 5c769a02fd..7f25c07957 100644 --- a/src/server/api/endpoints/i.ts +++ b/src/server/api/endpoints/i.ts @@ -1,10 +1,22 @@ import User, { pack, ILocalUser } from '../../../models/user'; import { IApp } from '../../../models/app'; -/** - * Show myself - */ -module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '自分のアカウント情報を取得します。' + }, + + requireCredential: true, + + params: {}, + + res: { + type: 'entity', + entity: 'User' + } +}; + +export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { const isSecure = user != null && app == null; // Serialize diff --git a/src/server/api/endpoints/i/2fa/done.ts b/src/server/api/endpoints/i/2fa/done.ts index 61f13c4c61..6d38ca1de1 100644 --- a/src/server/api/endpoints/i/2fa/done.ts +++ b/src/server/api/endpoints/i/2fa/done.ts @@ -2,7 +2,12 @@ import $ from 'cafy'; import * as speakeasy from 'speakeasy'; import User, { ILocalUser } from '../../../../../models/user'; -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + secure: true +}; + +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'token' parameter const [token, tokenErr] = $.str.get(params.token); if (tokenErr) return rej('invalid token param'); diff --git a/src/server/api/endpoints/i/2fa/register.ts b/src/server/api/endpoints/i/2fa/register.ts index d05892c84b..0466a4f366 100644 --- a/src/server/api/endpoints/i/2fa/register.ts +++ b/src/server/api/endpoints/i/2fa/register.ts @@ -5,7 +5,12 @@ import * as QRCode from 'qrcode'; import User, { ILocalUser } from '../../../../../models/user'; import config from '../../../../../config'; -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + secure: true +}; + +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'password' parameter const [password, passwordErr] = $.str.get(params.password); if (passwordErr) return rej('invalid password param'); diff --git a/src/server/api/endpoints/i/2fa/unregister.ts b/src/server/api/endpoints/i/2fa/unregister.ts index fc197cb1e4..accf3ea0f2 100644 --- a/src/server/api/endpoints/i/2fa/unregister.ts +++ b/src/server/api/endpoints/i/2fa/unregister.ts @@ -2,7 +2,12 @@ import $ from 'cafy'; import * as bcrypt from 'bcryptjs'; import User, { ILocalUser } from '../../../../../models/user'; -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + secure: true +}; + +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'password' parameter const [password, passwordErr] = $.str.get(params.password); if (passwordErr) return rej('invalid password param'); diff --git a/src/server/api/endpoints/i/authorized_apps.ts b/src/server/api/endpoints/i/authorized_apps.ts index cfc93c1518..313bb474f4 100644 --- a/src/server/api/endpoints/i/authorized_apps.ts +++ b/src/server/api/endpoints/i/authorized_apps.ts @@ -3,20 +3,22 @@ import AccessToken from '../../../../models/access-token'; import { pack } from '../../../../models/app'; import { ILocalUser } from '../../../../models/user'; -/** - * Get authorized apps of my account - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + secure: true +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // Get 'sort' parameter - const [sort = 'desc', sortError] = $.str.optional().or('desc asc').get(params.sort); + const [sort = 'desc', sortError] = $.str.optional.or('desc asc').get(params.sort); if (sortError) return rej('invalid sort param'); // Get tokens diff --git a/src/server/api/endpoints/i/change_password.ts b/src/server/api/endpoints/i/change_password.ts index 9851fa895a..dc0f060c08 100644 --- a/src/server/api/endpoints/i/change_password.ts +++ b/src/server/api/endpoints/i/change_password.ts @@ -2,10 +2,12 @@ import $ from 'cafy'; import * as bcrypt from 'bcryptjs'; import User, { ILocalUser } from '../../../../models/user'; -/** - * Change password - */ -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + secure: true +}; + +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'currentPasword' parameter const [currentPassword, currentPasswordErr] = $.str.get(params.currentPasword); if (currentPasswordErr) return rej('invalid currentPasword param'); diff --git a/src/server/api/endpoints/i/favorites.ts b/src/server/api/endpoints/i/favorites.ts index dc343afaed..47c8a87fd9 100644 --- a/src/server/api/endpoints/i/favorites.ts +++ b/src/server/api/endpoints/i/favorites.ts @@ -1,21 +1,29 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Favorite, { pack } from '../../../../models/favorite'; import { ILocalUser } from '../../../../models/user'; -/** - * Get favorited notes - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'お気に入りに登録した投稿一覧を取得します。', + en: 'Get favorited notes' + }, + + requireCredential: true, + + kind: 'favorites-read' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Check if both of sinceId and untilId is specified diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts index ce283fe48f..b6865fba52 100644 --- a/src/server/api/endpoints/i/notifications.ts +++ b/src/server/api/endpoints/i/notifications.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Notification from '../../../../models/notification'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/notification'; @@ -9,30 +9,30 @@ import { ILocalUser } from '../../../../models/user'; /** * Get notifications */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'following' parameter const [following = false, followingError] = - $.bool.optional().get(params.following); + $.bool.optional.get(params.following); if (followingError) return rej('invalid following param'); // Get 'markAsRead' parameter - const [markAsRead = true, markAsReadErr] = $.bool.optional().get(params.markAsRead); + const [markAsRead = true, markAsReadErr] = $.bool.optional.get(params.markAsRead); if (markAsReadErr) return rej('invalid markAsRead param'); // Get 'type' parameter - const [type, typeErr] = $.arr($.str).optional().unique().get(params.type); + const [type, typeErr] = $.arr($.str).optional.unique().get(params.type); if (typeErr) return rej('invalid type param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Check if both of sinceId and untilId is specified @@ -96,7 +96,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) // Serialize res(await Promise.all(notifications.map(notification => pack(notification)))); - // Mark as read all + // Mark all as read if (notifications.length > 0 && markAsRead) { read(user._id, notifications); } diff --git a/src/server/api/endpoints/i/pin.ts b/src/server/api/endpoints/i/pin.ts index 7f4a45e1f5..ae03a86336 100644 --- a/src/server/api/endpoints/i/pin.ts +++ b/src/server/api/endpoints/i/pin.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import User, { ILocalUser } from '../../../../models/user'; import Note from '../../../../models/note'; import { pack } from '../../../../models/user'; @@ -6,7 +6,7 @@ import { pack } from '../../../../models/user'; /** * Pin note */ -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/i/regenerate_token.ts b/src/server/api/endpoints/i/regenerate_token.ts index 3ffab5428e..fe4a5cd118 100644 --- a/src/server/api/endpoints/i/regenerate_token.ts +++ b/src/server/api/endpoints/i/regenerate_token.ts @@ -1,13 +1,15 @@ import $ from 'cafy'; import * as bcrypt from 'bcryptjs'; import User, { ILocalUser } from '../../../../models/user'; -import event from '../../../../publishers/stream'; +import { publishUserStream } from '../../../../stream'; import generateUserToken from '../../common/generate-native-user-token'; -/** - * Regenerate native token - */ -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + secure: true +}; + +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'password' parameter const [password, passwordErr] = $.str.get(params.password); if (passwordErr) return rej('invalid password param'); @@ -31,5 +33,5 @@ module.exports = async (params: any, user: ILocalUser) => new Promise(async (res res(); // Publish event - event(user._id, 'my_token_regenerated'); + publishUserStream(user._id, 'my_token_regenerated'); }); diff --git a/src/server/api/endpoints/i/signin_history.ts b/src/server/api/endpoints/i/signin_history.ts index 4ab9881f34..5a3c122f3a 100644 --- a/src/server/api/endpoints/i/signin_history.ts +++ b/src/server/api/endpoints/i/signin_history.ts @@ -1,21 +1,23 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Signin, { pack } from '../../../../models/signin'; import { ILocalUser } from '../../../../models/user'; -/** - * Get signin history of my account - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + secure: true +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Check if both of sinceId and untilId is specified diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts index 57b050ebc4..aa801b1b04 100644 --- a/src/server/api/endpoints/i/update.ts +++ b/src/server/api/endpoints/i/update.ts @@ -1,70 +1,79 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack, ILocalUser } from '../../../../models/user'; -import event from '../../../../publishers/stream'; +import { publishUserStream } from '../../../../stream'; import DriveFile from '../../../../models/drive-file'; import acceptAllFollowRequests from '../../../../services/following/requests/accept-all'; import { IApp } from '../../../../models/app'; +import config from '../../../../config'; -/** - * Update myself - */ -module.exports = async (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'アカウント情報を更新します。', + en: 'Update myself' + }, + + requireCredential: true, + + kind: 'account-write' +}; + +export default async (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { const isSecure = user != null && app == null; const updates = {} as any; // Get 'name' parameter - const [name, nameErr] = $.str.optional().nullable().pipe(isValidName).get(params.name); + const [name, nameErr] = $.str.optional.nullable.pipe(isValidName).get(params.name); if (nameErr) return rej('invalid name param'); if (name) updates.name = name; // Get 'description' parameter - const [description, descriptionErr] = $.str.optional().nullable().pipe(isValidDescription).get(params.description); + const [description, descriptionErr] = $.str.optional.nullable.pipe(isValidDescription).get(params.description); if (descriptionErr) return rej('invalid description param'); if (description !== undefined) updates.description = description; // Get 'location' parameter - const [location, locationErr] = $.str.optional().nullable().pipe(isValidLocation).get(params.location); + const [location, locationErr] = $.str.optional.nullable.pipe(isValidLocation).get(params.location); if (locationErr) return rej('invalid location param'); if (location !== undefined) updates['profile.location'] = location; // Get 'birthday' parameter - const [birthday, birthdayErr] = $.str.optional().nullable().pipe(isValidBirthday).get(params.birthday); + const [birthday, birthdayErr] = $.str.optional.nullable.pipe(isValidBirthday).get(params.birthday); if (birthdayErr) return rej('invalid birthday param'); if (birthday !== undefined) updates['profile.birthday'] = birthday; // Get 'avatarId' parameter - const [avatarId, avatarIdErr] = $.type(ID).optional().nullable().get(params.avatarId); + const [avatarId, avatarIdErr] = $.type(ID).optional.nullable.get(params.avatarId); if (avatarIdErr) return rej('invalid avatarId param'); if (avatarId !== undefined) updates.avatarId = avatarId; // Get 'bannerId' parameter - const [bannerId, bannerIdErr] = $.type(ID).optional().nullable().get(params.bannerId); + const [bannerId, bannerIdErr] = $.type(ID).optional.nullable.get(params.bannerId); if (bannerIdErr) return rej('invalid bannerId param'); if (bannerId !== undefined) updates.bannerId = bannerId; // Get 'wallpaperId' parameter - const [wallpaperId, wallpaperIdErr] = $.type(ID).optional().nullable().get(params.wallpaperId); + const [wallpaperId, wallpaperIdErr] = $.type(ID).optional.nullable.get(params.wallpaperId); if (wallpaperIdErr) return rej('invalid wallpaperId param'); if (wallpaperId !== undefined) updates.wallpaperId = wallpaperId; // Get 'isLocked' parameter - const [isLocked, isLockedErr] = $.bool.optional().get(params.isLocked); + const [isLocked, isLockedErr] = $.bool.optional.get(params.isLocked); if (isLockedErr) return rej('invalid isLocked param'); if (isLocked != null) updates.isLocked = isLocked; // Get 'isBot' parameter - const [isBot, isBotErr] = $.bool.optional().get(params.isBot); + const [isBot, isBotErr] = $.bool.optional.get(params.isBot); if (isBotErr) return rej('invalid isBot param'); if (isBot != null) updates.isBot = isBot; // Get 'isCat' parameter - const [isCat, isCatErr] = $.bool.optional().get(params.isCat); + const [isCat, isCatErr] = $.bool.optional.get(params.isCat); if (isCatErr) return rej('invalid isCat param'); if (isCat != null) updates.isCat = isCat; // Get 'autoWatch' parameter - const [autoWatch, autoWatchErr] = $.bool.optional().get(params.autoWatch); + const [autoWatch, autoWatchErr] = $.bool.optional.get(params.autoWatch); if (autoWatchErr) return rej('invalid autoWatch param'); if (autoWatch != null) updates['settings.autoWatch'] = autoWatch; @@ -73,7 +82,11 @@ module.exports = async (params: any, user: ILocalUser, app: IApp) => new Promise _id: avatarId }); - if (avatar != null && avatar.metadata.properties.avgColor) { + if (avatar == null) return rej('avatar not found'); + + updates.avatarUrl = avatar.metadata.url || `${config.drive_url}/${avatar._id}`; + + if (avatar.metadata.properties.avgColor) { updates.avatarColor = avatar.metadata.properties.avgColor; } } @@ -83,7 +96,11 @@ module.exports = async (params: any, user: ILocalUser, app: IApp) => new Promise _id: bannerId }); - if (banner != null && banner.metadata.properties.avgColor) { + if (banner == null) return rej('banner not found'); + + updates.bannerUrl = banner.metadata.url || `${config.drive_url}/${banner._id}`; + + if (banner.metadata.properties.avgColor) { updates.bannerColor = banner.metadata.properties.avgColor; } } @@ -93,7 +110,11 @@ module.exports = async (params: any, user: ILocalUser, app: IApp) => new Promise _id: wallpaperId }); - if (wallpaper != null && wallpaper.metadata.properties.avgColor) { + if (wallpaper == null) return rej('wallpaper not found'); + + updates.wallpaperUrl = wallpaper.metadata.url || `${config.drive_url}/${wallpaper._id}`; + + if (wallpaper.metadata.properties.avgColor) { updates.wallpaperColor = wallpaper.metadata.properties.avgColor; } } @@ -112,7 +133,7 @@ module.exports = async (params: any, user: ILocalUser, app: IApp) => new Promise res(iObj); // Publish meUpdated event - event(user._id, 'meUpdated', iObj); + publishUserStream(user._id, 'meUpdated', iObj); // 鍵垢を解除したとき、溜まっていたフォローリクエストがあるならすべて承認 if (user.isLocked && isLocked === false) { diff --git a/src/server/api/endpoints/i/update_client_setting.ts b/src/server/api/endpoints/i/update_client_setting.ts index 6d6e8ed24a..aed93c792f 100644 --- a/src/server/api/endpoints/i/update_client_setting.ts +++ b/src/server/api/endpoints/i/update_client_setting.ts @@ -1,17 +1,19 @@ import $ from 'cafy'; import User, { ILocalUser } from '../../../../models/user'; -import event from '../../../../publishers/stream'; +import { publishUserStream } from '../../../../stream'; -/** - * Update myself - */ -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + secure: true +}; + +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'name' parameter const [name, nameErr] = $.str.get(params.name); if (nameErr) return rej('invalid name param'); // Get 'value' parameter - const [value, valueErr] = $.any.nullable().get(params.value); + const [value, valueErr] = $.any.nullable.get(params.value); if (valueErr) return rej('invalid value param'); const x: any = {}; @@ -24,7 +26,7 @@ module.exports = async (params: any, user: ILocalUser) => new Promise(async (res res(); // Publish event - event(user._id, 'clientSettingUpdated', { + publishUserStream(user._id, 'clientSettingUpdated', { key: name, value }); diff --git a/src/server/api/endpoints/i/update_home.ts b/src/server/api/endpoints/i/update_home.ts index 511a647d88..ffca9b90b3 100644 --- a/src/server/api/endpoints/i/update_home.ts +++ b/src/server/api/endpoints/i/update_home.ts @@ -1,16 +1,20 @@ import $ from 'cafy'; import User, { ILocalUser } from '../../../../models/user'; -import event from '../../../../publishers/stream'; +import { publishUserStream } from '../../../../stream'; -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + secure: true +}; + +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'home' parameter - const [home, homeErr] = $.arr( - $.obj.strict() - .have('name', $.str) - .have('id', $.str) - .have('place', $.str) - .have('data', $.obj)) - .get(params.home); + const [home, homeErr] = $.arr($.obj({ + name: $.str, + id: $.str, + place: $.str, + data: $.obj() + }).strict()).get(params.home); if (homeErr) return rej('invalid home param'); await User.update(user._id, { @@ -21,5 +25,5 @@ module.exports = async (params: any, user: ILocalUser) => new Promise(async (res res(); - event(user._id, 'home_updated', home); + publishUserStream(user._id, 'home_updated', home); }); diff --git a/src/server/api/endpoints/i/update_mobile_home.ts b/src/server/api/endpoints/i/update_mobile_home.ts index b1f25624fd..0b72fbe2c1 100644 --- a/src/server/api/endpoints/i/update_mobile_home.ts +++ b/src/server/api/endpoints/i/update_mobile_home.ts @@ -1,15 +1,19 @@ import $ from 'cafy'; import User, { ILocalUser } from '../../../../models/user'; -import event from '../../../../publishers/stream'; +import { publishUserStream } from '../../../../stream'; -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + secure: true +}; + +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'home' parameter - const [home, homeErr] = $.arr( - $.obj.strict() - .have('name', $.str) - .have('id', $.str) - .have('data', $.obj)) - .get(params.home); + const [home, homeErr] = $.arr($.obj({ + name: $.str, + id: $.str, + data: $.obj() + }).strict()).get(params.home); if (homeErr) return rej('invalid home param'); await User.update(user._id, { @@ -20,5 +24,5 @@ module.exports = async (params: any, user: ILocalUser) => new Promise(async (res res(); - event(user._id, 'mobile_home_updated', home); + publishUserStream(user._id, 'mobile_home_updated', home); }); diff --git a/src/server/api/endpoints/i/update_widget.ts b/src/server/api/endpoints/i/update_widget.ts index 82bb04d1f4..5cbe7c07a3 100644 --- a/src/server/api/endpoints/i/update_widget.ts +++ b/src/server/api/endpoints/i/update_widget.ts @@ -1,14 +1,19 @@ import $ from 'cafy'; import User, { ILocalUser } from '../../../../models/user'; -import event from '../../../../publishers/stream'; +import { publishUserStream } from '../../../../stream'; -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + requireCredential: true, + secure: true +}; + +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'id' parameter const [id, idErr] = $.str.get(params.id); if (idErr) return rej('invalid id param'); // Get 'data' parameter - const [data, dataErr] = $.obj.get(params.data); + const [data, dataErr] = $.obj().get(params.data); if (dataErr) return rej('invalid data param'); if (id == null && data == null) return rej('you need to set id and data params if home param unset'); @@ -68,7 +73,7 @@ module.exports = async (params: any, user: ILocalUser) => new Promise(async (res //#endregion if (widget) { - event(user._id, 'widgetUpdated', { + publishUserStream(user._id, 'widgetUpdated', { id, data }); diff --git a/src/server/api/endpoints/messaging/history.ts b/src/server/api/endpoints/messaging/history.ts index 713ba9dd7f..66798d50c5 100644 --- a/src/server/api/endpoints/messaging/history.ts +++ b/src/server/api/endpoints/messaging/history.ts @@ -4,12 +4,20 @@ import Mute from '../../../../models/mute'; import { pack } from '../../../../models/messaging-message'; import { ILocalUser } from '../../../../models/user'; -/** - * Show messaging history - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'Messagingの履歴を取得します。', + en: 'Show messaging history.' + }, + + requireCredential: true, + + kind: 'messaging-read' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); const mute = await Mute.find({ diff --git a/src/server/api/endpoints/messaging/messages.ts b/src/server/api/endpoints/messaging/messages.ts index 3eb20ec06b..ae26419bc6 100644 --- a/src/server/api/endpoints/messaging/messages.ts +++ b/src/server/api/endpoints/messaging/messages.ts @@ -1,13 +1,21 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Message from '../../../../models/messaging-message'; import User, { ILocalUser } from '../../../../models/user'; import { pack } from '../../../../models/messaging-message'; import read from '../../common/read-messaging-message'; -/** - * Get messages - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定したユーザーとのMessagingのメッセージ一覧を取得します。', + en: 'Get messages of messaging.' + }, + + requireCredential: true, + + kind: 'messaging-read' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [recipientId, recipientIdErr] = $.type(ID).get(params.userId); if (recipientIdErr) return rej('invalid userId param'); @@ -16,29 +24,29 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) const recipient = await User.findOne({ _id: recipientId }, { - fields: { - _id: true - } - }); + fields: { + _id: true + } + }); if (recipient === null) { return rej('user not found'); } // Get 'markAsRead' parameter - const [markAsRead = true, markAsReadErr] = $.bool.optional().get(params.markAsRead); + const [markAsRead = true, markAsReadErr] = $.bool.optional.get(params.markAsRead); if (markAsReadErr) return rej('invalid markAsRead param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Check if both of sinceId and untilId is specified @@ -88,7 +96,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) return; } - // Mark as read all + // Mark all as read if (markAsRead) { read(user._id, recipient._id, messages); } diff --git a/src/server/api/endpoints/messaging/messages/create.ts b/src/server/api/endpoints/messaging/messages/create.ts index b3e4f6a8cd..8ebf1a2a2b 100644 --- a/src/server/api/endpoints/messaging/messages/create.ts +++ b/src/server/api/endpoints/messaging/messages/create.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import Message from '../../../../../models/messaging-message'; import { isValidText } from '../../../../../models/messaging-message'; import History from '../../../../../models/messaging-history'; @@ -6,15 +6,23 @@ import User, { ILocalUser } from '../../../../../models/user'; import Mute from '../../../../../models/mute'; import DriveFile from '../../../../../models/drive-file'; import { pack } from '../../../../../models/messaging-message'; -import publishUserStream from '../../../../../publishers/stream'; -import { publishMessagingStream, publishMessagingIndexStream } from '../../../../../publishers/stream'; -import pushSw from '../../../../../publishers/push-sw'; +import { publishUserStream } from '../../../../../stream'; +import { publishMessagingStream, publishMessagingIndexStream } from '../../../../../stream'; +import pushSw from '../../../../../push-sw'; import config from '../../../../../config'; -/** - * Create a message - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定したユーザーへMessagingのメッセージを送信します。', + en: 'Create a message of messaging.' + }, + + requireCredential: true, + + kind: 'messaging-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [recipientId, recipientIdErr] = $.type(ID).get(params.userId); if (recipientIdErr) return rej('invalid userId param'); @@ -38,11 +46,11 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) } // Get 'text' parameter - const [text, textErr] = $.str.optional().pipe(isValidText).get(params.text); + const [text, textErr] = $.str.optional.pipe(isValidText).get(params.text); if (textErr) return rej('invalid text'); // Get 'fileId' parameter - const [fileId, fileIdErr] = $.type(ID).optional().get(params.fileId); + const [fileId, fileIdErr] = $.type(ID).optional.get(params.fileId); if (fileIdErr) return rej('invalid fileId param'); let file = null; @@ -116,7 +124,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) }, 3000); // Register to search database - if (message.text && config.elasticsearch.enable) { + if (message.text && config.elasticsearch) { const es = require('../../../db/elasticsearch'); es.index({ diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts index ce460d0b8b..c2d93997a7 100644 --- a/src/server/api/endpoints/meta.ts +++ b/src/server/api/endpoints/meta.ts @@ -8,37 +8,10 @@ import Meta from '../../../models/meta'; const pkg = require('../../../../package.json'); const client = require('../../../../built/client/meta.json'); -/** - * @swagger - * /meta: - * note: - * summary: Show the misskey's information - * responses: - * 200: - * description: Success - * schema: - * type: object - * properties: - * maintainer: - * description: maintainer's name - * type: string - * commit: - * description: latest commit's hash - * type: string - * secure: - * description: whether the server supports secure protocols - * type: boolean - * - * default: - * description: Failed - * schema: - * $ref: "#/definitions/Error" - */ - /** * Show core info */ -module.exports = (params: any) => new Promise(async (res, rej) => { +export default () => new Promise(async (res, rej) => { const meta: any = (await Meta.findOne()) || {}; res({ diff --git a/src/server/api/endpoints/mute/create.ts b/src/server/api/endpoints/mute/create.ts index 415745e2c3..bd70cd62ef 100644 --- a/src/server/api/endpoints/mute/create.ts +++ b/src/server/api/endpoints/mute/create.ts @@ -1,11 +1,19 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import User, { ILocalUser } from '../../../../models/user'; import Mute from '../../../../models/mute'; -/** - * Mute a user - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'ユーザーをミュートします。', + en: 'Mute a user' + }, + + requireCredential: true, + + kind: 'account/write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const muter = user; // Get 'userId' parameter diff --git a/src/server/api/endpoints/mute/delete.ts b/src/server/api/endpoints/mute/delete.ts index 2d1d286585..3187c46f83 100644 --- a/src/server/api/endpoints/mute/delete.ts +++ b/src/server/api/endpoints/mute/delete.ts @@ -1,11 +1,19 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import User, { ILocalUser } from '../../../../models/user'; import Mute from '../../../../models/mute'; -/** - * Unmute a user - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'ユーザーのミュートを解除します。', + en: 'Unmute a user' + }, + + requireCredential: true, + + kind: 'account/write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { const muter = user; // Get 'userId' parameter diff --git a/src/server/api/endpoints/mute/list.ts b/src/server/api/endpoints/mute/list.ts index 8b0171be33..e297605338 100644 --- a/src/server/api/endpoints/mute/list.ts +++ b/src/server/api/endpoints/mute/list.ts @@ -1,22 +1,30 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Mute from '../../../../models/mute'; import { pack, ILocalUser } from '../../../../models/user'; import { getFriendIds } from '../../common/get-friends'; -/** - * Get muted users of a user - */ -module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'ミュートしているユーザー一覧を取得します。', + en: 'Get muted users.' + }, + + requireCredential: true, + + kind: 'account/read' +}; + +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'iknow' parameter - const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow); + const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow); if (iknowErr) return rej('invalid iknow param'); // Get 'limit' parameter - const [limit = 30, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 30, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'cursor' parameter - const [cursor = null, cursorErr] = $.type(ID).optional().get(params.cursor); + const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor); if (cursorErr) return rej('invalid cursor param'); // Construct query diff --git a/src/server/api/endpoints/my/apps.ts b/src/server/api/endpoints/my/apps.ts index 7687afd0c7..35185db41d 100644 --- a/src/server/api/endpoints/my/apps.ts +++ b/src/server/api/endpoints/my/apps.ts @@ -2,16 +2,22 @@ import $ from 'cafy'; import App, { pack } from '../../../../models/app'; import { ILocalUser } from '../../../../models/user'; -/** - * Get my apps - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '自分のアプリケーション一覧を取得します。', + en: 'Get my apps' + }, + + requireCredential: true +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); const query = { diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts index 5554e53aa4..029bc1a95e 100644 --- a/src/server/api/endpoints/notes.ts +++ b/src/server/api/endpoints/notes.ts @@ -1,47 +1,47 @@ /** * Module dependencies */ -import $ from 'cafy'; import ID from '../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../misc/cafy-id'; import Note, { pack } from '../../../models/note'; /** * Get all notes */ -module.exports = (params: any) => new Promise(async (res, rej) => { +export default (params: any) => new Promise(async (res, rej) => { // Get 'local' parameter - const [local, localErr] = $.bool.optional().get(params.local); + const [local, localErr] = $.bool.optional.get(params.local); if (localErr) return rej('invalid local param'); // Get 'reply' parameter - const [reply, replyErr] = $.bool.optional().get(params.reply); + const [reply, replyErr] = $.bool.optional.get(params.reply); if (replyErr) return rej('invalid reply param'); // Get 'renote' parameter - const [renote, renoteErr] = $.bool.optional().get(params.renote); + const [renote, renoteErr] = $.bool.optional.get(params.renote); if (renoteErr) return rej('invalid renote param'); // Get 'media' parameter - const [media, mediaErr] = $.bool.optional().get(params.media); + const [media, mediaErr] = $.bool.optional.get(params.media); if (mediaErr) return rej('invalid media param'); // Get 'poll' parameter - const [poll, pollErr] = $.bool.optional().get(params.poll); + const [poll, pollErr] = $.bool.optional.get(params.poll); if (pollErr) return rej('invalid poll param'); // Get 'bot' parameter - //const [bot, botErr] = $.bool.optional().get(params.bot); + //const [bot, botErr] = $.bool.optional.get(params.bot); //if (botErr) return rej('invalid bot param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Check if both of sinceId and untilId is specified diff --git a/src/server/api/endpoints/notes/conversation.ts b/src/server/api/endpoints/notes/conversation.ts index b2bc6a2e72..2782d14155 100644 --- a/src/server/api/endpoints/notes/conversation.ts +++ b/src/server/api/endpoints/notes/conversation.ts @@ -1,21 +1,21 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note, { pack, INote } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; /** * Show conversation of a note */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // Lookup note diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts index 64f3b5ce26..66d018618c 100644 --- a/src/server/api/endpoints/notes/create.ts +++ b/src/server/api/endpoints/notes/create.ts @@ -1,68 +1,135 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +const ms = require('ms'); import Note, { INote, isValidText, isValidCw, pack } from '../../../../models/note'; import User, { ILocalUser, IUser } from '../../../../models/user'; -import DriveFile from '../../../../models/drive-file'; +import DriveFile, { IDriveFile } from '../../../../models/drive-file'; import create from '../../../../services/note/create'; import { IApp } from '../../../../models/app'; +import getParams from '../../get-params'; + +export const meta = { + desc: { + ja: '投稿します。' + }, + + requireCredential: true, + + limit: { + duration: ms('1hour'), + max: 300, + minInterval: ms('1second') + }, + + kind: 'note-write', + + params: { + visibility: $.str.optional.or(['public', 'home', 'followers', 'specified', 'private']).note({ + default: 'public', + desc: { + ja: '投稿の公開範囲' + } + }), + + visibleUserIds: $.arr($.type(ID)).optional.unique().min(1).note({ + desc: { + ja: '(投稿の公開範囲が specified の場合)投稿を閲覧できるユーザー' + } + }), + + text: $.str.optional.nullable.pipe(isValidText).note({ + default: null, + desc: { + ja: '投稿内容' + } + }), + + cw: $.str.optional.nullable.pipe(isValidCw).note({ + desc: { + ja: 'コンテンツの警告。このパラメータを指定すると設定したテキストで投稿のコンテンツを隠す事が出来ます。' + } + }), + + viaMobile: $.bool.optional.note({ + default: false, + desc: { + ja: 'モバイルデバイスからの投稿か否か。' + } + }), + + geo: $.obj({ + coordinates: $.arr().length(2) + .item(0, $.num.range(-180, 180)) + .item(1, $.num.range(-90, 90)), + altitude: $.num.nullable, + accuracy: $.num.nullable, + altitudeAccuracy: $.num.nullable, + heading: $.num.nullable.range(0, 360), + speed: $.num.nullable + }).optional.nullable.strict().note({ + desc: { + ja: '位置情報' + }, + ref: 'geo' + }), + + mediaIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({ + desc: { + ja: '添付するメディア' + } + }), + + renoteId: $.type(ID).optional.note({ + desc: { + ja: 'Renote対象' + } + }), + + poll: $.obj({ + choices: $.arr($.str) + .unique() + .range(2, 10) + .each(c => c.length > 0 && c.length < 50) + }).optional.strict().note({ + desc: { + ja: 'アンケート' + }, + ref: 'poll' + }) + }, + + res: { + type: 'object', + props: { + createdNote: { + type: 'entity(Note)', + desc: { + ja: '作成した投稿' + } + } + } + } +}; /** * Create a note */ -module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { - // Get 'visibility' parameter - const [visibility = 'public', visibilityErr] = $.str.optional().or(['public', 'home', 'followers', 'specified', 'private']).get(params.visibility); - if (visibilityErr) return rej('invalid visibility'); - - // Get 'visibleUserIds' parameter - const [visibleUserIds, visibleUserIdsErr] = $.arr($.type(ID)).optional().unique().min(1).get(params.visibleUserIds); - if (visibleUserIdsErr) return rej('invalid visibleUserIds'); +export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) return rej(psErr); let visibleUsers: IUser[] = []; - if (visibleUserIds !== undefined) { - visibleUsers = await Promise.all(visibleUserIds.map(id => User.findOne({ + if (ps.visibleUserIds !== undefined) { + visibleUsers = await Promise.all(ps.visibleUserIds.map(id => User.findOne({ _id: id }))); } - // Get 'text' parameter - const [text = null, textErr] = $.str.optional().nullable().pipe(isValidText).get(params.text); - if (textErr) return rej('invalid text'); - - // Get 'cw' parameter - const [cw, cwErr] = $.str.optional().nullable().pipe(isValidCw).get(params.cw); - if (cwErr) return rej('invalid cw'); - - // Get 'viaMobile' parameter - const [viaMobile = false, viaMobileErr] = $.bool.optional().get(params.viaMobile); - if (viaMobileErr) return rej('invalid viaMobile'); - - // Get 'tags' parameter - const [tags = [], tagsErr] = $.arr($.str.range(1, 32)).optional().unique().get(params.tags); - if (tagsErr) return rej('invalid tags'); - - // Get 'geo' parameter - const [geo, geoErr] = $.obj.optional().nullable().strict() - .have('coordinates', $.arr().length(2) - .item(0, $.num.range(-180, 180)) - .item(1, $.num.range(-90, 90))) - .have('altitude', $.num.nullable()) - .have('accuracy', $.num.nullable()) - .have('altitudeAccuracy', $.num.nullable()) - .have('heading', $.num.nullable().range(0, 360)) - .have('speed', $.num.nullable()) - .get(params.geo); - if (geoErr) return rej('invalid geo'); - - // Get 'mediaIds' parameter - const [mediaIds, mediaIdsErr] = $.arr($.type(ID)).optional().unique().range(1, 4).get(params.mediaIds); - if (mediaIdsErr) return rej('invalid mediaIds'); - - let files = []; - if (mediaIds !== undefined) { + let files: IDriveFile[] = []; + if (ps.mediaIds !== undefined) { // Fetch files // forEach だと途中でエラーなどがあっても return できないので // 敢えて for を使っています。 - for (const mediaId of mediaIds) { + for (const mediaId of ps.mediaIds) { // Fetch file // SELECT _id const entity = await DriveFile.findOne({ @@ -80,15 +147,11 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async files = null; } - // Get 'renoteId' parameter - const [renoteId, renoteIdErr] = $.type(ID).optional().get(params.renoteId); - if (renoteIdErr) return rej('invalid renoteId'); - let renote: INote = null; - if (renoteId !== undefined) { + if (ps.renoteId !== undefined) { // Fetch renote to note renote = await Note.findOne({ - _id: renoteId + _id: ps.renoteId }); if (renote == null) { @@ -99,7 +162,7 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async } // Get 'replyId' parameter - const [replyId, replyIdErr] = $.type(ID).optional().get(params.replyId); + const [replyId, replyIdErr] = $.type(ID).optional.get(params.replyId); if (replyIdErr) return rej('invalid replyId'); let reply: INote = null; @@ -119,17 +182,8 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async } } - // Get 'poll' parameter - const [poll, pollErr] = $.obj.optional().strict() - .have('choices', $.arr($.str) - .unique() - .range(2, 10) - .each(c => c.length > 0 && c.length < 50)) - .get(params.poll); - if (pollErr) return rej('invalid poll'); - - if (poll) { - (poll as any).choices = (poll as any).choices.map((choice: string, i: number) => ({ + if (ps.poll) { + (ps.poll as any).choices = (ps.poll as any).choices.map((choice: string, i: number) => ({ id: i, // IDを付与 text: choice.trim(), votes: 0 @@ -137,7 +191,7 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async } // テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー - if ((text === undefined || text === null) && files === null && renote === null && poll === undefined) { + if ((ps.text === undefined || ps.text === null) && files === null && renote === null && ps.poll === undefined) { return rej('text, mediaIds, renoteId or poll is required'); } @@ -145,17 +199,16 @@ module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async const note = await create(user, { createdAt: new Date(), media: files, - poll, - text, + poll: ps.poll, + text: ps.text, reply, renote, - cw, - tags, + cw: ps.cw, app, - viaMobile, - visibility, + viaMobile: ps.viaMobile, + visibility: ps.visibility, visibleUsers, - geo + geo: ps.geo }); const noteObj = await pack(note, user); diff --git a/src/server/api/endpoints/notes/delete.ts b/src/server/api/endpoints/notes/delete.ts index 70bcdbaab9..22c6101e14 100644 --- a/src/server/api/endpoints/notes/delete.ts +++ b/src/server/api/endpoints/notes/delete.ts @@ -1,12 +1,20 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import deleteNote from '../../../../services/note/delete'; import { ILocalUser } from '../../../../models/user'; -/** - * Delete a note - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定した投稿を削除します。', + en: 'Delete a note.' + }, + + requireCredential: true, + + kind: 'note-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/favorites/create.ts b/src/server/api/endpoints/notes/favorites/create.ts index 23f7ac5f8d..87f6cf1f08 100644 --- a/src/server/api/endpoints/notes/favorites/create.ts +++ b/src/server/api/endpoints/notes/favorites/create.ts @@ -1,12 +1,20 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import Favorite from '../../../../../models/favorite'; import Note from '../../../../../models/note'; import { ILocalUser } from '../../../../../models/user'; -/** - * Favorite a note - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定した投稿をお気に入りに登録します。', + en: 'Favorite a note.' + }, + + requireCredential: true, + + kind: 'favorite-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/favorites/delete.ts b/src/server/api/endpoints/notes/favorites/delete.ts index 7d2d2b4cb5..3906fe99bb 100644 --- a/src/server/api/endpoints/notes/favorites/delete.ts +++ b/src/server/api/endpoints/notes/favorites/delete.ts @@ -1,12 +1,20 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import Favorite from '../../../../../models/favorite'; import Note from '../../../../../models/note'; import { ILocalUser } from '../../../../../models/user'; -/** - * Unfavorite a note - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定した投稿のお気に入りを解除します。', + en: 'Unfavorite a note.' + }, + + requireCredential: true, + + kind: 'favorite-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts index 24ffdbcba7..8f7233e308 100644 --- a/src/server/api/endpoints/notes/global-timeline.ts +++ b/src/server/api/endpoints/notes/global-timeline.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/note'; @@ -7,25 +7,25 @@ import { ILocalUser } from '../../../../models/user'; /** * Get timeline of global */ -module.exports = async (params: any, user: ILocalUser) => { +export default async (params: any, user: ILocalUser) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) throw 'invalid limit param'; // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) throw 'invalid sinceId param'; // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) throw 'invalid untilId param'; // Get 'sinceDate' parameter - const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate); + const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate); if (sinceDateErr) throw 'invalid sinceDate param'; // Get 'untilDate' parameter - const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate); + const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate); if (untilDateErr) throw 'invalid untilDate param'; // Check if only one of sinceId, untilId, sinceDate, untilDate specified @@ -34,7 +34,7 @@ module.exports = async (params: any, user: ILocalUser) => { } // Get 'mediaOnly' parameter - const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); + const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly); if (mediaOnlyErr) throw 'invalid mediaOnly param'; // ミュートしているユーザーを取得 @@ -49,7 +49,9 @@ module.exports = async (params: any, user: ILocalUser) => { const query = { // public only - visibility: 'public' + visibility: 'public', + + replyId: null } as any; if (mutedUserIds && mutedUserIds.length > 0) { diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts new file mode 100644 index 0000000000..036f84b54b --- /dev/null +++ b/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -0,0 +1,219 @@ +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import Note from '../../../../models/note'; +import Mute from '../../../../models/mute'; +import { getFriends } from '../../common/get-friends'; +import { pack } from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; +import getParams from '../../get-params'; + +export const meta = { + name: 'notes/hybrid-timeline', + + desc: { + ja: 'ハイブリッドタイムラインを取得します。' + }, + + params: { + limit: $.num.optional.range(1, 100).note({ + default: 10, + desc: { + ja: '最大数' + } + }), + + sinceId: $.type(ID).optional.note({ + desc: { + ja: '指定すると、この投稿を基点としてより新しい投稿を取得します' + } + }), + + untilId: $.type(ID).optional.note({ + desc: { + ja: '指定すると、この投稿を基点としてより古い投稿を取得します' + } + }), + + sinceDate: $.num.optional.note({ + desc: { + ja: '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' + } + }), + + untilDate: $.num.optional.note({ + desc: { + ja: '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' + } + }), + + includeMyRenotes: $.bool.optional.note({ + default: true, + desc: { + ja: '自分の行ったRenoteを含めるかどうか' + } + }), + + includeRenotedMyNotes: $.bool.optional.note({ + default: true, + desc: { + ja: 'Renoteされた自分の投稿を含めるかどうか' + } + }), + + mediaOnly: $.bool.optional.note({ + desc: { + ja: 'true にすると、メディアが添付された投稿だけ取得します' + } + }), + } +}; + +/** + * Get hybrid timeline of myself + */ +export default async (params: any, user: ILocalUser) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) throw psErr; + + // Check if only one of sinceId, untilId, sinceDate, untilDate specified + if ([ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate].filter(x => x != null).length > 1) { + throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; + } + + const [followings, mutedUserIds] = await Promise.all([ + // フォローを取得 + // Fetch following + getFriends(user._id, true, false), + + // ミュートしているユーザーを取得 + Mute.find({ + muterId: user._id + }).then(ms => ms.map(m => m.muteeId)) + ]); + + //#region Construct query + const sort = { + _id: -1 + }; + + const followQuery = followings.map(f => f.stalk ? { + userId: f.id + } : { + userId: f.id, + + // ストーキングしてないならリプライは含めない(ただし投稿者自身の投稿へのリプライ、自分の投稿へのリプライ、自分のリプライは含める) + $or: [{ + // リプライでない + replyId: null + }, { // または + // リプライだが返信先が投稿者自身の投稿 + $expr: { + $eq: ['$_reply.userId', '$userId'] + } + }, { // または + // リプライだが返信先が自分(フォロワー)の投稿 + '_reply.userId': user._id + }, { // または + // 自分(フォロワー)が送信したリプライ + userId: user._id + }] + }); + + const query = { + $and: [{ + $or: [{ + // フォローしている人の投稿 + $or: followQuery + }, { + // public only + visibility: 'public', + + // local + '_user.host': null + }], + + // mute + userId: { + $nin: mutedUserIds + }, + '_reply.userId': { + $nin: mutedUserIds + }, + '_renote.userId': { + $nin: mutedUserIds + }, + }] + } as any; + + // MongoDBではトップレベルで否定ができないため、De Morganの法則を利用してクエリします。 + // つまり、「『自分の投稿かつRenote』ではない」を「『自分の投稿ではない』または『Renoteではない』」と表現します。 + // for details: https://en.wikipedia.org/wiki/De_Morgan%27s_laws + + if (ps.includeMyRenotes === false) { + query.$and.push({ + $or: [{ + userId: { $ne: user._id } + }, { + renoteId: null + }, { + text: { $ne: null } + }, { + mediaIds: { $ne: [] } + }, { + poll: { $ne: null } + }] + }); + } + + if (ps.includeRenotedMyNotes === false) { + query.$and.push({ + $or: [{ + '_renote.userId': { $ne: user._id } + }, { + renoteId: null + }, { + text: { $ne: null } + }, { + mediaIds: { $ne: [] } + }, { + poll: { $ne: null } + }] + }); + } + + if (ps.mediaOnly) { + query.$and.push({ + mediaIds: { $exists: true, $ne: [] } + }); + } + + if (ps.sinceId) { + sort._id = 1; + query._id = { + $gt: ps.sinceId + }; + } else if (ps.untilId) { + query._id = { + $lt: ps.untilId + }; + } else if (ps.sinceDate) { + sort._id = 1; + query.createdAt = { + $gt: new Date(ps.sinceDate) + }; + } else if (ps.untilDate) { + query.createdAt = { + $lt: new Date(ps.untilDate) + }; + } + //#endregion + + // Issue query + const timeline = await Note + .find(query, { + limit: ps.limit, + sort: sort + }); + + // Serialize + return await Promise.all(timeline.map(note => pack(note, user))); +}; diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts index 48490638d2..bbcc6303ca 100644 --- a/src/server/api/endpoints/notes/local-timeline.ts +++ b/src/server/api/endpoints/notes/local-timeline.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/note'; @@ -7,25 +7,25 @@ import { ILocalUser } from '../../../../models/user'; /** * Get timeline of local */ -module.exports = async (params: any, user: ILocalUser) => { +export default async (params: any, user: ILocalUser) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) throw 'invalid limit param'; // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) throw 'invalid sinceId param'; // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) throw 'invalid untilId param'; // Get 'sinceDate' parameter - const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate); + const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate); if (sinceDateErr) throw 'invalid sinceDate param'; // Get 'untilDate' parameter - const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate); + const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate); if (untilDateErr) throw 'invalid untilDate param'; // Check if only one of sinceId, untilId, sinceDate, untilDate specified @@ -34,7 +34,7 @@ module.exports = async (params: any, user: ILocalUser) => { } // Get 'mediaOnly' parameter - const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); + const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly); if (mediaOnlyErr) throw 'invalid mediaOnly param'; // ミュートしているユーザーを取得 diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts index 45511603af..db91230a81 100644 --- a/src/server/api/endpoints/notes/mentions.ts +++ b/src/server/api/endpoints/notes/mentions.ts @@ -1,28 +1,34 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import { getFriendIds } from '../../common/get-friends'; import { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; -/** - * Get mentions of myself - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '自分に言及している投稿の一覧を取得します。', + en: 'Get mentions of myself.' + }, + + requireCredential: true +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'following' parameter const [following = false, followingError] = - $.bool.optional().get(params.following); + $.bool.optional.get(params.following); if (followingError) return rej('invalid following param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Check if both of sinceId and untilId is specified diff --git a/src/server/api/endpoints/notes/polls/recommendation.ts b/src/server/api/endpoints/notes/polls/recommendation.ts index 640140c3d1..a0469d1870 100644 --- a/src/server/api/endpoints/notes/polls/recommendation.ts +++ b/src/server/api/endpoints/notes/polls/recommendation.ts @@ -3,16 +3,22 @@ import Vote from '../../../../../models/poll-vote'; import Note, { pack } from '../../../../../models/note'; import { ILocalUser } from '../../../../../models/user'; -/** - * Get recommended polls - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'おすすめのアンケート一覧を取得します。', + en: 'Get recommended polls.' + }, + + requireCredential: true, +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // Get votes diff --git a/src/server/api/endpoints/notes/polls/vote.ts b/src/server/api/endpoints/notes/polls/vote.ts index 72ac6bb202..568c187f8a 100644 --- a/src/server/api/endpoints/notes/polls/vote.ts +++ b/src/server/api/endpoints/notes/polls/vote.ts @@ -1,16 +1,24 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import Vote from '../../../../../models/poll-vote'; import Note from '../../../../../models/note'; import Watching from '../../../../../models/note-watching'; import watch from '../../../../../services/note/watch'; -import { publishNoteStream } from '../../../../../publishers/stream'; -import notify from '../../../../../publishers/notify'; +import { publishNoteStream } from '../../../../../stream'; +import notify from '../../../../../notify'; import { ILocalUser } from '../../../../../models/user'; -/** - * Vote poll of a note - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定した投稿のアンケートに投票します。', + en: 'Vote poll of a note.' + }, + + requireCredential: true, + + kind: 'vote-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/reactions.ts b/src/server/api/endpoints/notes/reactions.ts index d3b2d43432..8921c55916 100644 --- a/src/server/api/endpoints/notes/reactions.ts +++ b/src/server/api/endpoints/notes/reactions.ts @@ -1,26 +1,32 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import Reaction, { pack } from '../../../../models/note-reaction'; import { ILocalUser } from '../../../../models/user'; -/** - * Show reactions of a note - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定した投稿のリアクション一覧を取得します。', + en: 'Show reactions of a note.' + }, + + requireCredential: true +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // Get 'sort' parameter - const [sort = 'desc', sortError] = $.str.optional().or('desc asc').get(params.sort); + const [sort = 'desc', sortError] = $.str.optional.or('desc asc').get(params.sort); if (sortError) return rej('invalid sort param'); // Lookup note @@ -46,6 +52,5 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) }); // Serialize - res(await Promise.all(reactions.map(async reaction => - await pack(reaction, user)))); + res(await Promise.all(reactions.map(reaction => pack(reaction, user)))); }); diff --git a/src/server/api/endpoints/notes/reactions/create.ts b/src/server/api/endpoints/notes/reactions/create.ts index 33e457e308..65e24e7c06 100644 --- a/src/server/api/endpoints/notes/reactions/create.ts +++ b/src/server/api/endpoints/notes/reactions/create.ts @@ -1,24 +1,42 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import Note from '../../../../../models/note'; import create from '../../../../../services/note/reaction/create'; import { validateReaction } from '../../../../../models/note-reaction'; import { ILocalUser } from '../../../../../models/user'; +import getParams from '../../../get-params'; -/** - * React to a note - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { - // Get 'noteId' parameter - const [noteId, noteIdErr] = $.type(ID).get(params.noteId); - if (noteIdErr) return rej('invalid noteId param'); +export const meta = { + desc: { + ja: '指定した投稿にリアクションします。', + en: 'React to a note.' + }, - // Get 'reaction' parameter - const [reaction, reactionErr] = $.str.pipe(validateReaction.ok).get(params.reaction); - if (reactionErr) return rej('invalid reaction param'); + requireCredential: true, + + kind: 'reaction-write', + + params: { + noteId: $.type(ID).note({ + desc: { + ja: '対象の投稿' + } + }), + + reaction: $.str.pipe(validateReaction.ok).note({ + desc: { + ja: 'リアクションの種類' + } + }) + } +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) return rej(psErr); // Fetch reactee const note = await Note.findOne({ - _id: noteId + _id: ps.noteId }); if (note === null) { @@ -26,7 +44,7 @@ module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) } try { - await create(user, note, reaction); + await create(user, note, ps.reaction); } catch (e) { rej(e); } diff --git a/src/server/api/endpoints/notes/reactions/delete.ts b/src/server/api/endpoints/notes/reactions/delete.ts index 1f2d662511..62af0407bc 100644 --- a/src/server/api/endpoints/notes/reactions/delete.ts +++ b/src/server/api/endpoints/notes/reactions/delete.ts @@ -1,12 +1,20 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import Reaction from '../../../../../models/note-reaction'; import Note from '../../../../../models/note'; import { ILocalUser } from '../../../../../models/user'; -/** - * Unreact to a note - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定した投稿へのリアクションを取り消します。', + en: 'Unreact to a note.' + }, + + requireCredential: true, + + kind: 'reaction-write' +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts index 4aaf1d322b..44c80afc4a 100644 --- a/src/server/api/endpoints/notes/replies.ts +++ b/src/server/api/endpoints/notes/replies.ts @@ -1,21 +1,21 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note, { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; /** * Get replies of a note */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // Lookup note diff --git a/src/server/api/endpoints/notes/reposts.ts b/src/server/api/endpoints/notes/reposts.ts index ea3f174e1a..05e68302ba 100644 --- a/src/server/api/endpoints/notes/reposts.ts +++ b/src/server/api/endpoints/notes/reposts.ts @@ -1,25 +1,25 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note, { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; /** * Show a renotes of a note */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Check if both of sinceId and untilId is specified diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts new file mode 100644 index 0000000000..9124899ad8 --- /dev/null +++ b/src/server/api/endpoints/notes/search.ts @@ -0,0 +1,65 @@ +import $ from 'cafy'; +import * as mongo from 'mongodb'; +import Note from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; +import { pack } from '../../../../models/note'; +import es from '../../../../db/elasticsearch'; + +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { + // Get 'query' parameter + const [query, queryError] = $.str.get(params.query); + if (queryError) return rej('invalid query param'); + + // Get 'offset' parameter + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); + if (offsetErr) return rej('invalid offset param'); + + // Get 'limit' parameter + const [limit = 10, limitErr] = $.num.optional.range(1, 30).get(params.limit); + if (limitErr) return rej('invalid limit param'); + + if (es == null) return rej('searching not available'); + + es.search({ + index: 'misskey', + type: 'note', + body: { + size: limit, + from: offset, + query: { + simple_query_string: { + fields: ['text'], + query: query, + default_operator: 'and' + } + }, + sort: [ + { _doc: 'desc' } + ] + } + }, async (error, response) => { + if (error) { + console.error(error); + return res(500); + } + + if (response.hits.total === 0) { + return res([]); + } + + const hits = response.hits.hits.map(hit => new mongo.ObjectID(hit._id)); + + // Fetch found notes + const notes = await Note.find({ + _id: { + $in: hits + } + }, { + sort: { + _id: -1 + } + }); + + res(await Promise.all(notes.map(note => pack(note, me)))); + }); +}); diff --git a/src/server/api/endpoints/notes/search_by_tag.ts b/src/server/api/endpoints/notes/search_by_tag.ts index 9be7cfffb6..e092275fe8 100644 --- a/src/server/api/endpoints/notes/search_by_tag.ts +++ b/src/server/api/endpoints/notes/search_by_tag.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import User, { ILocalUser } from '../../../../models/user'; import Mute from '../../../../models/mute'; @@ -8,65 +8,65 @@ import { pack } from '../../../../models/note'; /** * Search notes by tag */ -module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'tag' parameter const [tag, tagError] = $.str.get(params.tag); if (tagError) return rej('invalid tag param'); // Get 'includeUserIds' parameter - const [includeUserIds = [], includeUserIdsErr] = $.arr($.type(ID)).optional().get(params.includeUserIds); + const [includeUserIds = [], includeUserIdsErr] = $.arr($.type(ID)).optional.get(params.includeUserIds); if (includeUserIdsErr) return rej('invalid includeUserIds param'); // Get 'excludeUserIds' parameter - const [excludeUserIds = [], excludeUserIdsErr] = $.arr($.type(ID)).optional().get(params.excludeUserIds); + const [excludeUserIds = [], excludeUserIdsErr] = $.arr($.type(ID)).optional.get(params.excludeUserIds); if (excludeUserIdsErr) return rej('invalid excludeUserIds param'); // Get 'includeUserUsernames' parameter - const [includeUserUsernames = [], includeUserUsernamesErr] = $.arr($.str).optional().get(params.includeUserUsernames); + const [includeUserUsernames = [], includeUserUsernamesErr] = $.arr($.str).optional.get(params.includeUserUsernames); if (includeUserUsernamesErr) return rej('invalid includeUserUsernames param'); // Get 'excludeUserUsernames' parameter - const [excludeUserUsernames = [], excludeUserUsernamesErr] = $.arr($.str).optional().get(params.excludeUserUsernames); + const [excludeUserUsernames = [], excludeUserUsernamesErr] = $.arr($.str).optional.get(params.excludeUserUsernames); if (excludeUserUsernamesErr) return rej('invalid excludeUserUsernames param'); // Get 'following' parameter - const [following = null, followingErr] = $.bool.optional().nullable().get(params.following); + const [following = null, followingErr] = $.bool.optional.nullable.get(params.following); if (followingErr) return rej('invalid following param'); // Get 'mute' parameter - const [mute = 'mute_all', muteErr] = $.str.optional().get(params.mute); + const [mute = 'mute_all', muteErr] = $.str.optional.get(params.mute); if (muteErr) return rej('invalid mute param'); // Get 'reply' parameter - const [reply = null, replyErr] = $.bool.optional().nullable().get(params.reply); + const [reply = null, replyErr] = $.bool.optional.nullable.get(params.reply); if (replyErr) return rej('invalid reply param'); // Get 'renote' parameter - const [renote = null, renoteErr] = $.bool.optional().nullable().get(params.renote); + const [renote = null, renoteErr] = $.bool.optional.nullable.get(params.renote); if (renoteErr) return rej('invalid renote param'); // Get 'media' parameter - const [media = null, mediaErr] = $.bool.optional().nullable().get(params.media); + const [media = null, mediaErr] = $.bool.optional.nullable.get(params.media); if (mediaErr) return rej('invalid media param'); // Get 'poll' parameter - const [poll = null, pollErr] = $.bool.optional().nullable().get(params.poll); + const [poll = null, pollErr] = $.bool.optional.nullable.get(params.poll); if (pollErr) return rej('invalid poll param'); // Get 'sinceDate' parameter - const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate); + const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate); if (sinceDateErr) throw 'invalid sinceDate param'; // Get 'untilDate' parameter - const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate); + const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate); if (untilDateErr) throw 'invalid untilDate param'; // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 30).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 30).get(params.limit); if (limitErr) return rej('invalid limit param'); if (includeUserUsernames != null) { diff --git a/src/server/api/endpoints/notes/show.ts b/src/server/api/endpoints/notes/show.ts index 1ba7145996..3f94eeede5 100644 --- a/src/server/api/endpoints/notes/show.ts +++ b/src/server/api/endpoints/notes/show.ts @@ -1,11 +1,11 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note, { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; /** * Show a note */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'noteId' parameter const [noteId, noteIdErr] = $.type(ID).get(params.noteId); if (noteIdErr) return rej('invalid noteId param'); diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts index 18c0acd379..faa8ccf3ca 100644 --- a/src/server/api/endpoints/notes/timeline.ts +++ b/src/server/api/endpoints/notes/timeline.ts @@ -1,51 +1,84 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { getFriends } from '../../common/get-friends'; import { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; +import getParams from '../../get-params'; + +export const meta = { + desc: { + ja: 'タイムラインを取得します。' + }, + + requireCredential: true, + + params: { + limit: $.num.optional.range(1, 100).note({ + default: 10, + desc: { + ja: '最大数' + } + }), + + sinceId: $.type(ID).optional.note({ + desc: { + ja: '指定すると、この投稿を基点としてより新しい投稿を取得します' + } + }), + + untilId: $.type(ID).optional.note({ + desc: { + ja: '指定すると、この投稿を基点としてより古い投稿を取得します' + } + }), + + sinceDate: $.num.optional.note({ + desc: { + ja: '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' + } + }), + + untilDate: $.num.optional.note({ + desc: { + ja: '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' + } + }), + + includeMyRenotes: $.bool.optional.note({ + default: true, + desc: { + ja: '自分の行ったRenoteを含めるかどうか' + } + }), + + includeRenotedMyNotes: $.bool.optional.note({ + default: true, + desc: { + ja: 'Renoteされた自分の投稿を含めるかどうか' + } + }), + + mediaOnly: $.bool.optional.note({ + desc: { + ja: 'true にすると、メディアが添付された投稿だけ取得します' + } + }), + } +}; /** * Get timeline of myself */ -module.exports = async (params: any, user: ILocalUser) => { - // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); - if (limitErr) throw 'invalid limit param'; - - // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); - if (sinceIdErr) throw 'invalid sinceId param'; - - // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); - if (untilIdErr) throw 'invalid untilId param'; - - // Get 'sinceDate' parameter - const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate); - if (sinceDateErr) throw 'invalid sinceDate param'; - - // Get 'untilDate' parameter - const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate); - if (untilDateErr) throw 'invalid untilDate param'; +export default async (params: any, user: ILocalUser) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) throw psErr; // Check if only one of sinceId, untilId, sinceDate, untilDate specified - if ([sinceId, untilId, sinceDate, untilDate].filter(x => x != null).length > 1) { + if ([ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate].filter(x => x != null).length > 1) { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } - // Get 'includeMyRenotes' parameter - const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional().get(params.includeMyRenotes); - if (includeMyRenotesErr) throw 'invalid includeMyRenotes param'; - - // Get 'includeRenotedMyNotes' parameter - const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional().get(params.includeRenotedMyNotes); - if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param'; - - // Get 'mediaOnly' parameter - const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); - if (mediaOnlyErr) throw 'invalid mediaOnly param'; - const [followings, mutedUserIds] = await Promise.all([ // フォローを取得 // Fetch following @@ -107,7 +140,7 @@ module.exports = async (params: any, user: ILocalUser) => { // つまり、「『自分の投稿かつRenote』ではない」を「『自分の投稿ではない』または『Renoteではない』」と表現します。 // for details: https://en.wikipedia.org/wiki/De_Morgan%27s_laws - if (includeMyRenotes === false) { + if (ps.includeMyRenotes === false) { query.$and.push({ $or: [{ userId: { $ne: user._id } @@ -123,7 +156,7 @@ module.exports = async (params: any, user: ILocalUser) => { }); } - if (includeRenotedMyNotes === false) { + if (ps.includeRenotedMyNotes === false) { query.$and.push({ $or: [{ '_renote.userId': { $ne: user._id } @@ -139,29 +172,29 @@ module.exports = async (params: any, user: ILocalUser) => { }); } - if (mediaOnly) { + if (ps.mediaOnly) { query.$and.push({ mediaIds: { $exists: true, $ne: [] } }); } - if (sinceId) { + if (ps.sinceId) { sort._id = 1; query._id = { - $gt: sinceId + $gt: ps.sinceId }; - } else if (untilId) { + } else if (ps.untilId) { query._id = { - $lt: untilId + $lt: ps.untilId }; - } else if (sinceDate) { + } else if (ps.sinceDate) { sort._id = 1; query.createdAt = { - $gt: new Date(sinceDate) + $gt: new Date(ps.sinceDate) }; - } else if (untilDate) { + } else if (ps.untilDate) { query.createdAt = { - $lt: new Date(untilDate) + $lt: new Date(ps.untilDate) }; } //#endregion @@ -169,7 +202,7 @@ module.exports = async (params: any, user: ILocalUser) => { // Issue query const timeline = await Note .find(query, { - limit: limit, + limit: ps.limit, sort: sort }); diff --git a/src/server/api/endpoints/notes/trend.ts b/src/server/api/endpoints/notes/trend.ts index 9c0a1bb112..1cbbfacadc 100644 --- a/src/server/api/endpoints/notes/trend.ts +++ b/src/server/api/endpoints/notes/trend.ts @@ -3,32 +3,38 @@ import $ from 'cafy'; import Note, { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; -/** - * Get trend notes - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '人気の投稿の一覧を取得します。', + en: 'Get trend notes.' + }, + + requireCredential: true +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // Get 'reply' parameter - const [reply, replyErr] = $.bool.optional().get(params.reply); + const [reply, replyErr] = $.bool.optional.get(params.reply); if (replyErr) return rej('invalid reply param'); // Get 'renote' parameter - const [renote, renoteErr] = $.bool.optional().get(params.renote); + const [renote, renoteErr] = $.bool.optional.get(params.renote); if (renoteErr) return rej('invalid renote param'); // Get 'media' parameter - const [media, mediaErr] = $.bool.optional().get(params.media); + const [media, mediaErr] = $.bool.optional.get(params.media); if (mediaErr) return rej('invalid media param'); // Get 'poll' parameter - const [poll, pollErr] = $.bool.optional().get(params.poll); + const [poll, pollErr] = $.bool.optional.get(params.poll); if (pollErr) return rej('invalid poll param'); const query = { diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts index 8aa800b712..5837a9a301 100644 --- a/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/src/server/api/endpoints/notes/user-list-timeline.ts @@ -1,32 +1,38 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/note'; import UserList from '../../../../models/user-list'; import { ILocalUser } from '../../../../models/user'; -/** - * Get timeline of a user list - */ -module.exports = async (params: any, user: ILocalUser) => { +export const meta = { + desc: { + ja: '指定したユーザーリストのタイムラインを取得します。', + en: 'Get timeline of a user list.' + }, + + requireCredential: true +}; + +export default async (params: any, user: ILocalUser) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) throw 'invalid limit param'; // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) throw 'invalid sinceId param'; // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) throw 'invalid untilId param'; // Get 'sinceDate' parameter - const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate); + const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate); if (sinceDateErr) throw 'invalid sinceDate param'; // Get 'untilDate' parameter - const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate); + const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate); if (untilDateErr) throw 'invalid untilDate param'; // Check if only one of sinceId, untilId, sinceDate, untilDate specified @@ -35,15 +41,15 @@ module.exports = async (params: any, user: ILocalUser) => { } // Get 'includeMyRenotes' parameter - const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional().get(params.includeMyRenotes); + const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional.get(params.includeMyRenotes); if (includeMyRenotesErr) throw 'invalid includeMyRenotes param'; // Get 'includeRenotedMyNotes' parameter - const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional().get(params.includeRenotedMyNotes); + const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional.get(params.includeRenotedMyNotes); if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param'; // Get 'mediaOnly' parameter - const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); + const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly); if (mediaOnlyErr) throw 'invalid mediaOnly param'; // Get 'listId' parameter diff --git a/src/server/api/endpoints/notifications/mark_all_as_read.ts b/src/server/api/endpoints/notifications/mark_all_as_read.ts new file mode 100644 index 0000000000..a9875ebb01 --- /dev/null +++ b/src/server/api/endpoints/notifications/mark_all_as_read.ts @@ -0,0 +1,44 @@ +import Notification from '../../../../models/notification'; +import { publishUserStream } from '../../../../stream'; +import User, { ILocalUser } from '../../../../models/user'; + +export const meta = { + desc: { + ja: '全ての通知を既読にします。', + en: 'Mark all notifications as read.' + }, + + requireCredential: true, + + kind: 'notification-write' +}; + +/** + * Mark all notifications as read + */ +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + // Update documents + await Notification.update({ + notifieeId: user._id, + isRead: false + }, { + $set: { + isRead: true + } + }, { + multi: true + }); + + // Response + res(); + + // Update flag + User.update({ _id: user._id }, { + $set: { + hasUnreadNotification: false + } + }); + + // 全ての通知を読みましたよというイベントを発行 + publishUserStream(user._id, 'read_all_notifications'); +}); diff --git a/src/server/api/endpoints/notifications/mark_as_read_all.ts b/src/server/api/endpoints/notifications/mark_as_read_all.ts deleted file mode 100644 index faaaf65a2d..0000000000 --- a/src/server/api/endpoints/notifications/mark_as_read_all.ts +++ /dev/null @@ -1,33 +0,0 @@ -import Notification from '../../../../models/notification'; -import event from '../../../../publishers/stream'; -import User, { ILocalUser } from '../../../../models/user'; - -/** - * Mark as read all notifications - */ -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { - // Update documents - await Notification.update({ - notifieeId: user._id, - isRead: false - }, { - $set: { - isRead: true - } - }, { - multi: true - }); - - // Response - res(); - - // Update flag - User.update({ _id: user._id }, { - $set: { - hasUnreadNotification: false - } - }); - - // 全ての通知を読みましたよというイベントを発行 - event(user._id, 'read_all_notifications'); -}); diff --git a/src/server/api/endpoints/reversi/invitations.ts b/src/server/api/endpoints/reversi/invitations.ts deleted file mode 100644 index d7727071ae..0000000000 --- a/src/server/api/endpoints/reversi/invitations.ts +++ /dev/null @@ -1,16 +0,0 @@ -import Matching, { pack as packMatching } from '../../../../models/reversi-matching'; -import { ILocalUser } from '../../../../models/user'; - -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { - // Find session - const invitations = await Matching.find({ - childId: user._id - }, { - sort: { - _id: -1 - } - }); - - // Reponse - res(Promise.all(invitations.map(async (i) => await packMatching(i, user)))); -}); diff --git a/src/server/api/endpoints/reversi/match/cancel.ts b/src/server/api/endpoints/reversi/match/cancel.ts deleted file mode 100644 index 1c9c799dbe..0000000000 --- a/src/server/api/endpoints/reversi/match/cancel.ts +++ /dev/null @@ -1,10 +0,0 @@ -import Matching from '../../../../../models/reversi-matching'; -import { ILocalUser } from '../../../../../models/user'; - -module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => { - await Matching.remove({ - parentId: user._id - }); - - res(); -}); diff --git a/src/server/api/endpoints/stats.ts b/src/server/api/endpoints/stats.ts index 74ab6ba945..fc195da22d 100644 --- a/src/server/api/endpoints/stats.ts +++ b/src/server/api/endpoints/stats.ts @@ -3,8 +3,8 @@ import Meta from '../../../models/meta'; /** * Get the misskey's statistics */ -module.exports = () => new Promise(async (res, rej) => { +export default () => new Promise(async (res, rej) => { const meta = await Meta.findOne(); - res(meta.stats); + res(meta ? meta.stats : {}); }); diff --git a/src/server/api/endpoints/sw/register.ts b/src/server/api/endpoints/sw/register.ts index f04a77fa4d..3414600048 100644 --- a/src/server/api/endpoints/sw/register.ts +++ b/src/server/api/endpoints/sw/register.ts @@ -2,10 +2,14 @@ import $ from 'cafy'; import Subscription from '../../../../models/sw-subscription'; import { ILocalUser } from '../../../../models/user'; +export const meta = { + requireCredential: true +}; + /** * subscribe service worker */ -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'endpoint' parameter const [endpoint, endpointErr] = $.str.get(params.endpoint); if (endpointErr) return rej('invalid endpoint param'); diff --git a/src/server/api/endpoints/username/available.ts b/src/server/api/endpoints/username/available.ts index aad3adc514..ff12b797ed 100644 --- a/src/server/api/endpoints/username/available.ts +++ b/src/server/api/endpoints/username/available.ts @@ -5,7 +5,7 @@ import { validateUsername } from '../../../../models/user'; /** * Check available username */ -module.exports = async (params: any) => new Promise(async (res, rej) => { +export default async (params: any) => new Promise(async (res, rej) => { // Get 'username' parameter const [username, usernameError] = $.str.pipe(validateUsername).get(params.username); if (usernameError) return rej('invalid username param'); diff --git a/src/server/api/endpoints/users.ts b/src/server/api/endpoints/users.ts index b8df6f3ecf..d7e85d3cbe 100644 --- a/src/server/api/endpoints/users.ts +++ b/src/server/api/endpoints/users.ts @@ -4,17 +4,17 @@ import User, { pack, ILocalUser } from '../../../models/user'; /** * Lists all users */ -module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // Get 'sort' parameter - const [sort, sortError] = $.str.optional().or('+follower|-follower').get(params.sort); + const [sort, sortError] = $.str.optional.or('+follower|-follower').get(params.sort); if (sortError) return rej('invalid sort param'); // Construct query diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts index 53133ee969..9411873573 100644 --- a/src/server/api/endpoints/users/followers.ts +++ b/src/server/api/endpoints/users/followers.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import User, { ILocalUser } from '../../../../models/user'; import Following from '../../../../models/following'; import { pack } from '../../../../models/user'; @@ -7,21 +7,21 @@ import { getFriendIds } from '../../common/get-friends'; /** * Get followers of a user */ -module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); // Get 'iknow' parameter - const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow); + const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow); if (iknowErr) return rej('invalid iknow param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'cursor' parameter - const [cursor = null, cursorErr] = $.type(ID).optional().get(params.cursor); + const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor); if (cursorErr) return rej('invalid cursor param'); // Lookup user diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts index 2061200198..7a64d15d7b 100644 --- a/src/server/api/endpoints/users/following.ts +++ b/src/server/api/endpoints/users/following.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import User, { ILocalUser } from '../../../../models/user'; import Following from '../../../../models/following'; import { pack } from '../../../../models/user'; @@ -7,21 +7,21 @@ import { getFriendIds } from '../../common/get-friends'; /** * Get following users of a user */ -module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); // Get 'iknow' parameter - const [iknow = false, iknowErr] = $.bool.optional().get(params.iknow); + const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow); if (iknowErr) return rej('invalid iknow param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'cursor' parameter - const [cursor = null, cursorErr] = $.type(ID).optional().get(params.cursor); + const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor); if (cursorErr) return rej('invalid cursor param'); // Lookup user diff --git a/src/server/api/endpoints/users/get_frequently_replied_users.ts b/src/server/api/endpoints/users/get_frequently_replied_users.ts index ba8779d334..42b6ce20d6 100644 --- a/src/server/api/endpoints/users/get_frequently_replied_users.ts +++ b/src/server/api/endpoints/users/get_frequently_replied_users.ts @@ -1,14 +1,14 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import User, { pack, ILocalUser } from '../../../../models/user'; -module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter const [userId, userIdErr] = $.type(ID).get(params.userId); if (userIdErr) return rej('invalid userId param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Lookup user diff --git a/src/server/api/endpoints/users/lists/create.ts b/src/server/api/endpoints/users/lists/create.ts index cdd1a0d813..d7dc2a5f70 100644 --- a/src/server/api/endpoints/users/lists/create.ts +++ b/src/server/api/endpoints/users/lists/create.ts @@ -2,10 +2,18 @@ import $ from 'cafy'; import UserList, { pack } from '../../../../../models/user-list'; import { ILocalUser } from '../../../../../models/user'; -/** - * Create a user list - */ -module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'ユーザーリストを作成します。', + en: 'Create a user list' + }, + + requireCredential: true, + + kind: 'account-write' +}; + +export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { // Get 'title' parameter const [title, titleErr] = $.str.range(1, 100).get(params.title); if (titleErr) return rej('invalid title param'); diff --git a/src/server/api/endpoints/users/lists/list.ts b/src/server/api/endpoints/users/lists/list.ts index bf8391d863..31fef26bdc 100644 --- a/src/server/api/endpoints/users/lists/list.ts +++ b/src/server/api/endpoints/users/lists/list.ts @@ -1,10 +1,17 @@ import UserList, { pack } from '../../../../../models/user-list'; import { ILocalUser } from '../../../../../models/user'; -/** - * Add a user to a user list - */ -module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '自分の作成したユーザーリスト一覧を取得します。' + }, + + requireCredential: true, + + kind: 'account-read' +}; + +export default async (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Fetch lists const userLists = await UserList.find({ userId: me._id, diff --git a/src/server/api/endpoints/users/lists/push.ts b/src/server/api/endpoints/users/lists/push.ts index d8a3b3c9aa..bd4e201bde 100644 --- a/src/server/api/endpoints/users/lists/push.ts +++ b/src/server/api/endpoints/users/lists/push.ts @@ -1,15 +1,26 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import UserList from '../../../../../models/user-list'; import User, { pack as packUser, isRemoteUser, getGhost, ILocalUser } from '../../../../../models/user'; -import { publishUserListStream } from '../../../../../publishers/stream'; +import { publishUserListStream } from '../../../../../stream'; import ap from '../../../../../remote/activitypub/renderer'; import renderFollow from '../../../../../remote/activitypub/renderer/follow'; import { deliver } from '../../../../../queue'; +export const meta = { + desc: { + ja: '指定したユーザーリストに指定したユーザーを追加します。', + en: 'Add a user to a user list.' + }, + + requireCredential: true, + + kind: 'account-write' +}; + /** * Add a user to a user list */ -module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export default async (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'listId' parameter const [listId, listIdErr] = $.type(ID).get(params.listId); if (listIdErr) return rej('invalid listId param'); diff --git a/src/server/api/endpoints/users/lists/show.ts b/src/server/api/endpoints/users/lists/show.ts index e4ae239613..2fd142a609 100644 --- a/src/server/api/endpoints/users/lists/show.ts +++ b/src/server/api/endpoints/users/lists/show.ts @@ -1,11 +1,19 @@ -import $ from 'cafy'; import ID from '../../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import UserList, { pack } from '../../../../../models/user-list'; import { ILocalUser } from '../../../../../models/user'; -/** - * Show a user list - */ -module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: '指定したユーザーリストの情報を取得します。', + en: 'Show a user list.' + }, + + requireCredential: true, + + kind: 'account-read' +}; + +export default async (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'listId' parameter const [listId, listIdErr] = $.type(ID).get(params.listId); if (listIdErr) return rej('invalid listId param'); diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts index 222a8d950a..c60050d3cd 100644 --- a/src/server/api/endpoints/users/notes.ts +++ b/src/server/api/endpoints/users/notes.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import getHostLower from '../../common/get-host-lower'; import Note, { pack } from '../../../../models/note'; import User, { ILocalUser } from '../../../../models/user'; @@ -6,13 +6,13 @@ import User, { ILocalUser } from '../../../../models/user'; /** * Get notes of a user */ -module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'userId' parameter - const [userId, userIdErr] = $.type(ID).optional().get(params.userId); + const [userId, userIdErr] = $.type(ID).optional.get(params.userId); if (userIdErr) return rej('invalid userId param'); // Get 'username' parameter - const [username, usernameErr] = $.str.optional().get(params.username); + const [username, usernameErr] = $.str.optional.get(params.username); if (usernameErr) return rej('invalid username param'); if (userId === undefined && username === undefined) { @@ -20,7 +20,7 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) = } // Get 'host' parameter - const [host, hostErr] = $.str.optional().get(params.host); + const [host, hostErr] = $.str.optional.get(params.host); if (hostErr) return rej('invalid host param'); if (userId === undefined && host === undefined) { @@ -28,31 +28,31 @@ module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) = } // Get 'includeReplies' parameter - const [includeReplies = true, includeRepliesErr] = $.bool.optional().get(params.includeReplies); + const [includeReplies = true, includeRepliesErr] = $.bool.optional.get(params.includeReplies); if (includeRepliesErr) return rej('invalid includeReplies param'); // Get 'withMedia' parameter - const [withMedia = false, withMediaErr] = $.bool.optional().get(params.withMedia); + const [withMedia = false, withMediaErr] = $.bool.optional.get(params.withMedia); if (withMediaErr) return rej('invalid withMedia param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional().get(params.sinceId); + const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); if (sinceIdErr) return rej('invalid sinceId param'); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional().get(params.untilId); + const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); if (untilIdErr) return rej('invalid untilId param'); // Get 'sinceDate' parameter - const [sinceDate, sinceDateErr] = $.num.optional().get(params.sinceDate); + const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate); if (sinceDateErr) throw 'invalid sinceDate param'; // Get 'untilDate' parameter - const [untilDate, untilDateErr] = $.num.optional().get(params.untilDate); + const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate); if (untilDateErr) throw 'invalid untilDate param'; // Check if only one of sinceId, untilId, sinceDate, untilDate specified diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts index 1d0d889f11..13377e6fff 100644 --- a/src/server/api/endpoints/users/recommendation.ts +++ b/src/server/api/endpoints/users/recommendation.ts @@ -4,16 +4,23 @@ import User, { pack, ILocalUser } from '../../../../models/user'; import { getFriendIds } from '../../common/get-friends'; import Mute from '../../../../models/mute'; -/** - * Get recommended users - */ -module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export const meta = { + desc: { + ja: 'おすすめのユーザー一覧を取得します。' + }, + + requireCredential: true, + + kind: 'account-read' +}; + +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // ID list of the user itself and other users who the user follows diff --git a/src/server/api/endpoints/users/search.ts b/src/server/api/endpoints/users/search.ts index e29c8d32f1..d443d35b47 100644 --- a/src/server/api/endpoints/users/search.ts +++ b/src/server/api/endpoints/users/search.ts @@ -5,13 +5,13 @@ const escapeRegexp = require('escape-regexp'); /** * Search a user */ -module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'query' parameter const [query, queryError] = $.str.pipe(x => x != '').get(params.query); if (queryError) return rej('invalid query param'); // Get 'max' parameter - const [max = 10, maxErr] = $.num.optional().range(1, 30).get(params.max); + const [max = 10, maxErr] = $.num.optional.range(1, 30).get(params.max); if (maxErr) return rej('invalid max param'); const escapedQuery = escapeRegexp(query); diff --git a/src/server/api/endpoints/users/search_by_username.ts b/src/server/api/endpoints/users/search_by_username.ts index 937f9af589..bfab378389 100644 --- a/src/server/api/endpoints/users/search_by_username.ts +++ b/src/server/api/endpoints/users/search_by_username.ts @@ -1,41 +1,68 @@ import $ from 'cafy'; import User, { pack, ILocalUser } from '../../../../models/user'; +const escapeRegexp = require('escape-regexp'); /** * Search a user by username */ -module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { // Get 'query' parameter const [query, queryError] = $.str.get(params.query); if (queryError) return rej('invalid query param'); // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional().min(0).get(params.offset); + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); if (offsetErr) return rej('invalid offset param'); // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional().range(1, 100).get(params.limit); + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (limitErr) return rej('invalid limit param'); let users = await User .find({ host: null, - usernameLower: new RegExp(query.toLowerCase()) + usernameLower: new RegExp('^' + escapeRegexp(query.toLowerCase())) }, { limit: limit, skip: offset }); if (users.length < limit) { - const remoteUsers = await User + const otherUsers = await User .find({ host: { $ne: null }, - usernameLower: new RegExp(query.toLowerCase()) + usernameLower: new RegExp('^' + escapeRegexp(query.toLowerCase())) }, { limit: limit - users.length }); - users = users.concat(remoteUsers); + users = users.concat(otherUsers); + } + + if (users.length < limit) { + const otherUsers = await User + .find({ + _id: { $nin: users.map(u => u._id) }, + host: null, + usernameLower: new RegExp(escapeRegexp(query.toLowerCase())) + }, { + limit: limit - users.length + }); + + users = users.concat(otherUsers); + } + + if (users.length < limit) { + const otherUsers = await User + .find({ + _id: { $nin: users.map(u => u._id) }, + host: { $ne: null }, + usernameLower: new RegExp(escapeRegexp(query.toLowerCase())) + }, { + limit: limit - users.length + }); + + users = users.concat(otherUsers); } // Serialize diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts index bf7e2a2312..8ec0eb8dd9 100644 --- a/src/server/api/endpoints/users/show.ts +++ b/src/server/api/endpoints/users/show.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../cafy-id'; +import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import User, { pack, ILocalUser } from '../../../../models/user'; import resolveRemoteUser from '../../../../remote/resolve-user'; @@ -7,23 +7,23 @@ const cursorOption = { fields: { data: false } }; /** * Show user(s) */ -module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => { +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { let user; // Get 'userId' parameter - const [userId, userIdErr] = $.type(ID).optional().get(params.userId); + const [userId, userIdErr] = $.type(ID).optional.get(params.userId); if (userIdErr) return rej('invalid userId param'); // Get 'userIds' parameter - const [userIds, userIdsErr] = $.arr($.type(ID)).optional().get(params.userIds); + const [userIds, userIdsErr] = $.arr($.type(ID)).optional.get(params.userIds); if (userIdsErr) return rej('invalid userIds param'); // Get 'username' parameter - const [username, usernameErr] = $.str.optional().get(params.username); + const [username, usernameErr] = $.str.optional.get(params.username); if (usernameErr) return rej('invalid username param'); // Get 'host' parameter - const [host, hostErr] = $.str.optional().nullable().get(params.host); + const [host, hostErr] = $.str.optional.nullable.get(params.host); if (hostErr) return rej('invalid host param'); if (userIds) { diff --git a/src/server/api/get-params.ts b/src/server/api/get-params.ts new file mode 100644 index 0000000000..e495e3ef3e --- /dev/null +++ b/src/server/api/get-params.ts @@ -0,0 +1,27 @@ +import { Context } from 'cafy'; + +type Defs = { + params: { [key: string]: Context<any> } +}; + +export default function <T extends Defs>(defs: T, params: any): [{ + [P in keyof T['params']]: ReturnType<T['params'][P]['get']>[0]; +}, Error] { + const x: any = {}; + let err: Error = null; + Object.keys(defs.params).some(k => { + const [v, e] = defs.params[k].get(params[k]); + if (e) { + err = e; + return true; + } else { + if (v === undefined && defs.params[k].data.default) { + x[k] = defs.params[k].data.default; + } else { + x[k] = v; + } + return false; + } + }); + return [x, err]; +} diff --git a/src/server/api/index.ts b/src/server/api/index.ts index 004c21b821..3ec7a28df9 100644 --- a/src/server/api/index.ts +++ b/src/server/api/index.ts @@ -35,7 +35,7 @@ const router = new Router(); /** * Register endpoint handlers */ -endpoints.forEach(endpoint => endpoint.withFile +endpoints.forEach(endpoint => endpoint.meta.requireFile ? router.post(`/${endpoint.name}`, upload.single('file'), handler.bind(null, endpoint)) : router.post(`/${endpoint.name}`, handler.bind(null, endpoint)) ); diff --git a/src/server/api/limitter.ts b/src/server/api/limitter.ts index b84e16ecde..20a18a7098 100644 --- a/src/server/api/limitter.ts +++ b/src/server/api/limitter.ts @@ -1,14 +1,14 @@ import * as Limiter from 'ratelimiter'; import * as debug from 'debug'; import limiterDB from '../../db/redis'; -import { Endpoint } from './endpoints'; -import getAcct from '../../acct/render'; +import { IEndpoint } from './endpoints'; +import getAcct from '../../misc/acct/render'; import { IUser } from '../../models/user'; const log = debug('misskey:limitter'); -export default (endpoint: Endpoint, user: IUser) => new Promise((ok, reject) => { - const limitation = endpoint.limit; +export default (endpoint: IEndpoint, user: IUser) => new Promise((ok, reject) => { + const limitation = endpoint.meta.limit; const key = limitation.hasOwnProperty('key') ? limitation.key diff --git a/src/server/api/private/signin.ts b/src/server/api/private/signin.ts index 5450c7ad27..65413208dd 100644 --- a/src/server/api/private/signin.ts +++ b/src/server/api/private/signin.ts @@ -3,7 +3,7 @@ import * as bcrypt from 'bcryptjs'; import * as speakeasy from 'speakeasy'; import User, { ILocalUser } from '../../../models/user'; import Signin, { pack } from '../../../models/signin'; -import event from '../../../publishers/stream'; +import { publishUserStream } from '../../../stream'; import signin from '../common/signin'; import config from '../../../config'; @@ -11,9 +11,10 @@ export default async (ctx: Koa.Context) => { ctx.set('Access-Control-Allow-Origin', config.url); ctx.set('Access-Control-Allow-Credentials', 'true'); - const username = ctx.request.body['username']; - const password = ctx.request.body['password']; - const token = ctx.request.body['token']; + const body = ctx.request.body as any; + const username = body['username']; + const password = body['password']; + const token = body['token']; if (typeof username != 'string') { ctx.status = 400; @@ -35,11 +36,11 @@ export default async (ctx: Koa.Context) => { usernameLower: username.toLowerCase(), host: null }, { - fields: { - data: false, - profile: false - } - }) as ILocalUser; + fields: { + data: false, + profile: false + } + }) as ILocalUser; if (user === null) { ctx.throw(404, { @@ -85,5 +86,5 @@ export default async (ctx: Koa.Context) => { }); // Publish signin event - event(user._id, 'signin', await pack(record)); + publishUserStream(user._id, 'signin', await pack(record)); }; diff --git a/src/server/api/private/signup.ts b/src/server/api/private/signup.ts index cb47d400b0..563b6ca845 100644 --- a/src/server/api/private/signup.ts +++ b/src/server/api/private/signup.ts @@ -7,15 +7,19 @@ import generateUserToken from '../common/generate-native-user-token'; import config from '../../../config'; import Meta from '../../../models/meta'; -recaptcha.init({ - secret_key: config.recaptcha.secret_key -}); +if (config.recaptcha) { + recaptcha.init({ + secret_key: config.recaptcha.secret_key + }); +} export default async (ctx: Koa.Context) => { + const body = ctx.request.body as any; + // Verify recaptcha // ただしテスト時はこの機構は障害となるため無効にする - if (process.env.NODE_ENV !== 'test') { - const success = await recaptcha(ctx.request.body['g-recaptcha-response']); + if (process.env.NODE_ENV !== 'test' && config.recaptcha != null) { + const success = await recaptcha(body['g-recaptcha-response']); if (!success) { ctx.throw(400, 'recaptcha-failed'); @@ -23,8 +27,8 @@ export default async (ctx: Koa.Context) => { } } - const username = ctx.request.body['username']; - const password = ctx.request.body['password']; + const username = body['username']; + const password = body['password']; // Validate username if (!validateUsername(username)) { @@ -44,8 +48,8 @@ export default async (ctx: Koa.Context) => { usernameLower: username.toLowerCase(), host: null }, { - limit: 1 - }); + limit: 1 + }); // Check username already used if (usernameExist !== 0) { @@ -70,14 +74,12 @@ export default async (ctx: Koa.Context) => { followingCount: 0, name: null, notesCount: 0, - driveCapacity: 1024 * 1024 * 128, // 128MiB username: username, usernameLower: username.toLowerCase(), host: null, keypair: generateKeypair(), token: secret, email: null, - links: null, password: hash, profile: { bio: null, diff --git a/src/server/api/service/twitter.ts b/src/server/api/service/twitter.ts index 8c35509cce..8c668e832a 100644 --- a/src/server/api/service/twitter.ts +++ b/src/server/api/service/twitter.ts @@ -4,7 +4,7 @@ import * as uuid from 'uuid'; import autwh from 'autwh'; import redis from '../../../db/redis'; import User, { pack, ILocalUser } from '../../../models/user'; -import event from '../../../publishers/stream'; +import { publishUserStream } from '../../../stream'; import config from '../../../config'; import signin from '../common/signin'; @@ -49,7 +49,7 @@ router.get('/disconnect/twitter', async ctx => { ctx.body = `Twitterの連携を解除しました :v:`; // Publish i updated event - event(user._id, 'meUpdated', await pack(user, user, { + publishUserStream(user._id, 'meUpdated', await pack(user, user, { detail: true, includeSecrets: true })); @@ -174,7 +174,7 @@ if (config.twitter == null) { ctx.body = `Twitter: @${result.screenName} を、Misskey: @${user.username} に接続しました!`; // Publish i updated event - event(user._id, 'meUpdated', await pack(user, user, { + publishUserStream(user._id, 'meUpdated', await pack(user, user, { detail: true, includeSecrets: true })); diff --git a/src/server/api/stream/drive.ts b/src/server/api/stream/drive.ts index c97ab80dcc..28c241e1bc 100644 --- a/src/server/api/stream/drive.ts +++ b/src/server/api/stream/drive.ts @@ -1,10 +1,9 @@ import * as websocket from 'websocket'; -import * as redis from 'redis'; +import Xev from 'xev'; -export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void { +export default function(request: websocket.request, connection: websocket.connection, subscriber: Xev, user: any): void { // Subscribe drive stream - subscriber.subscribe(`misskey:drive-stream:${user._id}`); - subscriber.on('message', (_, data) => { - connection.send(data); + subscriber.on(`drive-stream:${user._id}`, data => { + connection.send(JSON.stringify(data)); }); } diff --git a/src/server/api/stream/reversi-game.ts b/src/server/api/stream/games/reversi-game.ts similarity index 90% rename from src/server/api/stream/reversi-game.ts rename to src/server/api/stream/games/reversi-game.ts index ea8a9741d2..5cbbf42d59 100644 --- a/src/server/api/stream/reversi-game.ts +++ b/src/server/api/stream/games/reversi-game.ts @@ -1,20 +1,19 @@ import * as websocket from 'websocket'; -import * as redis from 'redis'; +import Xev from 'xev'; import * as CRC32 from 'crc-32'; -import ReversiGame, { pack } from '../../../models/reversi-game'; -import { publishReversiGameStream } from '../../../publishers/stream'; -import Reversi from '../../../reversi/core'; -import * as maps from '../../../reversi/maps'; +import ReversiGame, { pack } from '../../../../models/games/reversi/game'; +import { publishReversiGameStream } from '../../../../stream'; +import Reversi from '../../../../games/reversi/core'; +import * as maps from '../../../../games/reversi/maps'; import { ParsedUrlQuery } from 'querystring'; -export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user?: any): void { +export default function(request: websocket.request, connection: websocket.connection, subscriber: Xev, user?: any): void { const q = request.resourceURL.query as ParsedUrlQuery; - const gameId = q.game; + const gameId = q.game as string; // Subscribe game stream - subscriber.subscribe(`misskey:reversi-game-stream:${gameId}`); - subscriber.on('message', (_, data) => { - connection.send(data); + subscriber.on(`reversi-game-stream:${gameId}`, data => { + connection.send(JSON.stringify(data)); }); connection.on('message', async (data) => { @@ -87,8 +86,8 @@ export default function(request: websocket.request, connection: websocket.connec const set = game.user1Id.equals(user._id) ? { form1: form } : { - form2: form - }; + form2: form + }; await ReversiGame.update({ _id: gameId }, { $set: set @@ -117,8 +116,8 @@ export default function(request: websocket.request, connection: websocket.connec const set = game.user1Id.equals(user._id) ? { form2: form } : { - form1: form - }; + form1: form + }; await ReversiGame.update({ _id: gameId }, { $set: set @@ -193,7 +192,7 @@ export default function(request: websocket.request, connection: websocket.connec function getRandomMap() { const mapCount = Object.entries(maps).length; const rnd = Math.floor(Math.random() * mapCount); - return Object.entries(maps).find((x, i) => i == rnd)[1].data; + return Object.values(maps)[rnd].data; } const map = freshGame.settings.map != null ? freshGame.settings.map : getRandomMap(); @@ -227,11 +226,11 @@ export default function(request: websocket.request, connection: websocket.connec await ReversiGame.update({ _id: gameId }, { - $set: { - isEnded: true, - winnerId: winner - } - }); + $set: { + isEnded: true, + winnerId: winner + } + }); publishReversiGameStream(gameId, 'ended', { winnerId: winner, @@ -293,15 +292,15 @@ export default function(request: websocket.request, connection: websocket.connec await ReversiGame.update({ _id: gameId }, { - $set: { - crc32, - isEnded: o.isEnded, - winnerId: winner - }, - $push: { - logs: log - } - }); + $set: { + crc32, + isEnded: o.isEnded, + winnerId: winner + }, + $push: { + logs: log + } + }); publishReversiGameStream(gameId, 'set', Object.assign(log, { next: o.turn diff --git a/src/server/api/stream/reversi.ts b/src/server/api/stream/games/reversi.ts similarity index 62% rename from src/server/api/stream/reversi.ts rename to src/server/api/stream/games/reversi.ts index 35c6167364..f467613b21 100644 --- a/src/server/api/stream/reversi.ts +++ b/src/server/api/stream/games/reversi.ts @@ -1,14 +1,13 @@ import * as mongo from 'mongodb'; import * as websocket from 'websocket'; -import * as redis from 'redis'; -import Matching, { pack } from '../../../models/reversi-matching'; -import publishUserStream from '../../../publishers/stream'; +import Xev from 'xev'; +import Matching, { pack } from '../../../../models/games/reversi/matching'; +import { publishUserStream } from '../../../../stream'; -export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void { +export default function(request: websocket.request, connection: websocket.connection, subscriber: Xev, user: any): void { // Subscribe reversi stream - subscriber.subscribe(`misskey:reversi-stream:${user._id}`); - subscriber.on('message', (_, data) => { - connection.send(data); + subscriber.on(`reversi-stream:${user._id}`, data => { + connection.send(JSON.stringify(data)); }); connection.on('message', async (data) => { diff --git a/src/server/api/stream/global-timeline.ts b/src/server/api/stream/global-timeline.ts index f31ce17752..4786450cbb 100644 --- a/src/server/api/stream/global-timeline.ts +++ b/src/server/api/stream/global-timeline.ts @@ -1,5 +1,5 @@ import * as websocket from 'websocket'; -import * as redis from 'redis'; +import Xev from 'xev'; import { IUser } from '../../../models/user'; import Mute from '../../../models/mute'; @@ -7,18 +7,14 @@ import Mute from '../../../models/mute'; export default async function( request: websocket.request, connection: websocket.connection, - subscriber: redis.RedisClient, + subscriber: Xev, user: IUser ) { - // Subscribe stream - subscriber.subscribe(`misskey:global-timeline`); - const mute = await Mute.find({ muterId: user._id }); const mutedUserIds = mute.map(m => m.muteeId.toString()); - subscriber.on('message', async (_, data) => { - const note = JSON.parse(data); - + // Subscribe stream + subscriber.on('global-timeline', async note => { //#region 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する if (mutedUserIds.indexOf(note.userId) != -1) { return; diff --git a/src/server/api/stream/home.ts b/src/server/api/stream/home.ts index d9b8f7fb96..dc3ce9d19f 100644 --- a/src/server/api/stream/home.ts +++ b/src/server/api/stream/home.ts @@ -1,5 +1,5 @@ import * as websocket from 'websocket'; -import * as redis from 'redis'; +import Xev from 'xev'; import * as debug from 'debug'; import User, { IUser } from '../../../models/user'; @@ -14,68 +14,54 @@ const log = debug('misskey'); export default async function( request: websocket.request, connection: websocket.connection, - subscriber: redis.RedisClient, + subscriber: Xev, user: IUser, app: IApp ) { - // Subscribe Home stream channel - subscriber.subscribe(`misskey:user-stream:${user._id}`); - const mute = await Mute.find({ muterId: user._id }); const mutedUserIds = mute.map(m => m.muteeId.toString()); - subscriber.on('message', async (channel, data) => { - switch (channel.split(':')[1]) { - case 'user-stream': - try { - const x = JSON.parse(data); + async function onNoteStream(noteId: any) { + const note = await packNote(noteId, user, { + detail: true + }); - //#region 流れてきたメッセージがミュートしているユーザーが関わるものだったら無視する - if (x.type == 'note') { - if (mutedUserIds.includes(x.body.userId)) { - return; - } - if (x.body.reply != null && mutedUserIds.includes(x.body.reply.userId)) { - return; - } - if (x.body.renote != null && mutedUserIds.includes(x.body.renote.userId)) { - return; - } - } else if (x.type == 'notification') { - if (mutedUserIds.includes(x.body.userId)) { - return; - } - } - //#endregion + connection.send(JSON.stringify({ + type: 'note-updated', + body: { + note: note + } + })); + } - // Renoteなら再pack - if (x.type == 'note' && x.body.renoteId != null) { - x.body.renote = await pack(x.body.renoteId, user, { - detail: true - }); - data = JSON.stringify(x); - } - - connection.send(data); - } catch (e) { - connection.send(data); - } - break; - - case 'note-stream': - const noteId = channel.split(':')[2]; - log(`RECEIVED: ${noteId} ${data} by @${user.username}`); - const note = await packNote(noteId, user, { - detail: true - }); - connection.send(JSON.stringify({ - type: 'note-updated', - body: { - note: note - } - })); - break; + // Subscribe Home stream channel + subscriber.on(`user-stream:${user._id}`, async x => { + //#region 流れてきたメッセージがミュートしているユーザーが関わるものだったら無視する + if (x.type == 'note') { + if (mutedUserIds.includes(x.body.userId)) { + return; + } + if (x.body.reply != null && mutedUserIds.includes(x.body.reply.userId)) { + return; + } + if (x.body.renote != null && mutedUserIds.includes(x.body.renote.userId)) { + return; + } + } else if (x.type == 'notification') { + if (mutedUserIds.includes(x.body.userId)) { + return; + } } + //#endregion + + // Renoteなら再pack + if (x.type == 'note' && x.body.renoteId != null) { + x.body.renote = await pack(x.body.renoteId, user, { + detail: true + }); + } + + connection.send(JSON.stringify(x)); }); connection.on('message', async data => { @@ -113,9 +99,14 @@ export default async function( case 'capture': if (!msg.id) return; - const noteId = msg.id; - log(`CAPTURE: ${noteId} by @${user.username}`); - subscriber.subscribe(`misskey:note-stream:${noteId}`); + log(`CAPTURE: ${msg.id} by @${user.username}`); + subscriber.on(`note-stream:${msg.id}`, onNoteStream); + break; + + case 'decapture': + if (!msg.id) return; + log(`DECAPTURE: ${msg.id} by @${user.username}`); + subscriber.off(`note-stream:${msg.id}`, onNoteStream); break; } }); diff --git a/src/server/api/stream/hybrid-timeline.ts b/src/server/api/stream/hybrid-timeline.ts new file mode 100644 index 0000000000..5f411317c3 --- /dev/null +++ b/src/server/api/stream/hybrid-timeline.ts @@ -0,0 +1,46 @@ +import * as websocket from 'websocket'; +import Xev from 'xev'; + +import { IUser } from '../../../models/user'; +import Mute from '../../../models/mute'; +import { pack } from '../../../models/note'; + +export default async function( + request: websocket.request, + connection: websocket.connection, + subscriber: Xev, + user: IUser +) { + // Subscribe stream + subscriber.on('hybrid-timeline', onEvent); + subscriber.on(`hybrid-timeline:${user._id}`, onEvent); + + const mute = await Mute.find({ muterId: user._id }); + const mutedUserIds = mute.map(m => m.muteeId.toString()); + + async function onEvent(note: any) { + //#region 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する + if (mutedUserIds.indexOf(note.userId) != -1) { + return; + } + if (note.reply != null && mutedUserIds.indexOf(note.reply.userId) != -1) { + return; + } + if (note.renote != null && mutedUserIds.indexOf(note.renote.userId) != -1) { + return; + } + //#endregion + + // Renoteなら再pack + if (note.renoteId != null) { + note.renote = await pack(note.renoteId, user, { + detail: true + }); + } + + connection.send(JSON.stringify({ + type: 'note', + body: note + })); + } +} diff --git a/src/server/api/stream/local-timeline.ts b/src/server/api/stream/local-timeline.ts index 8f6a445be0..82060a7aaa 100644 --- a/src/server/api/stream/local-timeline.ts +++ b/src/server/api/stream/local-timeline.ts @@ -1,5 +1,5 @@ import * as websocket from 'websocket'; -import * as redis from 'redis'; +import Xev from 'xev'; import { IUser } from '../../../models/user'; import Mute from '../../../models/mute'; @@ -8,18 +8,14 @@ import { pack } from '../../../models/note'; export default async function( request: websocket.request, connection: websocket.connection, - subscriber: redis.RedisClient, + subscriber: Xev, user: IUser ) { - // Subscribe stream - subscriber.subscribe(`misskey:local-timeline`); - const mute = await Mute.find({ muterId: user._id }); const mutedUserIds = mute.map(m => m.muteeId.toString()); - subscriber.on('message', async (_, data) => { - const note = JSON.parse(data); - + // Subscribe stream + subscriber.on('local-timeline', async note => { //#region 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する if (mutedUserIds.indexOf(note.userId) != -1) { return; diff --git a/src/server/api/stream/messaging-index.ts b/src/server/api/stream/messaging-index.ts index c1b2fbc806..9af63f2812 100644 --- a/src/server/api/stream/messaging-index.ts +++ b/src/server/api/stream/messaging-index.ts @@ -1,10 +1,9 @@ import * as websocket from 'websocket'; -import * as redis from 'redis'; +import Xev from 'xev'; -export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void { +export default function(request: websocket.request, connection: websocket.connection, subscriber: Xev, user: any): void { // Subscribe messaging index stream - subscriber.subscribe(`misskey:messaging-index-stream:${user._id}`); - subscriber.on('message', (_, data) => { - connection.send(data); + subscriber.on(`messaging-index-stream:${user._id}`, data => { + connection.send(JSON.stringify(data)); }); } diff --git a/src/server/api/stream/messaging.ts b/src/server/api/stream/messaging.ts index 3e6c2cd509..8b352cea3c 100644 --- a/src/server/api/stream/messaging.ts +++ b/src/server/api/stream/messaging.ts @@ -1,16 +1,15 @@ import * as websocket from 'websocket'; -import * as redis from 'redis'; +import Xev from 'xev'; import read from '../common/read-messaging-message'; import { ParsedUrlQuery } from 'querystring'; -export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void { +export default function(request: websocket.request, connection: websocket.connection, subscriber: Xev, user: any): void { const q = request.resourceURL.query as ParsedUrlQuery; const otherparty = q.otherparty as string; // Subscribe messaging stream - subscriber.subscribe(`misskey:messaging-stream:${user._id}-${otherparty}`); - subscriber.on('message', (_, data) => { - connection.send(data); + subscriber.on(`messaging-stream:${user._id}-${otherparty}`, data => { + connection.send(JSON.stringify(data)); }); connection.on('message', async (data) => { diff --git a/src/server/api/stream/user-list.ts b/src/server/api/stream/user-list.ts index ba03b97860..33cc2a1ee1 100644 --- a/src/server/api/stream/user-list.ts +++ b/src/server/api/stream/user-list.ts @@ -1,14 +1,13 @@ import * as websocket from 'websocket'; -import * as redis from 'redis'; +import Xev from 'xev'; import { ParsedUrlQuery } from 'querystring'; -export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void { +export default function(request: websocket.request, connection: websocket.connection, subscriber: Xev, user: any): void { const q = request.resourceURL.query as ParsedUrlQuery; const listId = q.listId as string; // Subscribe stream - subscriber.subscribe(`misskey:user-list-stream:${listId}`); - subscriber.on('message', (_, data) => { + subscriber.on(`user-list-stream:${listId}`, data => { connection.send(data); }); } diff --git a/src/server/api/streaming.ts b/src/server/api/streaming.ts index 81adff0b58..c8b2d4e0b9 100644 --- a/src/server/api/streaming.ts +++ b/src/server/api/streaming.ts @@ -1,17 +1,17 @@ import * as http from 'http'; import * as websocket from 'websocket'; -import * as redis from 'redis'; -import config from '../../config'; +import Xev from 'xev'; import homeStream from './stream/home'; import localTimelineStream from './stream/local-timeline'; +import hybridTimelineStream from './stream/hybrid-timeline'; import globalTimelineStream from './stream/global-timeline'; import userListStream from './stream/user-list'; import driveStream from './stream/drive'; import messagingStream from './stream/messaging'; import messagingIndexStream from './stream/messaging-index'; -import reversiGameStream from './stream/reversi-game'; -import reversiStream from './stream/reversi'; +import reversiGameStream from './stream/games/reversi-game'; +import reversiStream from './stream/games/reversi'; import serverStatsStream from './stream/server-stats'; import notesStatsStream from './stream/notes-stats'; import { ParsedUrlQuery } from 'querystring'; @@ -38,20 +38,17 @@ module.exports = (server: http.Server) => { return; } - // Connect to Redis - const subscriber = redis.createClient( - config.redis.port, config.redis.host); + const ev = new Xev(); - connection.on('close', () => { - subscriber.unsubscribe(); - subscriber.quit(); + connection.once('close', () => { + ev.removeAllListeners(); }); const q = request.resourceURL.query as ParsedUrlQuery; const [user, app] = await authenticate(q.i as string); - if (request.resourceURL.pathname === '/reversi-game') { - reversiGameStream(request, connection, subscriber, user); + if (request.resourceURL.pathname === '/games/reversi-game') { + reversiGameStream(request, connection, ev, user); return; } @@ -64,16 +61,17 @@ module.exports = (server: http.Server) => { const channel: any = request.resourceURL.pathname === '/' ? homeStream : request.resourceURL.pathname === '/local-timeline' ? localTimelineStream : + request.resourceURL.pathname === '/hybrid-timeline' ? hybridTimelineStream : request.resourceURL.pathname === '/global-timeline' ? globalTimelineStream : request.resourceURL.pathname === '/user-list' ? userListStream : request.resourceURL.pathname === '/drive' ? driveStream : request.resourceURL.pathname === '/messaging' ? messagingStream : request.resourceURL.pathname === '/messaging-index' ? messagingIndexStream : - request.resourceURL.pathname === '/reversi' ? reversiStream : + request.resourceURL.pathname === '/games/reversi' ? reversiStream : null; if (channel !== null) { - channel(request, connection, subscriber, user, app); + channel(request, connection, ev, user, app); } else { connection.close(); } diff --git a/src/server/file/assets/avatar.jpg b/src/server/file/assets/avatar.jpg index 3c803f568e..be0c3ca829 100644 Binary files a/src/server/file/assets/avatar.jpg and b/src/server/file/assets/avatar.jpg differ diff --git a/src/server/file/assets/bad-egg.png b/src/server/file/assets/bad-egg.png index a7c5930bd4..e96ba0dcc1 100644 Binary files a/src/server/file/assets/bad-egg.png and b/src/server/file/assets/bad-egg.png differ diff --git a/src/server/file/assets/cache-expired.png b/src/server/file/assets/cache-expired.png index ea681af0a0..5d988c502b 100644 Binary files a/src/server/file/assets/cache-expired.png and b/src/server/file/assets/cache-expired.png differ diff --git a/src/server/file/assets/not-an-image.png b/src/server/file/assets/not-an-image.png index bf98b293f7..39e4aa0892 100644 Binary files a/src/server/file/assets/not-an-image.png and b/src/server/file/assets/not-an-image.png differ diff --git a/src/server/file/assets/thumbnail-not-available.png b/src/server/file/assets/thumbnail-not-available.png index f960ce4d00..07cad9919c 100644 Binary files a/src/server/file/assets/thumbnail-not-available.png and b/src/server/file/assets/thumbnail-not-available.png differ diff --git a/src/server/file/assets/tombstone.png b/src/server/file/assets/tombstone.png index 86224e3182..83159d6b3c 100644 Binary files a/src/server/file/assets/tombstone.png and b/src/server/file/assets/tombstone.png differ diff --git a/src/server/file/send-drive-file.ts b/src/server/file/send-drive-file.ts index e04400317f..1a76b0e41f 100644 --- a/src/server/file/send-drive-file.ts +++ b/src/server/file/send-drive-file.ts @@ -37,7 +37,7 @@ export default async function(ctx: Koa.Context) { return; } - if (file.metadata.isMetaOnly) { + if (file.metadata.withoutChunks) { ctx.status = 204; return; } diff --git a/src/server/web/docs.ts b/src/server/web/docs.ts index e65cc87b12..81e5ace3e8 100644 --- a/src/server/web/docs.ts +++ b/src/server/web/docs.ts @@ -2,26 +2,239 @@ * Docs */ +import * as fs from 'fs'; +import * as path from 'path'; +import * as showdown from 'showdown'; +import 'showdown-highlightjs-extension'; import ms = require('ms'); import * as Router from 'koa-router'; import * as send from 'koa-send'; +import { Context, ObjectContext } from 'cafy'; +import * as glob from 'glob'; +import * as yaml from 'js-yaml'; +import config from '../../config'; +import I18n from '../../misc/i18n'; +import { licenseHtml } from '../../misc/license'; +const constants = require('../../const.json'); +import endpoints from '../api/endpoints'; -const docs = `${__dirname}/../../client/docs/`; +async function genVars(lang: string): Promise<{ [key: string]: any }> { + const vars = {} as { [key: string]: any }; + + vars['lang'] = lang; + + const cwd = path.resolve(__dirname + '/../../../') + '/'; + + vars['endpoints'] = endpoints; + + const entities = glob.sync('src/docs/api/entities/**/*.yaml', { cwd }); + vars['entities'] = entities.map(x => { + const _x = yaml.safeLoad(fs.readFileSync(cwd + x, 'utf-8')) as any; + return _x.name; + }); + + const docs = glob.sync(`src/docs/**/*.${lang}.md`, { cwd }); + vars['docs'] = {}; + docs.forEach(x => { + const [, name] = x.match(/docs\/(.+?)\.(.+?)\.md$/); + if (vars['docs'][name] == null) { + vars['docs'][name] = { + name, + title: {} + }; + } + vars['docs'][name]['title'][lang] = fs.readFileSync(cwd + x, 'utf-8').match(/^# (.+?)\r?\n/)[1]; + }); + + vars['kebab'] = (string: string) => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase(); + + vars['config'] = config; + + vars['copyright'] = constants.copyright; + + vars['license'] = licenseHtml; + + const i18n = new I18n(lang); + vars['i18n'] = (key: string) => i18n.get(null, key); + + return vars; +} + +// WIP type +const parseParamDefinition = (key: string, param: Context) => { + return Object.assign({ + name: key, + type: param.getType() + }, param.data); +}; + +const parsePropDefinition = (key: string, prop: any) => { + const id = prop.type.match(/^id\((.+?)\)|^id/); + const entity = prop.type.match(/^entity\((.+?)\)/); + const isObject = /^object/.test(prop.type); + const isDate = /^date/.test(prop.type); + const isArray = /\[\]$/.test(prop.type); + if (id) { + prop.kind = 'id'; + prop.type = 'string'; + prop.entity = id[1]; + if (isArray) { + prop.type += '[]'; + } + } + if (entity) { + prop.kind = 'entity'; + prop.type = 'object'; + prop.entity = entity[1]; + if (isArray) { + prop.type += '[]'; + } + } + if (isObject) { + prop.kind = 'object'; + if (prop.props) { + prop.hasDef = true; + } + } + if (isDate) { + prop.kind = 'date'; + prop.type = 'string'; + if (isArray) { + prop.type += '[]'; + } + } + + if (prop.optional) { + prop.type += '?'; + } + + prop.name = key; + + return prop; +}; + +const sortParams = (params: Array<{ name: string }>) => { + return params; +}; + +// WIP type +const extractParamDefRef = (params: Context[]) => { + let defs: any[] = []; + + params.forEach(param => { + if (param.data && param.data.ref) { + const props = (param as ObjectContext<any>).props; + defs.push({ + name: param.data.ref, + params: sortParams(Object.keys(props).map(k => parseParamDefinition(k, props[k]))) + }); + + const childDefs = extractParamDefRef(Object.keys(props).map(k => props[k])); + + defs = defs.concat(childDefs); + } + }); + + return sortParams(defs); +}; + +const extractPropDefRef = (props: any[]) => { + let defs: any[] = []; + + Object.entries(props).forEach(([k, v]) => { + if (v.props) { + defs.push({ + name: k, + props: sortParams(Object.entries(v.props).map(([k, v]) => parsePropDefinition(k, v))) + }); + + const childDefs = extractPropDefRef(v.props); + + defs = defs.concat(childDefs); + } + }); + + return sortParams(defs); +}; const router = new Router(); router.get('/assets/*', async ctx => { await send(ctx, ctx.params[0], { - root: docs + '/assets/', + root: `${__dirname}/../../docs/assets/`, maxage: ms('7 days'), immutable: true }); }); -router.get('*', async ctx => { - await send(ctx, `${ctx.params[0]}.html`, { - root: docs +router.get('/*/api/endpoints/*', async ctx => { + const lang = ctx.params[0]; + const name = ctx.params[1]; + const ep = endpoints.find(e => e.name === name); + + const vars = { + id: `api/endpoints/${name}`, + title: name, + endpoint: ep.meta, + endpointUrl: { + host: config.api_url, + path: name + }, + // @ts-ignore + params: ep.meta.params ? sortParams(Object.entries(ep.meta.params).map(([k, v]) => parseParamDefinition(k, v))) : null, + paramDefs: ep.meta.params ? extractParamDefRef(Object.values(ep.meta.params)) : null, + res: ep.meta.res, + resProps: ep.meta.res && ep.meta.res.props ? sortParams(Object.entries(ep.meta.res.props).map(([k, v]) => parsePropDefinition(k, v))) : null, + resDefs: null as any, //extractPropDefRef(Object.entries(ep.res.props).map(([k, v]) => parsePropDefinition(k, v))) + src: `https://github.com/syuilo/misskey/tree/master/src/server/api/endpoints/${name}.ts` + }; + + await ctx.render('../../../../src/docs/api/endpoints/view', Object.assign(await genVars(lang), vars)); +}); + +router.get('/*/api/entities/*', async ctx => { + const lang = ctx.params[0]; + const entity = ctx.params[1]; + + const x = yaml.safeLoad(fs.readFileSync(path.resolve(__dirname + '/../../../src/docs/api/entities/' + entity + '.yaml'), 'utf-8')) as any; + + await ctx.render('../../../../src/docs/api/entities/view', Object.assign(await genVars(lang), { + id: `api/entities/${entity}`, + name: x.name, + desc: x.desc, + props: sortParams(Object.entries(x.props).map(([k, v]) => parsePropDefinition(k, v))), + propDefs: extractPropDefRef(x.props) + })); +}); + +router.get('/*/*', async ctx => { + const lang = ctx.params[0]; + const doc = ctx.params[1]; + + showdown.extension('urlExtension', () => ({ + type: 'output', + regex: /%URL%/g, + replace: config.url + })); + + showdown.extension('apiUrlExtension', () => ({ + type: 'output', + regex: /%API_URL%/g, + replace: config.api_url + })); + + const conv = new showdown.Converter({ + tables: true, + extensions: ['urlExtension', 'apiUrlExtension', 'highlightjs'] }); + const md = fs.readFileSync(`${__dirname}/../../../src/docs/${doc}.${lang}.md`, 'utf8'); + + await ctx.render('../../../../src/docs/article', Object.assign({ + id: doc, + html: conv.makeHtml(md), + title: md.match(/^# (.+?)\r?\n/)[1], + src: `https://github.com/syuilo/misskey/tree/master/src/docs/${doc}.${lang}.md` + }, await genVars(lang))); }); export default router; diff --git a/src/server/web/index.ts b/src/server/web/index.ts index 4400fc1024..7291f8a0a5 100644 --- a/src/server/web/index.ts +++ b/src/server/web/index.ts @@ -11,11 +11,11 @@ import * as views from 'koa-views'; import docs from './docs'; import User from '../../models/user'; -import parseAcct from '../../acct/parse'; -import { fa } from '../../build/fa'; +import parseAcct from '../../misc/acct/parse'; +import { fa } from '../../misc/fa'; import config from '../../config'; import Note, { pack as packNote } from '../../models/note'; -import getNoteSummary from '../../renderers/get-note-summary'; +import getNoteSummary from '../../misc/get-note-summary'; const consts = require('../../const.json'); const client = `${__dirname}/../../client/`; diff --git a/src/server/webfinger.ts b/src/server/webfinger.ts index ce0cb82fe2..6c2afae79c 100644 --- a/src/server/webfinger.ts +++ b/src/server/webfinger.ts @@ -2,7 +2,7 @@ import * as mongo from 'mongodb'; import * as Router from 'koa-router'; import config from '../config'; -import parseAcct from '../acct/parse'; +import parseAcct from '../misc/acct/parse'; import User, { IUser } from '../models/user'; // Init router diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts index 4167df0662..a04bab9dbd 100644 --- a/src/services/drive/add-file.ts +++ b/src/services/drive/add-file.ts @@ -4,48 +4,67 @@ import * as stream from 'stream'; import * as mongodb from 'mongodb'; import * as crypto from 'crypto'; -import * as _gm from 'gm'; import * as debug from 'debug'; import fileType = require('file-type'); -const prominence = require('prominence'); +import * as Minio from 'minio'; +import * as uuid from 'uuid'; +import * as sharp from 'sharp'; import DriveFile, { IMetadata, getDriveFileBucket, IDriveFile } from '../../models/drive-file'; import DriveFolder from '../../models/drive-folder'; import { pack } from '../../models/drive-file'; -import event, { publishDriveStream } from '../../publishers/stream'; +import { publishUserStream, publishDriveStream } from '../../stream'; import { isLocalUser, IUser, IRemoteUser } from '../../models/user'; -import { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail'; -import genThumbnail from '../../drive/gen-thumbnail'; import delFile from './delete-file'; - -const gm = _gm.subClass({ - imageMagick: true -}); +import config from '../../config'; const log = debug('misskey:drive:add-file'); -const writeChunks = (name: string, readable: stream.Readable, type: string, metadata: any) => - getDriveFileBucket() - .then(bucket => new Promise((resolve, reject) => { +async function save(readable: stream.Readable, name: string, type: string, hash: string, size: number, metadata: any): Promise<IDriveFile> { + if (config.drive && config.drive.storage == 'minio') { + const minio = new Minio.Client(config.drive.config); + const id = uuid.v4(); + const obj = `${config.drive.prefix}/${id}`; + + const baseUrl = config.drive.baseUrl + || `${ config.drive.config.secure ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }`; + + await minio.putObject(config.drive.bucket, obj, readable, size, { + 'Content-Type': type, + 'Cache-Control': 'max-age=31536000, immutable' + }); + + Object.assign(metadata, { + withoutChunks: true, + storage: 'minio', + storageProps: { + id: id + }, + url: `${ baseUrl }/${ obj }` + }); + + const file = await DriveFile.insert({ + length: size, + uploadDate: new Date(), + md5: hash, + filename: name, + metadata: metadata, + contentType: type + }); + + return file; + } else { + // Get MongoDB GridFS bucket + const bucket = await getDriveFileBucket(); + + return new Promise<IDriveFile>((resolve, reject) => { const writeStream = bucket.openUploadStream(name, { contentType: type, metadata }); writeStream.once('finish', resolve); writeStream.on('error', reject); readable.pipe(writeStream); - })); - -const writeThumbnailChunks = (name: string, readable: stream.Readable, originalId: mongodb.ObjectID) => - getDriveFileThumbnailBucket() - .then(bucket => new Promise((resolve, reject) => { - const writeStream = bucket.openUploadStream(name, { - contentType: 'image/jpeg', - metadata: { - originalId - } - }); - writeStream.once('finish', resolve); - writeStream.on('error', reject); - readable.pipe(writeStream); - })); + }); + } +} async function deleteOldFile(user: IRemoteUser) { const oldFile = await DriveFile.findOne({ @@ -81,9 +100,10 @@ export default async function( comment: string = null, folderId: mongodb.ObjectID = null, force: boolean = false, - metaOnly: boolean = false, + isLink: boolean = false, url: string = null, - uri: string = null + uri: string = null, + sensitive = false ): Promise<IDriveFile> { // Calc md5 hash const calcHash = new Promise<string>((res, rej) => { @@ -148,7 +168,7 @@ export default async function( } //#region Check drive usage - if (!metaOnly) { + if (!isLink) { const usage = await DriveFile .aggregate([{ $match: { @@ -174,8 +194,10 @@ export default async function( log(`drive usage is ${usage}`); + const driveCapacity = 1024 * 1024 * (isLocalUser(user) ? config.localDriveCapacityMb : config.remoteDriveCapacityMb); + // If usage limit exceeded - if (usage + size > user.driveCapacity) { + if (usage + size > driveCapacity) { if (isLocalUser(user)) { throw 'no-free-space'; } else { @@ -205,44 +227,41 @@ export default async function( let propPromises: Array<Promise<void>> = []; - const isImage = ['image/jpeg', 'image/gif', 'image/png'].includes(mime); + const isImage = ['image/jpeg', 'image/gif', 'image/png', 'image/webp'].includes(mime); if (isImage) { + const img = sharp(path); + // Calc width and height const calcWh = async () => { log('calculate image width and height...'); // Calculate width and height - const g = gm(fs.createReadStream(path), name); - const size = await prominence(g).size(); + const meta = await img.metadata(); - log(`image width and height is calculated: ${size.width}, ${size.height}`); + log(`image width and height is calculated: ${meta.width}, ${meta.height}`); - properties['width'] = size.width; - properties['height'] = size.height; + properties['width'] = meta.width; + properties['height'] = meta.height; }; // Calc average color const calcAvg = async () => { log('calculate average color...'); - const info = await prominence(gm(fs.createReadStream(path), name)).identify(); - const isTransparent = info ? info['Channel depth'].Alpha != null : false; + try { + const info = await (img as any).stats(); - const buffer = await prominence(gm(fs.createReadStream(path), name) - .setFormat('ppm') - .resize(1, 1)) // 1pxのサイズに縮小して平均色を取得するというハック - .toBuffer(); + const r = Math.round(info.channels[0].mean); + const g = Math.round(info.channels[1].mean); + const b = Math.round(info.channels[2].mean); - const r = buffer.readUInt8(buffer.length - 3); - const g = buffer.readUInt8(buffer.length - 2); - const b = buffer.readUInt8(buffer.length - 1); + log(`average color is calculated: ${r}, ${g}, ${b}`); - log(`average color is calculated: ${r}, ${g}, ${b}`); + const value = info.isOpaque ? [r, g, b] : [r, g, b, 255]; - const value = isTransparent ? [r, g, b, 255] : [r, g, b]; - - properties['avgColor'] = value; + properties['avgColor'] = value; + } catch (e) { } }; propPromises = [calcWh(), calcAvg()]; @@ -258,18 +277,24 @@ export default async function( folderId: folder !== null ? folder._id : null, comment: comment, properties: properties, - isMetaOnly: metaOnly + withoutChunks: isLink, + isRemote: isLink, + isSensitive: sensitive } as IMetadata; if (url !== null) { - metadata.url = url; + metadata.src = url; + + if (isLink) { + metadata.url = url; + } } if (uri !== null) { metadata.uri = uri; } - const driveFile = metaOnly + const driveFile = isLink ? await DriveFile.insert({ length: 0, uploadDate: new Date(), @@ -278,26 +303,17 @@ export default async function( metadata: metadata, contentType: mime }) - : await (writeChunks(detectedName, fs.createReadStream(path), mime, metadata) as Promise<IDriveFile>); + : await (save(fs.createReadStream(path), detectedName, mime, hash, size, metadata)); log(`drive file has been created ${driveFile._id}`); pack(driveFile).then(packedFile => { // Publish drive_file_created event - event(user._id, 'drive_file_created', packedFile); + publishUserStream(user._id, 'drive_file_created', packedFile); publishDriveStream(user._id, 'file_created', packedFile); }); - if (!metaOnly) { - try { - const thumb = await genThumbnail(driveFile); - if (thumb) { - await writeThumbnailChunks(detectedName, thumb, driveFile._id); - } - } catch (e) { - // noop - } - } + // TODO: サムネイル生成 return driveFile; } diff --git a/src/services/drive/delete-file.ts b/src/services/drive/delete-file.ts index 4ac60439b7..5494023f46 100644 --- a/src/services/drive/delete-file.ts +++ b/src/services/drive/delete-file.ts @@ -1,7 +1,15 @@ +import * as Minio from 'minio'; import DriveFile, { DriveFileChunk, IDriveFile } from '../../models/drive-file'; import DriveFileThumbnail, { DriveFileThumbnailChunk } from '../../models/drive-file-thumbnail'; +import config from '../../config'; export default async function(file: IDriveFile, isExpired = false) { + if (file.metadata.storage == 'minio') { + const minio = new Minio.Client(config.drive.config); + const obj = `${config.drive.prefix}/${file.metadata.storageProps.id}`; + await minio.removeObject(config.drive.bucket, obj); + } + // チャンクをすべて削除 await DriveFileChunk.remove({ files_id: file._id diff --git a/src/services/drive/upload-from-url.ts b/src/services/drive/upload-from-url.ts index 73d9b1123a..4e297d3bb1 100644 --- a/src/services/drive/upload-from-url.ts +++ b/src/services/drive/upload-from-url.ts @@ -13,7 +13,7 @@ import * as mongodb from 'mongodb'; const log = debug('misskey:drive:upload-from-url'); -export default async (url: string, user: IUser, folderId: mongodb.ObjectID = null, uri: string = null): Promise<IDriveFile> => { +export default async (url: string, user: IUser, folderId: mongodb.ObjectID = null, uri: string = null, sensitive = false): Promise<IDriveFile> => { log(`REQUESTED: ${url}`); let name = URL.parse(url).pathname.split('/').pop(); @@ -48,8 +48,8 @@ export default async (url: string, user: IUser, folderId: mongodb.ObjectID = nul let error; try { - driveFile = await create(user, path, name, null, folderId, false, config.preventCacheRemoteFiles, url, uri); - log(`created: ${driveFile._id}`); + driveFile = await create(user, path, name, null, folderId, false, config.preventCacheRemoteFiles, url, uri, sensitive); + log(`got: ${driveFile._id}`); } catch (e) { error = e; log(`failed: ${e}`); diff --git a/src/services/following/create.ts b/src/services/following/create.ts index 03db72c332..bd39b8e183 100644 --- a/src/services/following/create.ts +++ b/src/services/following/create.ts @@ -2,8 +2,8 @@ import User, { isLocalUser, isRemoteUser, pack as packUser, IUser } from '../../ import Following from '../../models/following'; import FollowingLog from '../../models/following-log'; import FollowedLog from '../../models/followed-log'; -import event from '../../publishers/stream'; -import notify from '../../publishers/notify'; +import { publishUserStream } from '../../stream'; +import notify from '../../notify'; import pack from '../../remote/activitypub/renderer'; import renderFollow from '../../remote/activitypub/renderer/follow'; import renderAccept from '../../remote/activitypub/renderer/accept'; @@ -22,11 +22,13 @@ export default async function(follower: IUser, followee: IUser) { // 非正規化 _follower: { host: follower.host, - inbox: isRemoteUser(follower) ? follower.inbox : undefined + inbox: isRemoteUser(follower) ? follower.inbox : undefined, + sharedInbox: isRemoteUser(follower) ? follower.sharedInbox : undefined }, _followee: { host: followee.host, - inbox: isRemoteUser(followee) ? followee.inbox : undefined + inbox: isRemoteUser(followee) ? followee.inbox : undefined, + sharedInbox: isRemoteUser(followee) ? followee.sharedInbox : undefined } }); @@ -59,12 +61,12 @@ export default async function(follower: IUser, followee: IUser) { // Publish follow event if (isLocalUser(follower)) { - packUser(followee, follower).then(packed => event(follower._id, 'follow', packed)); + packUser(followee, follower).then(packed => publishUserStream(follower._id, 'follow', packed)); } // Publish followed event if (isLocalUser(followee)) { - packUser(follower, followee).then(packed => event(followee._id, 'followed', packed)), + packUser(follower, followee).then(packed => publishUserStream(followee._id, 'followed', packed)), // 通知を作成 notify(followee._id, follower._id, 'follow'); diff --git a/src/services/following/delete.ts b/src/services/following/delete.ts index 4fc5d42476..8a9f739bd4 100644 --- a/src/services/following/delete.ts +++ b/src/services/following/delete.ts @@ -2,7 +2,7 @@ import User, { isLocalUser, isRemoteUser, pack as packUser, IUser } from '../../ import Following from '../../models/following'; import FollowingLog from '../../models/following-log'; import FollowedLog from '../../models/followed-log'; -import event from '../../publishers/stream'; +import { publishUserStream } from '../../stream'; import pack from '../../remote/activitypub/renderer'; import renderFollow from '../../remote/activitypub/renderer/follow'; import renderUndo from '../../remote/activitypub/renderer/undo'; @@ -52,7 +52,7 @@ export default async function(follower: IUser, followee: IUser) { // Publish unfollow event if (isLocalUser(follower)) { - packUser(followee, follower).then(packed => event(follower._id, 'unfollow', packed)); + packUser(followee, follower).then(packed => publishUserStream(follower._id, 'unfollow', packed)); } if (isLocalUser(follower) && isRemoteUser(followee)) { diff --git a/src/services/following/requests/accept.ts b/src/services/following/requests/accept.ts index 2eaccbbd36..bf8ed99e13 100644 --- a/src/services/following/requests/accept.ts +++ b/src/services/following/requests/accept.ts @@ -7,7 +7,7 @@ import { deliver } from '../../../queue'; import Following from '../../../models/following'; import FollowingLog from '../../../models/following-log'; import FollowedLog from '../../../models/followed-log'; -import event from '../../../publishers/stream'; +import { publishUserStream } from '../../../stream'; export default async function(followee: IUser, follower: IUser) { const following = await Following.insert({ @@ -18,11 +18,13 @@ export default async function(followee: IUser, follower: IUser) { // 非正規化 _follower: { host: follower.host, - inbox: isRemoteUser(follower) ? follower.inbox : undefined + inbox: isRemoteUser(follower) ? follower.inbox : undefined, + sharedInbox: isRemoteUser(follower) ? follower.sharedInbox : undefined }, _followee: { host: followee.host, - inbox: isRemoteUser(followee) ? followee.inbox : undefined + inbox: isRemoteUser(followee) ? followee.inbox : undefined, + sharedInbox: isRemoteUser(followee) ? followee.sharedInbox : undefined } }); @@ -64,7 +66,13 @@ export default async function(followee: IUser, follower: IUser) { }); //#endregion + await User.update({ _id: followee._id }, { + $inc: { + pendingReceivedFollowRequestsCount: -1 + } + }); + packUser(followee, followee, { detail: true - }).then(packed => event(followee._id, 'meUpdated', packed)); + }).then(packed => publishUserStream(followee._id, 'meUpdated', packed)); } diff --git a/src/services/following/requests/cancel.ts b/src/services/following/requests/cancel.ts index 7e9dc5630f..b0b574da58 100644 --- a/src/services/following/requests/cancel.ts +++ b/src/services/following/requests/cancel.ts @@ -4,7 +4,7 @@ import pack from '../../../remote/activitypub/renderer'; import renderFollow from '../../../remote/activitypub/renderer/follow'; import renderUndo from '../../../remote/activitypub/renderer/undo'; import { deliver } from '../../../queue'; -import event from '../../../publishers/stream'; +import { publishUserStream } from '../../../stream'; export default async function(followee: IUser, follower: IUser) { if (isRemoteUser(followee)) { @@ -25,5 +25,5 @@ export default async function(followee: IUser, follower: IUser) { packUser(followee, followee, { detail: true - }).then(packed => event(followee._id, 'meUpdated', packed)); + }).then(packed => publishUserStream(followee._id, 'meUpdated', packed)); } diff --git a/src/services/following/requests/create.ts b/src/services/following/requests/create.ts index fea82b57d8..4c7c90cc08 100644 --- a/src/services/following/requests/create.ts +++ b/src/services/following/requests/create.ts @@ -1,6 +1,6 @@ import User, { isLocalUser, isRemoteUser, pack as packUser, IUser } from '../../../models/user'; -import event from '../../../publishers/stream'; -import notify from '../../../publishers/notify'; +import { publishUserStream } from '../../../stream'; +import notify from '../../../notify'; import pack from '../../../remote/activitypub/renderer'; import renderFollow from '../../../remote/activitypub/renderer/follow'; import { deliver } from '../../../queue'; @@ -17,11 +17,13 @@ export default async function(follower: IUser, followee: IUser) { // 非正規化 _follower: { host: follower.host, - inbox: isRemoteUser(follower) ? follower.inbox : undefined + inbox: isRemoteUser(follower) ? follower.inbox : undefined, + sharedInbox: isRemoteUser(follower) ? follower.sharedInbox : undefined }, _followee: { host: followee.host, - inbox: isRemoteUser(followee) ? followee.inbox : undefined + inbox: isRemoteUser(followee) ? followee.inbox : undefined, + sharedInbox: isRemoteUser(followee) ? followee.sharedInbox : undefined } }); @@ -33,11 +35,11 @@ export default async function(follower: IUser, followee: IUser) { // Publish receiveRequest event if (isLocalUser(followee)) { - packUser(follower, followee).then(packed => event(followee._id, 'receiveFollowRequest', packed)); + packUser(follower, followee).then(packed => publishUserStream(followee._id, 'receiveFollowRequest', packed)); packUser(followee, followee, { detail: true - }).then(packed => event(followee._id, 'meUpdated', packed)); + }).then(packed => publishUserStream(followee._id, 'meUpdated', packed)); // 通知を作成 notify(followee._id, follower._id, 'receiveFollowRequest'); diff --git a/src/services/note/create.ts b/src/services/note/create.ts index a793c8e580..6e644ef1d3 100644 --- a/src/services/note/create.ts +++ b/src/services/note/create.ts @@ -1,6 +1,7 @@ +import es from '../../db/elasticsearch'; import Note, { pack, INote } from '../../models/note'; import User, { isLocalUser, IUser, isRemoteUser, IRemoteUser, ILocalUser } from '../../models/user'; -import stream, { publishLocalTimelineStream, publishGlobalTimelineStream, publishUserListStream } from '../../publishers/stream'; +import { publishUserStream, publishLocalTimelineStream, publishHybridTimelineStream, publishGlobalTimelineStream, publishUserListStream } from '../../stream'; import Following from '../../models/following'; import { deliver } from '../../queue'; import renderNote from '../../remote/activitypub/renderer/note'; @@ -8,52 +9,76 @@ import renderCreate from '../../remote/activitypub/renderer/create'; import renderAnnounce from '../../remote/activitypub/renderer/announce'; import packAp from '../../remote/activitypub/renderer'; import { IDriveFile } from '../../models/drive-file'; -import notify from '../../publishers/notify'; +import notify from '../../notify'; import NoteWatching from '../../models/note-watching'; import watch from './watch'; import Mute from '../../models/mute'; -import event from '../../publishers/stream'; import parse from '../../mfm/parse'; import { IApp } from '../../models/app'; import UserList from '../../models/user-list'; import resolveUser from '../../remote/resolve-user'; import Meta from '../../models/meta'; +import config from '../../config'; +import registerHashtag from '../register-hashtag'; +import isQuote from '../../misc/is-quote'; +import { TextElementMention } from '../../mfm/parse/elements/mention'; +import { TextElementHashtag } from '../../mfm/parse/elements/hashtag'; -type Type = 'reply' | 'renote' | 'quote' | 'mention'; +type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; -/** - * 通知を担当 - */ class NotificationManager { private notifier: IUser; private note: INote; + private queue: Array<{ + target: ILocalUser['_id']; + reason: NotificationType; + }>; constructor(notifier: IUser, note: INote) { this.notifier = notifier; this.note = note; + this.queue = []; } - public async push(notifiee: ILocalUser['_id'], type: Type) { + public push(notifiee: ILocalUser['_id'], reason: NotificationType) { // 自分自身へは通知しない if (this.notifier._id.equals(notifiee)) return; - // ミュート情報を取得 - const mentioneeMutes = await Mute.find({ - muterId: notifiee - }); + const exist = this.queue.find(x => x.target.equals(notifiee)); - const mentioneesMutedUserIds = mentioneeMutes.map(m => m.muteeId.toString()); - - // 通知される側のユーザーが通知する側のユーザーをミュートしていない限りは通知する - if (!mentioneesMutedUserIds.includes(this.notifier._id.toString())) { - notify(notifiee, this.notifier._id, type, { - noteId: this.note._id + if (exist) { + // 「メンションされているかつ返信されている」場合は、メンションとしての通知ではなく返信としての通知にする + if (reason != 'mention') { + exist.reason = reason; + } + } else { + this.queue.push({ + reason: reason, + target: notifiee }); } } + + public deliver() { + this.queue.forEach(async x => { + // ミュート情報を取得 + const mentioneeMutes = await Mute.find({ + muterId: x.target + }); + + const mentioneesMutedUserIds = mentioneeMutes.map(m => m.muteeId.toString()); + + // 通知される側のユーザーが通知する側のユーザーをミュートしていない限りは通知する + if (!mentioneesMutedUserIds.includes(this.notifier._id.toString())) { + notify(x.target, this.notifier._id, x.reason, { + noteId: this.note._id + }); + } + }); + } } -export default async (user: IUser, data: { +type Option = { createdAt?: Date; text?: string; reply?: INote; @@ -62,43 +87,197 @@ export default async (user: IUser, data: { geo?: any; poll?: any; viaMobile?: boolean; - tags?: string[]; cw?: string; visibility?: string; visibleUsers?: IUser[]; uri?: string; app?: IApp; -}, silent = false) => new Promise<INote>(async (res, rej) => { +}; + +export default async (user: IUser, data: Option, silent = false) => new Promise<INote>(async (res, rej) => { if (data.createdAt == null) data.createdAt = new Date(); if (data.visibility == null) data.visibility = 'public'; if (data.viaMobile == null) data.viaMobile = false; - let tags = data.tags || []; - - let tokens: any[] = null; - - if (data.text) { - // Analyze - tokens = parse(data.text); - - // Extract hashtags - const hashtags = tokens - .filter(t => t.type == 'hashtag') - .map(t => t.hashtag); - - hashtags.forEach(tag => { - if (tags.indexOf(tag) == -1) { - tags.push(tag); - } - }); - } - - tags = tags.filter(tag => tag.length <= 100); - if (data.visibleUsers) { data.visibleUsers = data.visibleUsers.filter(x => x != null); } + // Parse MFM + const tokens = data.text ? parse(data.text) : []; + + const tags = extractHashtags(tokens); + + const mentionedUsers = await extractMentionedUsers(tokens); + + const note = await insertNote(user, data, tokens, tags, mentionedUsers); + + res(note); + + if (note == null) { + return; + } + + // ハッシュタグ登録 + tags.map(tag => registerHashtag(user, tag)); + + // Increment notes count + incNotesCount(user); + + // Increment notes count (user) + incNotesCountOfUser(user); + + if (data.reply) { + saveReply(data.reply, note); + } + + if (data.renote) { + incRenoteCount(data.renote); + } + + if (isQuote(note)) { + saveQuote(data.renote, note); + } + + // Pack the note + const noteObj = await pack(note); + + const nm = new NotificationManager(user, note); + const nmRelatedPromises = []; + + createMentionedEvents(mentionedUsers, noteObj, nm); + + const noteActivity = await renderActivity(data, note); + + if (isLocalUser(user)) { + deliverNoteToMentionedRemoteUsers(mentionedUsers, user, noteActivity); + } + + // If has in reply to note + if (data.reply) { + // Fetch watchers + nmRelatedPromises.push(notifyToWatchersOfReplyee(data.reply, user, nm)); + + // この投稿をWatchする + if (isLocalUser(user) && user.settings.autoWatch !== false) { + watch(user._id, data.reply); + } + + // 通知 + nm.push(data.reply.userId, 'reply'); + } + + // If it is renote + if (data.renote) { + // Notify + const type = data.text ? 'quote' : 'renote'; + nm.push(data.renote.userId, type); + + // Fetch watchers + nmRelatedPromises.push(notifyToWatchersOfRenotee(data.renote, user, nm, type)); + + // この投稿をWatchする + if (isLocalUser(user) && user.settings.autoWatch !== false) { + watch(user._id, data.renote); + } + + // If it is quote renote + if (data.text) { + // Add mention + nm.push(data.renote.userId, 'quote'); + } else { + // Publish event + if (!user._id.equals(data.renote.userId)) { + publishUserStream(data.renote.userId, 'renote', noteObj); + } + } + } + + if (!silent) { + publish(user, note, noteObj, data.reply, data.renote, data.visibleUsers, noteActivity); + } + + Promise.all(nmRelatedPromises).then(() => { + nm.deliver(); + }); + + // Register to search database + index(note); +}); + +async function renderActivity(data: Option, note: INote) { + const content = data.renote && data.text == null + ? renderAnnounce(data.renote.uri ? data.renote.uri : await renderNote(data.renote)) + : renderCreate(await renderNote(note)); + + return packAp(content); +} + +function incRenoteCount(renote: INote) { + Note.update({ _id: renote._id }, { + $inc: { + renoteCount: 1 + } + }); +} + +async function publish(user: IUser, note: INote, noteObj: any, reply: INote, renote: INote, visibleUsers: IUser[], noteActivity: any) { + if (isLocalUser(user)) { + // 投稿がリプライかつ投稿者がローカルユーザーかつリプライ先の投稿の投稿者がリモートユーザーなら配送 + if (reply && isRemoteUser(reply._user)) { + deliver(user, noteActivity, reply._user.inbox); + } + + // 投稿がRenoteかつ投稿者がローカルユーザーかつRenote元の投稿の投稿者がリモートユーザーなら配送 + if (renote && isRemoteUser(renote._user)) { + deliver(user, noteActivity, renote._user.inbox); + } + + if (['private', 'followers', 'specified'].includes(note.visibility)) { + // Publish event to myself's stream + publishUserStream(note.userId, 'note', await pack(note, user, { + detail: true + })); + } else { + // Publish event to myself's stream + publishUserStream(note.userId, 'note', noteObj); + + // Publish note to local and hybrid timeline stream + if (note.visibility != 'home') { + publishLocalTimelineStream(noteObj); + } + + if (note.visibility == 'public') { + publishHybridTimelineStream(null, noteObj); + } + } + } + + // Publish note to global timeline stream + if (note.visibility == 'public' && note.replyId == null) { + publishGlobalTimelineStream(noteObj); + } + + if (note.visibility == 'specified') { + visibleUsers.forEach(async (u) => { + const n = await pack(note, u, { + detail: true + }); + publishUserStream(u._id, 'note', n); + publishHybridTimelineStream(u._id, n); + }); + } + + if (['public', 'home', 'followers'].includes(note.visibility)) { + // フォロワーに配信 + publishToFollowers(note, noteObj, user, noteActivity); + } + + // リストに配信 + publishToUserLists(note, noteObj); +} + +async function insertNote(user: IUser, data: Option, tokens: ReturnType<typeof parse>, tags: string[], mentionedUsers: IUser[]) { const insert: any = { createdAt: data.createdAt, mediaIds: data.media ? data.media.map(file => file._id) : [], @@ -131,23 +310,175 @@ export default async (user: IUser, data: { if (data.uri != null) insert.uri = data.uri; + // Append mentions data + if (mentionedUsers.length > 0) { + insert.mentions = mentionedUsers.map(u => u._id); + insert.mentionedRemoteUsers = mentionedUsers.filter(u => isRemoteUser(u)).map(u => ({ + uri: (u as IRemoteUser).uri, + username: u.username, + host: u.host + })); + } + // 投稿を作成 - let note: INote; try { - note = await Note.insert(insert); + return await Note.insert(insert); } catch (e) { // duplicate key error if (e.code === 11000) { - return res(null); + return null; } console.error(e); - return rej('something happened'); + throw 'something happened'; } +} - res(note); +function extractHashtags(tokens: ReturnType<typeof parse>): string[] { + // Extract hashtags + const hashtags = tokens + .filter(t => t.type == 'hashtag') + .map(t => (t as TextElementHashtag).hashtag) + .filter(tag => tag.length <= 100); - //#region Increment notes count + return [...new Set(hashtags)]; +} + +function index(note: INote) { + if (note.text == null || config.elasticsearch == null) return; + + es.index({ + index: 'misskey', + type: 'note', + id: note._id.toString(), + body: { + text: note.text + } + }); +} + +async function notifyToWatchersOfRenotee(renote: INote, user: IUser, nm: NotificationManager, type: NotificationType) { + const watchers = await NoteWatching.find({ + noteId: renote._id, + userId: { $ne: user._id } + }, { + fields: { + userId: true + } + }); + + watchers.forEach(watcher => { + nm.push(watcher.userId, type); + }); +} + +async function notifyToWatchersOfReplyee(reply: INote, user: IUser, nm: NotificationManager) { + const watchers = await NoteWatching.find({ + noteId: reply._id, + userId: { $ne: user._id } + }, { + fields: { + userId: true + } + }); + + watchers.forEach(watcher => { + nm.push(watcher.userId, 'reply'); + }); +} + +async function publishToUserLists(note: INote, noteObj: any) { + const lists = await UserList.find({ + userIds: note.userId + }); + + lists.forEach(list => { + publishUserListStream(list._id, 'note', noteObj); + }); +} + +async function publishToFollowers(note: INote, noteObj: any, user: IUser, noteActivity: any) { + const followers = await Following.find({ + followeeId: note.userId + }); + + const queue: string[] = []; + + followers.map(following => { + const follower = following._follower; + + if (isLocalUser(follower)) { + // ストーキングしていない場合 + if (!following.stalk) { + // この投稿が返信ならスキップ + if (note.replyId && !note._reply.userId.equals(following.followerId) && !note._reply.userId.equals(note.userId)) + return; + } + + // Publish event to followers stream + publishUserStream(following.followerId, 'note', noteObj); + + if (isRemoteUser(user) || note.visibility != 'public') { + publishHybridTimelineStream(following.followerId, noteObj); + } + } else { + // フォロワーがリモートユーザーかつ投稿者がローカルユーザーなら投稿を配信 + if (isLocalUser(user)) { + const inbox = follower.sharedInbox || follower.inbox; + if (!queue.includes(inbox)) queue.push(inbox); + } + } + }); + + queue.forEach(inbox => { + deliver(user as any, noteActivity, inbox); + }); +} + +function deliverNoteToMentionedRemoteUsers(mentionedUsers: IUser[], user: ILocalUser, noteActivity: any) { + mentionedUsers.filter(u => isRemoteUser(u)).forEach(async (u) => { + deliver(user, noteActivity, (u as IRemoteUser).inbox); + }); +} + +function createMentionedEvents(mentionedUsers: IUser[], noteObj: any, nm: NotificationManager) { + mentionedUsers.filter(u => isLocalUser(u)).forEach(async (u) => { + publishUserStream(u._id, 'mention', noteObj); + + // Create notification + nm.push(u._id, 'mention'); + }); +} + +function saveQuote(renote: INote, note: INote) { + Note.update({ _id: renote._id }, { + $push: { + _quoteIds: note._id + }, + + }); +} + +function saveReply(reply: INote, note: INote) { + Note.update({ _id: reply._id }, { + $push: { + _replyIds: note._id + }, + $inc: { + repliesCount: 1 + } + }); +} + +function incNotesCountOfUser(user: IUser) { + User.update({ _id: user._id }, { + $inc: { + notesCount: 1 + } + }); +} + +function incNotesCount(user: IUser) { if (isLocalUser(user)) { Meta.update({}, { $inc: { @@ -162,269 +493,25 @@ export default async (user: IUser, data: { } }, { upsert: true }); } - //#endregion +} - // Increment notes count (user) - User.update({ _id: user._id }, { - $inc: { - notesCount: 1 - } - }); +async function extractMentionedUsers(tokens: ReturnType<typeof parse>): Promise<IUser[]> { + if (tokens == null) return []; - if (data.reply) { - Note.update({ _id: data.reply._id }, { - $push: { - _replyIds: note._id - } - }); - } + const mentionTokens = [...new Set( + tokens + .filter(t => t.type == 'mention') as TextElementMention[] + )]; - const isQuote = data.renote && (data.text || data.poll || data.media); - - if (isQuote) { - Note.update({ _id: data.renote._id }, { - $push: { - _quoteIds: note._id - } - }); - } - - // Serialize - const noteObj = await pack(note); - - const nm = new NotificationManager(user, note); - - const render = async () => { - const content = data.renote && data.text == null - ? renderAnnounce(data.renote.uri ? data.renote.uri : await renderNote(data.renote)) - : renderCreate(await renderNote(note)); - return packAp(content); - }; - - //#region メンション - if (data.text) { - // TODO: Drop dupulicates - const mentionTokens = tokens - .filter(t => t.type == 'mention'); - - // TODO: Drop dupulicates - const mentionedUsers = (await Promise.all(mentionTokens.map(async m => { + const mentionedUsers = [...new Set( + (await Promise.all(mentionTokens.map(async m => { try { return await resolveUser(m.username, m.host); } catch (e) { return null; } - }))).filter(x => x != null); + }))).filter(x => x != null) + )]; - // Append mentions data - if (mentionedUsers.length > 0) { - const set = { - mentions: mentionedUsers.map(u => u._id), - mentionedRemoteUsers: mentionedUsers.filter(u => isRemoteUser(u)).map(u => ({ - uri: (u as IRemoteUser).uri, - username: u.username, - host: u.host - })) - }; - - Note.update({ _id: note._id }, { - $set: set - }); - - Object.assign(note, set); - } - - mentionedUsers.filter(u => isLocalUser(u)).forEach(async u => { - event(u, 'mention', noteObj); - - // 既に言及されたユーザーに対する返信や引用renoteの場合も無視 - if (data.reply && data.reply.userId.equals(u._id)) return; - if (data.renote && data.renote.userId.equals(u._id)) return; - - // Create notification - nm.push(u._id, 'mention'); - }); - - if (isLocalUser(user)) { - mentionedUsers.filter(u => isRemoteUser(u)).forEach(async u => { - deliver(user, await render(), (u as IRemoteUser).inbox); - }); - } - } - //#endregion - - if (!silent) { - if (isLocalUser(user)) { - if (note.visibility == 'private' || note.visibility == 'followers' || note.visibility == 'specified') { - // Publish event to myself's stream - stream(note.userId, 'note', await pack(note, user, { - detail: true - })); - } else { - // Publish event to myself's stream - stream(note.userId, 'note', noteObj); - - // Publish note to local timeline stream - if (note.visibility != 'home') { - publishLocalTimelineStream(noteObj); - } - } - } - - // Publish note to global timeline stream - if (note.visibility == 'public' && note.replyId == null) { - publishGlobalTimelineStream(noteObj); - } - - if (note.visibility == 'specified') { - data.visibleUsers.forEach(async u => { - stream(u._id, 'note', await pack(note, u, { - detail: true - })); - }); - } - - if (note.visibility == 'public' || note.visibility == 'home' || note.visibility == 'followers') { - // フォロワーに配信 - Following.find({ - followeeId: note.userId - }).then(followers => { - followers.map(async following => { - const follower = following._follower; - - if (isLocalUser(follower)) { - // ストーキングしていない場合 - if (!following.stalk) { - // この投稿が返信ならスキップ - if (note.replyId && !note._reply.userId.equals(following.followerId) && !note._reply.userId.equals(note.userId)) return; - } - - // Publish event to followers stream - stream(following.followerId, 'note', noteObj); - } else { - //#region AP配送 - // フォロワーがリモートユーザーかつ投稿者がローカルユーザーなら投稿を配信 - if (isLocalUser(user)) { - deliver(user, await render(), follower.inbox); - } - //#endergion - } - }); - }); - } - - // リストに配信 - UserList.find({ - userIds: note.userId - }).then(lists => { - lists.forEach(list => { - publishUserListStream(list._id, 'note', noteObj); - }); - }); - } - - //#region リプライとAnnounceのAP配送 - - // 投稿がリプライかつ投稿者がローカルユーザーかつリプライ先の投稿の投稿者がリモートユーザーなら配送 - if (data.reply && isLocalUser(user) && isRemoteUser(data.reply._user)) { - deliver(user, await render(), data.reply._user.inbox); - } - - // 投稿がRenoteかつ投稿者がローカルユーザーかつRenote元の投稿の投稿者がリモートユーザーなら配送 - if (data.renote && isLocalUser(user) && isRemoteUser(data.renote._user)) { - deliver(user, await render(), data.renote._user.inbox); - } - //#endergion - - // If has in reply to note - if (data.reply) { - // Increment replies count - Note.update({ _id: data.reply._id }, { - $inc: { - repliesCount: 1 - } - }); - - // Fetch watchers - NoteWatching.find({ - noteId: data.reply._id, - userId: { $ne: user._id }, - // 削除されたドキュメントは除く - deletedAt: { $exists: false } - }, { - fields: { - userId: true - } - }).then(watchers => { - watchers.forEach(watcher => { - nm.push(watcher.userId, 'reply'); - }); - }); - - // この投稿をWatchする - if (isLocalUser(user) && user.settings.autoWatch !== false) { - watch(user._id, data.reply); - } - - // (自分自身へのリプライでない限りは)通知を作成 - nm.push(data.reply.userId, 'reply'); - } - - // If it is renote - if (data.renote) { - // Notify - const type = data.text ? 'quote' : 'renote'; - nm.push(data.renote.userId, type); - - // Fetch watchers - NoteWatching.find({ - noteId: data.renote._id, - userId: { $ne: user._id } - }, { - fields: { - userId: true - } - }).then(watchers => { - watchers.forEach(watcher => { - nm.push(watcher.userId, type); - }); - }); - - // この投稿をWatchする - if (isLocalUser(user) && user.settings.autoWatch !== false) { - watch(user._id, data.renote); - } - - // If it is quote renote - if (data.text) { - // Add mention - nm.push(data.renote.userId, 'quote'); - } else { - // Publish event - if (!user._id.equals(data.renote.userId)) { - event(data.renote.userId, 'renote', noteObj); - } - } - - //#region TODO: これ重い - // 今までで同じ投稿をRenoteしているか - //const existRenote = await Note.findOne({ - // userId: user._id, - // renoteId: data.renote._id, - // _id: { - // $ne: note._id - // } - //}); - const existRenote: INote | null = null; - //#endregion - - if (!existRenote) { - // Update renoteee status - Note.update({ _id: data.renote._id }, { - $inc: { - renoteCount: 1 - } - }); - } - } -}); + return mentionedUsers; +} diff --git a/src/services/note/delete.ts b/src/services/note/delete.ts index 3e928303d2..7f245958b0 100644 --- a/src/services/note/delete.ts +++ b/src/services/note/delete.ts @@ -1,6 +1,6 @@ import Note, { INote } from '../../models/note'; import { IUser, isLocalUser } from '../../models/user'; -import { publishNoteStream } from '../../publishers/stream'; +import { publishNoteStream } from '../../stream'; import renderDelete from '../../remote/activitypub/renderer/delete'; import pack from '../../remote/activitypub/renderer'; import { deliver } from '../../queue'; @@ -22,7 +22,8 @@ export default async function(user: IUser, note: INote) { text: null, tags: [], mediaIds: [], - poll: null + poll: null, + geo: null } }); diff --git a/src/services/note/reaction/create.ts b/src/services/note/reaction/create.ts index b3235e94dc..5b6267b0dd 100644 --- a/src/services/note/reaction/create.ts +++ b/src/services/note/reaction/create.ts @@ -1,8 +1,8 @@ import { IUser, isLocalUser, isRemoteUser } from '../../../models/user'; import Note, { INote } from '../../../models/note'; import NoteReaction from '../../../models/note-reaction'; -import { publishNoteStream } from '../../../publishers/stream'; -import notify from '../../../publishers/notify'; +import { publishNoteStream } from '../../../stream'; +import notify from '../../../notify'; import NoteWatching from '../../../models/note-watching'; import watch from '../watch'; import renderLike from '../../../remote/activitypub/renderer/like'; diff --git a/src/services/note/watch.ts b/src/services/note/watch.ts index 28fb7a32c2..aad53610d8 100644 --- a/src/services/note/watch.ts +++ b/src/services/note/watch.ts @@ -10,8 +10,7 @@ export default async (me: mongodb.ObjectID, note: object) => { // if watching now const exist = await Watching.findOne({ noteId: (note as any)._id, - userId: me, - deletedAt: { $exists: false } + userId: me }); if (exist !== null) { diff --git a/src/services/register-hashtag.ts b/src/services/register-hashtag.ts new file mode 100644 index 0000000000..ca6b74783b --- /dev/null +++ b/src/services/register-hashtag.ts @@ -0,0 +1,28 @@ +import { IUser } from '../models/user'; +import Hashtag from '../models/hashtag'; + +export default async function(user: IUser, tag: string) { + tag = tag.toLowerCase(); + + const index = await Hashtag.findOne({ tag }); + + if (index != null) { + // 自分が初めてこのタグを使ったなら + if (!index.mentionedUserIds.some(id => id.equals(user._id))) { + Hashtag.update({ tag }, { + $push: { + mentionedUserIds: user._id + }, + $inc: { + mentionedUserIdsCount: 1 + } + }); + } + } else { + Hashtag.insert({ + tag, + mentionedUserIds: [user._id], + mentionedUserIdsCount: 1 + }); + } +} diff --git a/src/stream.ts b/src/stream.ts new file mode 100644 index 0000000000..be7a8c4ba1 --- /dev/null +++ b/src/stream.ts @@ -0,0 +1,58 @@ +import * as mongo from 'mongodb'; +import Xev from 'xev'; + +const ev = new Xev(); + +type ID = string | mongo.ObjectID; + +function publish(channel: string, type: string, value?: any): void { + const message = type == null ? value : value == null ? + { type: type } : + { type: type, body: value }; + + ev.emit(channel, message); +} + +export function publishUserStream(userId: ID, type: string, value?: any): void { + publish(`user-stream:${userId}`, type, typeof value === 'undefined' ? null : value); +} + +export function publishDriveStream(userId: ID, type: string, value?: any): void { + publish(`drive-stream:${userId}`, type, typeof value === 'undefined' ? null : value); +} + +export function publishNoteStream(noteId: ID, type: string): void { + publish(`note-stream:${noteId}`, null, noteId); +} + +export function publishUserListStream(listId: ID, type: string, value?: any): void { + publish(`user-list-stream:${listId}`, type, typeof value === 'undefined' ? null : value); +} + +export function publishMessagingStream(userId: ID, otherpartyId: ID, type: string, value?: any): void { + publish(`messaging-stream:${userId}-${otherpartyId}`, type, typeof value === 'undefined' ? null : value); +} + +export function publishMessagingIndexStream(userId: ID, type: string, value?: any): void { + publish(`messaging-index-stream:${userId}`, type, typeof value === 'undefined' ? null : value); +} + +export function publishReversiStream(userId: ID, type: string, value?: any): void { + publish(`reversi-stream:${userId}`, type, typeof value === 'undefined' ? null : value); +} + +export function publishReversiGameStream(gameId: ID, type: string, value?: any): void { + publish(`reversi-game-stream:${gameId}`, type, typeof value === 'undefined' ? null : value); +} + +export function publishLocalTimelineStream(note: any): void { + publish('local-timeline', null, note); +} + +export function publishHybridTimelineStream(userId: ID, note: any): void { + publish(userId ? `hybrid-timeline:${userId}` : 'hybrid-timeline', null, note); +} + +export function publishGlobalTimelineStream(note: any): void { + publish('global-timeline', null, note); +} diff --git a/src/utils/cli/indicator.ts b/src/utils/cli/indicator.ts deleted file mode 100644 index 3e23f9b274..0000000000 --- a/src/utils/cli/indicator.ts +++ /dev/null @@ -1,35 +0,0 @@ -import * as readline from 'readline'; - -/** - * Indicator - */ -export default class { - private clock: NodeJS.Timer; - - constructor(text: string) { - let i = 0; // Dots counter - - draw(); - this.clock = setInterval(draw, 300); - - function draw(): void { - cll(); - i = (i + 1) % 4; - const dots = new Array(i + 1).join('.'); - process.stdout.write(text + dots); // Write text - } - } - - public end(): void { - clearInterval(this.clock); - cll(); - } -} - -/** - * Clear current line - */ -function cll(): void { - readline.clearLine(process.stdout, 0); // Clear current text - readline.cursorTo(process.stdout, 0, null); // Move cursor to the head of line -} diff --git a/src/utils/logger.ts b/src/utils/logger.ts deleted file mode 100644 index fae1042c39..0000000000 --- a/src/utils/logger.ts +++ /dev/null @@ -1,53 +0,0 @@ -import chalk, { Chalk } from 'chalk'; - -export type LogLevel = 'Error' | 'Warn' | 'Info'; - -function toLevelColor(level: LogLevel): Chalk { - switch (level) { - case 'Error': return chalk.red; - case 'Warn': return chalk.yellow; - case 'Info': return chalk.blue; - } -} - -export default class Logger { - private domain: string; - - constructor(domain: string) { - this.domain = domain; - } - - public static log(level: LogLevel, message: string): void { - const color = toLevelColor(level); - const time = (new Date()).toLocaleTimeString('ja-JP'); - console.log(`[${time} ${color.bold(level.toUpperCase())}]: ${message}`); - } - - public static error(message: string): void { - Logger.log('Error', message); - } - - public static warn(message: string): void { - Logger.log('Warn', message); - } - - public static info(message: string): void { - Logger.log('Info', message); - } - - public log(level: LogLevel, message: string): void { - Logger.log(level, `[${this.domain}] ${message}`); - } - - public error(message: string): void { - this.log('Error', message); - } - - public warn(message: string): void { - this.log('Warn', message); - } - - public info(message: string): void { - this.log('Info', message); - } -} diff --git a/swagger.js b/swagger.js deleted file mode 100644 index ebd7a356e9..0000000000 --- a/swagger.js +++ /dev/null @@ -1,229 +0,0 @@ -'use strict' - -const swaggerJSDoc = require('swagger-jsdoc'); -const fs = require('fs'); -const yaml = require('js-yaml'); - -const apiRoot = './src/api/endpoints'; -const files = [ - 'meta.js', - //app - 'app/show.js', - 'app/create.js', - 'app/name_id/available.js', - //auth - 'auth/accept.js', - //auth/session - 'auth/session/generate.js', - 'auth/session/show.js', - 'auth/session/userkey.js', -]; - -const defaultSwagger = { - "swagger": "2.0", - "info": { - "title": "Misskey API", - "version": "nighthike" - }, - "host": "api.misskey.xyz", - "schemes": [ - "https" - ], - "consumes": [ - "application/x-www-form-urlencoded" - ], - "produces": [ - "application/json" - ], - - "parameters": { - "AccessToken": { - "name": "i", - "description": "Access Token", - "in": "formData", - "required": true, - "type": "string" - }, - - "NativeToken": { - "name": "i", - "description": "Native Access Token", - "in": "formData", - "required": true, - "type": "string", - "pattern": "^\!.+" - } - }, - - "definitions": { - "Error": { - "type": "object", - "properties": { - "error": { - "type": "string", - "description": "Error message" - } - } - }, - "User": { - "type": "object", - "required": [ - "created_at", - "followers_count", - "following_count", - "id", - "liked_count", - "likes_count", - "name", - "posts_count", - "username" - ], - "properties": { - "avatar_id": { - "type": "string", - "description": "アバターに設定しているドライブのファイルのID" - }, - "avatarUrl": { - "type": "string", - "description": "アバターURL" - }, - "banner_id": { - "type": "string", - "description": "バナーに設定しているドライブのファイルのID" - }, - "bannerUrl": { - "type": "string", - "description": "バナーURL" - }, - "bio": { - "type": "string", - "description": "プロフィール" - }, - "birthday": { - "type": "string", - "format": "date", - "description": "誕生日" - }, - "created_at": { - "type": "string", - "format": "date-time", - "description": "アカウント作成日時" - }, - "drive_capacity": { - "type": "integer", - "description": "ドライブの最大容量" - }, - "followers_count": { - "type": "integer", - "description": "フォロワー数" - }, - "following_count": { - "type": "integer", - "description": "フォロー数" - }, - "id": { - "type": "string", - "description": "ユーザーID" - }, - "is_followed": { - "type": "boolean", - "description": "フォローされているか" - }, - "is_following": { - "type": "boolean", - "description": "フォローしているか" - }, - "liked_count": { - "type": "integer", - "description": "投稿にいいねされた数" - }, - "likes_count": { - "type": "integer", - "description": "投稿にいいねした数" - }, - "location": { - "type": "string", - "description": "場所" - }, - "name": { - "type": "string", - "description": "ニックネーム" - }, - "posts_count": { - "type": "integer", - "description": "投稿数" - }, - "username": { - "type": "string", - "description": "ユーザー名" - } - } - }, - "Application": { - "type": "object", - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "description": "アプリケーションの作成日時" - }, - "user_id": { - "type": "string", - "description": "アプリケーションを作成したユーザーのID" - }, - "name": { - "type": "string", - "description": "アプリケーションの名前" - }, - "name_id": { - "type": "string", - "description": "アプリケーションのユニークな名前" - }, - "description": { - "type": "string", - "description": "アプリケーションの説明" - }, - "permission": { - "type": "array", - "items": { - "type": "string" - }, - "description": "アプリケーションの持つ権限一覧" - }, - "callback_url": { - "type": "string", - "description": "コールバックURL" - }, - "id": { - "type": "string", - "description": "アプリケーションID" - }, - "icon_url": { - "type": "string", - "description": "アプリケーションのアイコンのURL" - } - } - } - }, - "securityDefinitions": {}, - "tags": [] -}; - -var options = { - swaggerDefinition: defaultSwagger, - apis: [] -}; -options.apis = files.map(c => {return `${apiRoot}/${c}`;}); - -if(fs.existsSync('.config/config.yml')){ - var config = yaml.safeLoad(fs.readFileSync('./.config/config.yml', 'utf8')); - options.swaggerDefinition.host = `api.${config.url.match(/\:\/\/(.+)$/)[1]}`; - options.swaggerDefinition.schemes = config.https.enable ? - ['https'] : - ['http']; -} - -var swaggerSpec = swaggerJSDoc(options); - -fs.writeFileSync('api-docs.json', JSON.stringify(swaggerSpec)); - diff --git a/test/resources/Lenna.jpg b/test/resources/Lenna.jpg index ad36bc1075..6b5b32281c 100644 Binary files a/test/resources/Lenna.jpg and b/test/resources/Lenna.jpg differ diff --git a/webpack.config.ts b/webpack.config.ts index 3c426ebb49..e60eb8347e 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -12,14 +12,14 @@ const WebpackOnBuildPlugin = require('on-build-webpack'); //const HardSourceWebpackPlugin = require('hard-source-webpack-plugin'); const ProgressBarPlugin = require('progress-bar-webpack-plugin'); -import I18nReplacer from './src/build/i18n'; +import I18nReplacer from './src/misc/i18n'; import { pattern as i18nPattern, replacement as i18nReplacement } from './webpack/i18n'; -import { pattern as faPattern, replacement as faReplacement } from './src/build/fa'; +import { pattern as faPattern, replacement as faReplacement } from './src/misc/fa'; const constants = require('./src/const.json'); import config from './src/config'; -import { licenseHtml } from './src/build/license'; +import { licenseHtml } from './src/misc/license'; -import locales from './locales'; +const locales = require('./locales'); const meta = require('./package.json'); const version = meta.clientVersion; const codename = meta.codename; @@ -72,7 +72,7 @@ const output = { //#region Define consts const consts = { - _RECAPTCHA_SITEKEY_: config.recaptcha.site_key, + _RECAPTCHA_SITEKEY_: config.recaptcha ? config.recaptcha.site_key : null, _SW_PUBLICKEY_: config.sw ? config.sw.public_key : null, _THEME_COLOR_: constants.themeColor, _COPYRIGHT_: constants.copyright, @@ -84,6 +84,8 @@ const consts = { _API_URL_: config.api_url, _WS_URL_: config.ws_url, _DEV_URL_: config.dev_url, + _REPOSITORY_URL_: config.maintainer.repository_url, + _FEEDBACK_URL_: config.maintainer.feedback_url, _LANG_: '%lang%', _LANGS_: Object.keys(locales).map(l => [l, locales[l].meta.lang]), _NAME_: config.name, diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index cb6a4a6221..0000000000 --- a/yarn.lock +++ /dev/null @@ -1,11948 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@fortawesome/fontawesome-common-types@^0.1.7": - version "0.1.7" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.1.7.tgz#4336c4b06d0b5608ff1215464b66fcf9f4795284" - -"@fortawesome/fontawesome-free-brands@5.0.13": - version "5.0.13" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-brands/-/fontawesome-free-brands-5.0.13.tgz#4d15ff4e1e862d5e4a4df3654f8e8acbd47e9c09" - dependencies: - "@fortawesome/fontawesome-common-types" "^0.1.7" - -"@fortawesome/fontawesome-free-regular@5.0.13": - version "5.0.13" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-regular/-/fontawesome-free-regular-5.0.13.tgz#eb78c30184e3f456a423a1dcfa0f682f7b50de4a" - dependencies: - "@fortawesome/fontawesome-common-types" "^0.1.7" - -"@fortawesome/fontawesome-free-solid@5.0.13": - version "5.0.13" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free-solid/-/fontawesome-free-solid-5.0.13.tgz#24b61aaf471a9d34a5364b052d64a516285ba894" - dependencies: - "@fortawesome/fontawesome-common-types" "^0.1.7" - -"@fortawesome/fontawesome@1.1.8": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome/-/fontawesome-1.1.8.tgz#75fe66a60f95508160bb16bd781ad7d89b280f5b" - dependencies: - "@fortawesome/fontawesome-common-types" "^0.1.7" - -"@gulp-sourcemaps/identity-map@1.X": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz#cfa23bc5840f9104ce32a65e74db7e7a974bbee1" - dependencies: - acorn "^5.0.3" - css "^2.2.1" - normalize-path "^2.1.1" - source-map "^0.5.6" - through2 "^2.0.3" - -"@gulp-sourcemaps/map-sources@1.X": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda" - dependencies: - normalize-path "^2.0.1" - through2 "^2.0.3" - -"@koa/cors@2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-2.2.1.tgz#c06a1c34d787e3cee79c0d4c20e8952d1b6d75c5" - -"@mrmlnc/readdir-enhanced@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" - dependencies: - call-me-maybe "^1.0.1" - glob-to-regexp "^0.3.0" - -"@nodelib/fs.stat@^1.0.1": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz#50c1e2260ac0ed9439a181de3725a0168d59c48a" - -"@prezzemolo/rap@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@prezzemolo/rap/-/rap-0.1.2.tgz#01f8a60bb61de33822fc632563fb8b23e574854e" - -"@prezzemolo/zip@0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@prezzemolo/zip/-/zip-0.0.3.tgz#6532d4bcd77c6a95e3a90ca5388a09b532a1f8e4" - -"@samverschueren/stream-to-observable@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" - dependencies: - any-observable "^0.3.0" - -"@sindresorhus/is@^0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" - -"@types/accepts@*": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575" - dependencies: - "@types/node" "*" - -"@types/babel-types@*", "@types/babel-types@^7.0.0": - version "7.0.3" - resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.3.tgz#9dc5316090ad99cd2679051ab21a5676c90a2bcc" - -"@types/babylon@^6.16.2": - version "6.16.3" - resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.3.tgz#c2937813a89fcb5e79a00062fc4a8b143e7237bb" - dependencies: - "@types/babel-types" "*" - -"@types/bcryptjs@2.4.1": - version "2.4.1" - resolved "https://registry.yarnpkg.com/@types/bcryptjs/-/bcryptjs-2.4.1.tgz#7fb63922b5b106edacdcfe084cd38850f78aacfc" - -"@types/body-parser@*": - version "1.17.0" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c" - dependencies: - "@types/connect" "*" - "@types/node" "*" - -"@types/bson@*": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@types/bson/-/bson-1.0.8.tgz#6ad272b3f049e9598ec33aed09cf56d8946b75f1" - dependencies: - "@types/node" "*" - -"@types/caseless@*": - version "0.12.1" - resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.1.tgz#9794c69c8385d0192acc471a540d1f8e0d16218a" - -"@types/cheerio@^0.22.5": - version "0.22.7" - resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.7.tgz#4a92eafedfb2b9f4437d3a4410006d81114c66ce" - -"@types/clean-css@*": - version "3.4.30" - resolved "https://registry.yarnpkg.com/@types/clean-css/-/clean-css-3.4.30.tgz#0052c136f5248002428e3638b37de4a39818641d" - -"@types/connect@*": - version "3.4.32" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28" - dependencies: - "@types/node" "*" - -"@types/cookies@*": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.1.tgz#f9f204bd6767d389eea3b87609e30c090c77a540" - dependencies: - "@types/connect" "*" - "@types/express" "*" - "@types/keygrip" "*" - "@types/node" "*" - -"@types/debug@0.0.30": - version "0.0.30" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-0.0.30.tgz#dc1e40f7af3b9c815013a7860e6252f6352a84df" - -"@types/deep-equal@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.1.tgz#71cfabb247c22bcc16d536111f50c0ed12476b03" - -"@types/elasticsearch@5.0.23": - version "5.0.23" - resolved "https://registry.yarnpkg.com/@types/elasticsearch/-/elasticsearch-5.0.23.tgz#235622772a7c7f3ccedd0dc9769dfcfe20eed1ec" - -"@types/events@*": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" - -"@types/express-serve-static-core@*": - version "4.16.0" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz#fdfe777594ddc1fe8eb8eccce52e261b496e43e7" - dependencies: - "@types/events" "*" - "@types/node" "*" - "@types/range-parser" "*" - -"@types/express@*": - version "4.16.0" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.16.0.tgz#6d8bc42ccaa6f35cf29a2b7c3333cb47b5a32a19" - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "*" - "@types/serve-static" "*" - -"@types/fancy-log@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@types/fancy-log/-/fancy-log-1.3.0.tgz#a61ab476e5e628cd07a846330df53b85e05c8ce0" - -"@types/file-type@5.2.1": - version "5.2.1" - resolved "https://registry.yarnpkg.com/@types/file-type/-/file-type-5.2.1.tgz#e7af49e08187b6b7598509c5e416669d25fa3461" - dependencies: - "@types/node" "*" - -"@types/form-data@*": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-2.2.1.tgz#ee2b3b8eaa11c0938289953606b745b738c54b1e" - dependencies: - "@types/node" "*" - -"@types/glob@*": - version "5.0.35" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.35.tgz#1ae151c802cece940443b5ac246925c85189f32a" - dependencies: - "@types/events" "*" - "@types/minimatch" "*" - "@types/node" "*" - -"@types/gm@1.18.0": - version "1.18.0" - resolved "https://registry.yarnpkg.com/@types/gm/-/gm-1.18.0.tgz#49be90ff74286fcdc23b00f13d3699e6dfaceef2" - dependencies: - "@types/node" "*" - -"@types/gulp-htmlmin@1.3.32": - version "1.3.32" - resolved "https://registry.yarnpkg.com/@types/gulp-htmlmin/-/gulp-htmlmin-1.3.32.tgz#342baec649f285c7cbd78dfcf54dd17c388bde2b" - dependencies: - "@types/html-minifier" "*" - "@types/node" "*" - -"@types/gulp-mocha@0.0.32": - version "0.0.32" - resolved "https://registry.yarnpkg.com/@types/gulp-mocha/-/gulp-mocha-0.0.32.tgz#dbc425e804a8354236c31ab23406222a8ab9bdaf" - dependencies: - "@types/mocha" "*" - "@types/node" "*" - -"@types/gulp-rename@0.0.33": - version "0.0.33" - resolved "https://registry.yarnpkg.com/@types/gulp-rename/-/gulp-rename-0.0.33.tgz#38d146e97786569f74f5391a1b1f9b5198674b6c" - dependencies: - "@types/node" "*" - -"@types/gulp-replace@0.0.31": - version "0.0.31" - resolved "https://registry.yarnpkg.com/@types/gulp-replace/-/gulp-replace-0.0.31.tgz#87c3ac90b437694c58d68d1da677fcaff38b25ff" - dependencies: - "@types/node" "*" - -"@types/gulp-uglify@3.0.5": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@types/gulp-uglify/-/gulp-uglify-3.0.5.tgz#ddcbbb6bd15a84b8a6c5e2218c2efba98102d135" - dependencies: - "@types/node" "*" - "@types/uglify-js" "^2" - -"@types/gulp-util@3.0.34": - version "3.0.34" - resolved "https://registry.yarnpkg.com/@types/gulp-util/-/gulp-util-3.0.34.tgz#d1291ebf706d93f46eb8df11344bbfd96247697e" - dependencies: - "@types/node" "*" - "@types/through2" "*" - "@types/vinyl" "*" - chalk "^2.2.0" - -"@types/gulp@3.8.36": - version "3.8.36" - resolved "https://registry.yarnpkg.com/@types/gulp/-/gulp-3.8.36.tgz#11eaf583bf0534669b4ffa9bfed51557faa00a4c" - dependencies: - "@types/node" "*" - "@types/orchestrator" "*" - "@types/vinyl" "*" - -"@types/html-minifier@*": - version "3.5.2" - resolved "https://registry.yarnpkg.com/@types/html-minifier/-/html-minifier-3.5.2.tgz#f897a13d847a774e9b6fd91497e9b0e0ead71c35" - dependencies: - "@types/clean-css" "*" - "@types/relateurl" "*" - "@types/uglify-js" "*" - -"@types/http-assert@*": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.3.0.tgz#5e932606153da28e1d04f9043f4912cf61fd55dd" - -"@types/inquirer@0.0.41": - version "0.0.41" - resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-0.0.41.tgz#0c33027dcd0b0dde234e22afa454f2c75d8b30d2" - dependencies: - "@types/rx" "*" - "@types/through" "*" - -"@types/is-root@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/is-root/-/is-root-1.0.0.tgz#1cf41787243a8f030eb737a9aaf08b071e4f2453" - -"@types/is-url@1.2.28": - version "1.2.28" - resolved "https://registry.yarnpkg.com/@types/is-url/-/is-url-1.2.28.tgz#914dabd50546d9b0142806e42c72bc7c2b7e0787" - -"@types/js-yaml@3.11.1": - version "3.11.1" - resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.11.1.tgz#ac5bab26be5f9c6f74b6b23420f2cfa5a7a6ba40" - -"@types/jsdom@11.0.5": - version "11.0.5" - resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-11.0.5.tgz#b12fffc73eb3731b218e9665a50f023b6b84b5cb" - dependencies: - "@types/events" "*" - "@types/node" "*" - "@types/tough-cookie" "*" - parse5 "^3.0.2" - -"@types/keygrip@*": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.1.tgz#ff540462d2fb4d0a88441ceaf27d287b01c3d878" - -"@types/koa-bodyparser@4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@types/koa-bodyparser/-/koa-bodyparser-4.2.0.tgz#04febc567f3d3dd40e3d1a0e095cdf7b07c4d7ce" - dependencies: - "@types/koa" "*" - -"@types/koa-compose@*": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@types/koa-compose/-/koa-compose-3.2.2.tgz#dc106e000bbf92a3ac900f756df47344887ee847" - -"@types/koa-compress@2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@types/koa-compress/-/koa-compress-2.0.8.tgz#426a2fac419aff7d1a7d87fd78203bf0d26a94fb" - dependencies: - "@types/koa" "*" - "@types/node" "*" - -"@types/koa-favicon@2.0.19": - version "2.0.19" - resolved "https://registry.yarnpkg.com/@types/koa-favicon/-/koa-favicon-2.0.19.tgz#a1b584fd64c99f16710633272292bf7d4b0ca1fa" - dependencies: - "@types/koa" "*" - -"@types/koa-logger@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/koa-logger/-/koa-logger-3.1.0.tgz#133acdbc56d87b5a559cab25528b087381a8fc0d" - dependencies: - "@types/koa" "*" - -"@types/koa-mount@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/koa-mount/-/koa-mount-3.0.1.tgz#2c068d1696b173c62c316158210c4316c4401f57" - dependencies: - "@types/koa" "*" - -"@types/koa-multer@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/koa-multer/-/koa-multer-1.0.0.tgz#f449f399ac3f80c05753452f000e8694ceec4249" - dependencies: - "@types/koa" "*" - -"@types/koa-router@7.0.28": - version "7.0.28" - resolved "https://registry.yarnpkg.com/@types/koa-router/-/koa-router-7.0.28.tgz#67487c862a831099aed8864a8996bfa7e989edc0" - dependencies: - "@types/koa" "*" - -"@types/koa-send@4.1.1": - version "4.1.1" - resolved "https://registry.yarnpkg.com/@types/koa-send/-/koa-send-4.1.1.tgz#88f57cbe0343c8204903f9096d8ff6b98ec3296f" - dependencies: - "@types/koa" "*" - -"@types/koa-views@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/koa-views/-/koa-views-2.0.3.tgz#38fc1f3027503acba73a93fe06678813f306779b" - dependencies: - "@types/koa" "*" - -"@types/koa@*": - version "2.0.46" - resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.0.46.tgz#24bc3cd405d10fcde81f876cd8285b44d4ddc3e9" - dependencies: - "@types/accepts" "*" - "@types/cookies" "*" - "@types/events" "*" - "@types/http-assert" "*" - "@types/keygrip" "*" - "@types/koa-compose" "*" - "@types/node" "*" - -"@types/koa@2.0.45": - version "2.0.45" - resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.0.45.tgz#133cbda6cc8d12b73434b5d9663898c833f80aa2" - dependencies: - "@types/accepts" "*" - "@types/cookies" "*" - "@types/events" "*" - "@types/http-assert" "*" - "@types/keygrip" "*" - "@types/koa-compose" "*" - "@types/node" "*" - -"@types/koa__cors@2.2.2": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@types/koa__cors/-/koa__cors-2.2.2.tgz#03d7cf3b076d5dfab8a5444ac6c5df5173147de8" - dependencies: - "@types/koa" "*" - -"@types/kue@0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@types/kue/-/kue-0.11.8.tgz#820f5e3db6025f0411e0942cd3ccab461a060c90" - dependencies: - "@types/express" "*" - "@types/node" "*" - "@types/redis" "*" - -"@types/license-checker@15.0.0": - version "15.0.0" - resolved "https://registry.yarnpkg.com/@types/license-checker/-/license-checker-15.0.0.tgz#685d69e2cf61ffd862320434601f51c85e28bba1" - -"@types/mime@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.0.tgz#5a7306e367c539b9f6543499de8dd519fac37a8b" - -"@types/minimatch@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" - -"@types/mkdirp@0.5.2": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" - dependencies: - "@types/node" "*" - -"@types/mocha@*": - version "5.2.2" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.2.tgz#202d2b8fe1364c5b617b439b26a54f0e75eac0a7" - -"@types/mocha@5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.0.tgz#b3c8e69f038835db1a7fdc0b3d879fc50506e29e" - -"@types/mongodb@3.0.18": - version "3.0.18" - resolved "https://registry.yarnpkg.com/@types/mongodb/-/mongodb-3.0.18.tgz#e5775ba9c15bf1601e57ada52d9fcbc6d6095d18" - dependencies: - "@types/bson" "*" - "@types/events" "*" - "@types/node" "*" - -"@types/ms@0.7.30": - version "0.7.30" - resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.30.tgz#f6c38b7ecbbf698b0bbd138315a0f0f18954f85f" - -"@types/node@*": - version "10.3.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.3.3.tgz#8798d9e39af2fa604f715ee6a6b19796528e46c3" - -"@types/node@10.1.2": - version "10.1.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.1.2.tgz#1b928a0baa408fc8ae3ac012cc81375addc147c6" - -"@types/node@^8.0.47": - version "8.10.20" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.20.tgz#fe674ea52e13950ab10954433a7824438aabbcac" - -"@types/nopt@3.0.29": - version "3.0.29" - resolved "https://registry.yarnpkg.com/@types/nopt/-/nopt-3.0.29.tgz#f19df3db4c97ee1459a2740028320a71d70964ce" - -"@types/orchestrator@*": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@types/orchestrator/-/orchestrator-0.3.2.tgz#cd15c6cea978a32b98e5054239cbcc78e55671f1" - dependencies: - "@types/node" "*" - "@types/q" "*" - -"@types/parse5@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-3.0.0.tgz#b63305718d82af42a9e5da79c56ecfc1f32e32c0" - dependencies: - parse5 "*" - -"@types/pug@2.0.4", "@types/pug@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.4.tgz#8772fcd0418e3cd2cc171555d73007415051f4b2" - -"@types/q@*": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.0.tgz#87567ea1206935405e51c03635b6cbf3a01f7bc4" - -"@types/qrcode@0.8.1": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@types/qrcode/-/qrcode-0.8.1.tgz#5776cb5da299cfa7cee2610f59997acad90ad38d" - dependencies: - "@types/node" "*" - -"@types/range-parser@*": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.2.tgz#fa8e1ad1d474688a757140c91de6dace6f4abc8d" - -"@types/ratelimiter@2.1.28": - version "2.1.28" - resolved "https://registry.yarnpkg.com/@types/ratelimiter/-/ratelimiter-2.1.28.tgz#cf6371e6d9b1d236e3f0b25889a6d52aed2e0e22" - dependencies: - "@types/redis" "*" - -"@types/redis@*", "@types/redis@2.8.6": - version "2.8.6" - resolved "https://registry.yarnpkg.com/@types/redis/-/redis-2.8.6.tgz#3674d07a13ad76bccda4c37dc3909e4e95757e7e" - dependencies: - "@types/events" "*" - "@types/node" "*" - -"@types/relateurl@*": - version "0.2.28" - resolved "https://registry.yarnpkg.com/@types/relateurl/-/relateurl-0.2.28.tgz#6bda7db8653fa62643f5ee69e9f69c11a392e3a6" - -"@types/request-promise-native@1.0.14": - version "1.0.14" - resolved "https://registry.yarnpkg.com/@types/request-promise-native/-/request-promise-native-1.0.14.tgz#20f2ba136e6f29c2ea745c60767738d434793d31" - dependencies: - "@types/request" "*" - -"@types/request@*": - version "2.47.1" - resolved "https://registry.yarnpkg.com/@types/request/-/request-2.47.1.tgz#25410d3afbdac04c91a94ad9efc9824100735824" - dependencies: - "@types/caseless" "*" - "@types/form-data" "*" - "@types/node" "*" - "@types/tough-cookie" "*" - -"@types/request@2.47.0": - version "2.47.0" - resolved "https://registry.yarnpkg.com/@types/request/-/request-2.47.0.tgz#76a666cee4cb85dcffea6cd4645227926d9e114e" - dependencies: - "@types/caseless" "*" - "@types/form-data" "*" - "@types/node" "*" - "@types/tough-cookie" "*" - -"@types/rimraf@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.2.tgz#7f0fc3cf0ff0ad2a99bb723ae1764f30acaf8b6e" - dependencies: - "@types/glob" "*" - "@types/node" "*" - -"@types/rx-core-binding@*": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@types/rx-core-binding/-/rx-core-binding-4.0.4.tgz#d969d32f15a62b89e2862c17b3ee78fe329818d3" - dependencies: - "@types/rx-core" "*" - -"@types/rx-core@*": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/rx-core/-/rx-core-4.0.3.tgz#0b3354b1238cedbe2b74f6326f139dbc7a591d60" - -"@types/rx-lite-aggregates@*": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/rx-lite-aggregates/-/rx-lite-aggregates-4.0.3.tgz#6efb2b7f3d5f07183a1cb2bd4b1371d7073384c2" - dependencies: - "@types/rx-lite" "*" - -"@types/rx-lite-async@*": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/rx-lite-async/-/rx-lite-async-4.0.2.tgz#27fbf0caeff029f41e2d2aae638b05e91ceb600c" - dependencies: - "@types/rx-lite" "*" - -"@types/rx-lite-backpressure@*": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/rx-lite-backpressure/-/rx-lite-backpressure-4.0.3.tgz#05abb19bdf87cc740196c355e5d0b37bb50b5d56" - dependencies: - "@types/rx-lite" "*" - -"@types/rx-lite-coincidence@*": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/rx-lite-coincidence/-/rx-lite-coincidence-4.0.3.tgz#80bd69acc4054a15cdc1638e2dc8843498cd85c0" - dependencies: - "@types/rx-lite" "*" - -"@types/rx-lite-experimental@*": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@types/rx-lite-experimental/-/rx-lite-experimental-4.0.1.tgz#c532f5cbdf3f2c15da16ded8930d1b2984023cbd" - dependencies: - "@types/rx-lite" "*" - -"@types/rx-lite-joinpatterns@*": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@types/rx-lite-joinpatterns/-/rx-lite-joinpatterns-4.0.1.tgz#f70fe370518a8432f29158cc92ffb56b4e4afc3e" - dependencies: - "@types/rx-lite" "*" - -"@types/rx-lite-testing@*": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@types/rx-lite-testing/-/rx-lite-testing-4.0.1.tgz#21b19d11f4dfd6ffef5a9d1648e9c8879bfe21e9" - dependencies: - "@types/rx-lite-virtualtime" "*" - -"@types/rx-lite-time@*": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/rx-lite-time/-/rx-lite-time-4.0.3.tgz#0eda65474570237598f3448b845d2696f2dbb1c4" - dependencies: - "@types/rx-lite" "*" - -"@types/rx-lite-virtualtime@*": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/rx-lite-virtualtime/-/rx-lite-virtualtime-4.0.3.tgz#4b30cacd0fe2e53af29f04f7438584c7d3959537" - dependencies: - "@types/rx-lite" "*" - -"@types/rx-lite@*": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@types/rx-lite/-/rx-lite-4.0.5.tgz#b3581525dff69423798daa9a0d33c1e66a5e8c4c" - dependencies: - "@types/rx-core" "*" - "@types/rx-core-binding" "*" - -"@types/rx@*": - version "4.1.1" - resolved "https://registry.yarnpkg.com/@types/rx/-/rx-4.1.1.tgz#598fc94a56baed975f194574e0f572fd8e627a48" - dependencies: - "@types/rx-core" "*" - "@types/rx-core-binding" "*" - "@types/rx-lite" "*" - "@types/rx-lite-aggregates" "*" - "@types/rx-lite-async" "*" - "@types/rx-lite-backpressure" "*" - "@types/rx-lite-coincidence" "*" - "@types/rx-lite-experimental" "*" - "@types/rx-lite-joinpatterns" "*" - "@types/rx-lite-testing" "*" - "@types/rx-lite-time" "*" - "@types/rx-lite-virtualtime" "*" - -"@types/seedrandom@2.4.27": - version "2.4.27" - resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.27.tgz#9db563937dd86915f69092bc43259d2f48578e41" - -"@types/serve-static@*": - version "1.13.2" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.2.tgz#f5ac4d7a6420a99a6a45af4719f4dcd8cd907a48" - dependencies: - "@types/express-serve-static-core" "*" - "@types/mime" "*" - -"@types/single-line-log@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@types/single-line-log/-/single-line-log-1.1.0.tgz#7e6fc4e8e785f5f5ab11157418df2684a21ed971" - -"@types/speakeasy@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/speakeasy/-/speakeasy-2.0.2.tgz#153ec3636eea0562209b0a2f1fdf8b479286919b" - -"@types/tapable@*": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.2.tgz#e13182e1b69871a422d7863e11a4a6f5b814a4bd" - -"@types/through2@*": - version "2.0.33" - resolved "https://registry.yarnpkg.com/@types/through2/-/through2-2.0.33.tgz#1ff2e88a100dfb5b140e7bb98791f1194400d131" - dependencies: - "@types/node" "*" - -"@types/through@*": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.29.tgz#72943aac922e179339c651fa34a4428a4d722f93" - dependencies: - "@types/node" "*" - -"@types/tmp@0.0.33": - version "0.0.33" - resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d" - -"@types/tough-cookie@*": - version "2.3.3" - resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.3.tgz#7f226d67d654ec9070e755f46daebf014628e9d9" - -"@types/uglify-js@*": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.2.tgz#f30c75458d18e8ee885c792c04adcb78a13bc286" - dependencies: - source-map "^0.6.1" - -"@types/uglify-js@^2": - version "2.6.31" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-2.6.31.tgz#c694755eeb6a1bb9f8f321f3ec37cc22ca4c4f6b" - dependencies: - source-map "^0.6.1" - -"@types/uuid@3.4.3": - version "3.4.3" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.3.tgz#121ace265f5569ce40f4f6d0ff78a338c732a754" - dependencies: - "@types/node" "*" - -"@types/vinyl@*": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/vinyl/-/vinyl-2.0.2.tgz#4f3b8dae8f5828d3800ef709b0cff488ee852de3" - dependencies: - "@types/node" "*" - -"@types/webpack-stream@3.2.10": - version "3.2.10" - resolved "https://registry.yarnpkg.com/@types/webpack-stream/-/webpack-stream-3.2.10.tgz#eed8389a60d9928b357aa6d13599428d2c4889e7" - dependencies: - "@types/node" "*" - "@types/webpack" "*" - -"@types/webpack@*", "@types/webpack@4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.4.0.tgz#c0551b772be241d786c0548812dd75a932f8efb4" - dependencies: - "@types/node" "*" - "@types/tapable" "*" - "@types/uglify-js" "*" - source-map "^0.6.0" - -"@types/websocket@0.0.39": - version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-0.0.39.tgz#aa971e24f9c1455fe2a57ee3e69c7d395016b12a" - dependencies: - "@types/events" "*" - "@types/node" "*" - -"@types/ws@5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-5.1.1.tgz#4adc1f1a5e92e7e0e95658fb35c7eab1bc52f4ac" - dependencies: - "@types/events" "*" - "@types/node" "*" - -"@vue/component-compiler-utils@^1.2.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-1.3.1.tgz#686f0b913d59590ae327b2a1cb4b6d9b931bbe0e" - dependencies: - consolidate "^0.15.1" - hash-sum "^1.0.2" - lru-cache "^4.1.2" - merge-source-map "^1.1.0" - postcss "^6.0.20" - postcss-selector-parser "^3.1.1" - prettier "^1.13.0" - source-map "^0.5.6" - vue-template-es2015-compiler "^1.6.0" - -"@webassemblyjs/ast@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.4.3.tgz#3b3f6fced944d8660273347533e6d4d315b5934a" - dependencies: - "@webassemblyjs/helper-wasm-bytecode" "1.4.3" - "@webassemblyjs/wast-parser" "1.4.3" - debug "^3.1.0" - webassemblyjs "1.4.3" - -"@webassemblyjs/floating-point-hex-parser@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.4.3.tgz#f5aee4c376a717c74264d7bacada981e7e44faad" - -"@webassemblyjs/helper-buffer@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.4.3.tgz#0434b55958519bf503697d3824857b1dea80b729" - dependencies: - debug "^3.1.0" - -"@webassemblyjs/helper-code-frame@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.4.3.tgz#f1349ca3e01a8e29ee2098c770773ef97af43641" - dependencies: - "@webassemblyjs/wast-printer" "1.4.3" - -"@webassemblyjs/helper-fsm@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.4.3.tgz#65a921db48fb43e868f17b27497870bdcae22b79" - -"@webassemblyjs/helper-wasm-bytecode@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.4.3.tgz#0e5b4b5418e33f8a26e940b7809862828c3721a5" - -"@webassemblyjs/helper-wasm-section@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.4.3.tgz#9ceedd53a3f152c3412e072887ade668d0b1acbf" - dependencies: - "@webassemblyjs/ast" "1.4.3" - "@webassemblyjs/helper-buffer" "1.4.3" - "@webassemblyjs/helper-wasm-bytecode" "1.4.3" - "@webassemblyjs/wasm-gen" "1.4.3" - debug "^3.1.0" - -"@webassemblyjs/leb128@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.4.3.tgz#5a5e5949dbb5adfe3ae95664d0439927ac557fb8" - dependencies: - leb "^0.3.0" - -"@webassemblyjs/validation@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/validation/-/validation-1.4.3.tgz#9e66c9b3079d7bbcf2070c1bf52a54af2a09aac9" - dependencies: - "@webassemblyjs/ast" "1.4.3" - -"@webassemblyjs/wasm-edit@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.4.3.tgz#87febd565e0ffb5ae25f6495bb3958d17aa0a779" - dependencies: - "@webassemblyjs/ast" "1.4.3" - "@webassemblyjs/helper-buffer" "1.4.3" - "@webassemblyjs/helper-wasm-bytecode" "1.4.3" - "@webassemblyjs/helper-wasm-section" "1.4.3" - "@webassemblyjs/wasm-gen" "1.4.3" - "@webassemblyjs/wasm-opt" "1.4.3" - "@webassemblyjs/wasm-parser" "1.4.3" - "@webassemblyjs/wast-printer" "1.4.3" - debug "^3.1.0" - -"@webassemblyjs/wasm-gen@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.4.3.tgz#8553164d0154a6be8f74d653d7ab355f73240aa4" - dependencies: - "@webassemblyjs/ast" "1.4.3" - "@webassemblyjs/helper-wasm-bytecode" "1.4.3" - "@webassemblyjs/leb128" "1.4.3" - -"@webassemblyjs/wasm-opt@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.4.3.tgz#26c7a23bfb136aa405b1d3410e63408ec60894b8" - dependencies: - "@webassemblyjs/ast" "1.4.3" - "@webassemblyjs/helper-buffer" "1.4.3" - "@webassemblyjs/wasm-gen" "1.4.3" - "@webassemblyjs/wasm-parser" "1.4.3" - debug "^3.1.0" - -"@webassemblyjs/wasm-parser@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.4.3.tgz#7ddd3e408f8542647ed612019cfb780830993698" - dependencies: - "@webassemblyjs/ast" "1.4.3" - "@webassemblyjs/helper-wasm-bytecode" "1.4.3" - "@webassemblyjs/leb128" "1.4.3" - "@webassemblyjs/wasm-parser" "1.4.3" - webassemblyjs "1.4.3" - -"@webassemblyjs/wast-parser@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.4.3.tgz#3250402e2c5ed53dbe2233c9de1fe1f9f0d51745" - dependencies: - "@webassemblyjs/ast" "1.4.3" - "@webassemblyjs/floating-point-hex-parser" "1.4.3" - "@webassemblyjs/helper-code-frame" "1.4.3" - "@webassemblyjs/helper-fsm" "1.4.3" - long "^3.2.0" - webassemblyjs "1.4.3" - -"@webassemblyjs/wast-printer@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.4.3.tgz#3d59aa8d0252d6814a3ef4e6d2a34c9ded3904e0" - dependencies: - "@webassemblyjs/ast" "1.4.3" - "@webassemblyjs/wast-parser" "1.4.3" - long "^3.2.0" - -abab@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - -accepts@^1.2.2, accepts@~1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" - dependencies: - mime-types "~2.1.18" - negotiator "0.6.1" - -accord@^0.26.3: - version "0.26.4" - resolved "https://registry.yarnpkg.com/accord/-/accord-0.26.4.tgz#fc4c8d3ebab406a07cb28819b859651c44a92e80" - dependencies: - convert-source-map "^1.2.0" - glob "^7.0.5" - indx "^0.2.3" - lodash.clone "^4.3.2" - lodash.defaults "^4.0.1" - lodash.flatten "^4.2.0" - lodash.merge "^4.4.0" - lodash.partialright "^4.1.4" - lodash.pick "^4.2.1" - lodash.uniq "^4.3.0" - resolve "^1.1.7" - semver "^5.3.0" - uglify-js "^2.7.0" - when "^3.7.7" - -acorn-dynamic-import@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278" - dependencies: - acorn "^5.0.0" - -acorn-globals@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf" - dependencies: - acorn "^4.0.4" - -acorn-globals@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.1.0.tgz#ab716025dbe17c54d3ef81d32ece2b2d99fe2538" - dependencies: - acorn "^5.0.0" - -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - dependencies: - acorn "^3.0.4" - -acorn@5.X, acorn@^5.0.0, acorn@^5.0.3, acorn@^5.3.0, acorn@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8" - -acorn@^3.0.4, acorn@^3.1.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - -acorn@^4.0.4, acorn@~4.0.2: - version "4.0.13" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - -agent-base@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce" - dependencies: - es6-promisify "^5.0.0" - -agentkeepalive@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.4.1.tgz#aa95aebc3a749bca5ed53e3880a09f5235b48f0c" - dependencies: - humanize-ms "^1.2.1" - -ajv-keywords@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" - -ajv-keywords@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" - -ajv@^4.9.1: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -ajv@^6.1.0: - version "6.5.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.1.tgz#88ebc1263c7133937d108b80c5572e64e1d9322d" - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.1" - -align-text@^0.1.1, align-text@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - dependencies: - kind-of "^3.0.2" - longest "^1.0.1" - repeat-string "^1.5.2" - -alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - -animejs@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/animejs/-/animejs-2.2.0.tgz#35eefdfc535b81949c9cb06f0b3e60c02e6fdc80" - -ansi-colors@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" - dependencies: - ansi-wrap "^0.1.0" - -ansi-cyan@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" - dependencies: - ansi-wrap "0.1.0" - -ansi-escapes@^1.0.0, ansi-escapes@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - -ansi-escapes@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" - -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - dependencies: - ansi-wrap "0.1.0" - -ansi-red@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" - dependencies: - ansi-wrap "0.1.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - dependencies: - color-convert "^1.9.0" - -ansi-styles@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" - -ansi-wrap@0.1.0, ansi-wrap@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - -any-observable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" - -any-promise@^1.0.0, any-promise@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - -anymatch@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" - dependencies: - micromatch "^2.1.5" - normalize-path "^2.0.0" - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -"apparatus@>= 0.0.9": - version "0.0.10" - resolved "https://registry.yarnpkg.com/apparatus/-/apparatus-0.0.10.tgz#81ea756772ada77863db54ceee8202c109bdca3e" - dependencies: - sylvester ">= 0.0.8" - -append-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" - dependencies: - buffer-equal "^1.0.0" - -append-field@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/append-field/-/append-field-0.1.0.tgz#6ddc58fa083c7bc545d3c5995b2830cc2366d44a" - -aproba@^1.0.3, aproba@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - -archive-type@^3.0.0, archive-type@^3.0.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/archive-type/-/archive-type-3.2.0.tgz#9cd9c006957ebe95fadad5bd6098942a813737f6" - dependencies: - file-type "^3.1.0" - -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" - dependencies: - arr-flatten "^1.0.1" - array-slice "^0.2.3" - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - dependencies: - arr-flatten "^1.0.1" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - -arr-flatten@^1.0.1, arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - -arr-union@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - -array-each@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" - -array-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" - -array-filter@~0.0.0: - version "0.0.1" - resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" - -array-find-index@^1.0.1, array-find-index@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - -array-map@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" - -array-parallel@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/array-parallel/-/array-parallel-0.1.3.tgz#8f785308926ed5aa478c47e64d1b334b6c0c947d" - -array-reduce@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" - -array-series@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/array-series/-/array-series-0.1.5.tgz#df5d37bfc5c2ef0755e2aa4f92feae7d4b5a972f" - -array-slice@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" - -array-slice@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.0, array-uniq@^1.0.1, array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - -arrify@^1.0.0, arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - -asap@^2.0.0, asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -asn1.js@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.0.1.tgz#7668b56416953f0ce3421adbb3893ace59c96f59" - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - -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" - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - -assert@^1.1.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - dependencies: - util "0.10.3" - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - -ast-types@0.10.1: - version "0.10.1" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.10.1.tgz#f52fca9715579a14f841d67d7f8d25432ab6a3dd" - -ast-types@0.11.5: - version "0.11.5" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.5.tgz#9890825d660c03c28339f315e9fa0a360e31ec28" - -async-each-series@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/async-each-series/-/async-each-series-1.1.0.tgz#f42fd8155d38f21a5b8ea07c28e063ed1700b138" - -async-each@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - -async-foreach@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" - -async-limiter@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - -async-validator@~1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-1.8.2.tgz#b77597226e96242f8d531c0d46ae295f62422ba4" - dependencies: - babel-runtime "6.x" - -async@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - -async@^2.5.0, async@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - dependencies: - lodash "^4.17.10" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - -atob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" - -autoprefixer@^6.3.1: - version "6.7.7" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" - dependencies: - browserslist "^1.7.6" - caniuse-db "^1.0.30000634" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^5.2.16" - postcss-value-parser "^3.2.3" - -autosize@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/autosize/-/autosize-4.0.2.tgz#073cfd07c8bf45da4b9fd153437f5bafbba1e4c9" - -autwh@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/autwh/-/autwh-0.1.0.tgz#24a5300923309d105133401a2568f9c8ab7d7e03" - dependencies: - oauth "0.9.15" - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - -aws4@^1.2.1, aws4@^1.6.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" - -babel-code-frame@^6.22.0, 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" - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@^6.26.0: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helper-bindify-decorators@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-explode-class@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" - dependencies: - babel-helper-bindify-decorators "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-vue-jsx-merge-props@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - -babel-plugin-syntax-async-generators@^6.5.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" - -babel-plugin-syntax-class-constructor-call@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416" - -babel-plugin-syntax-class-properties@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - -babel-plugin-syntax-decorators@^6.13.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" - -babel-plugin-syntax-dynamic-import@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - -babel-plugin-syntax-export-extensions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721" - -babel-plugin-syntax-flow@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" - -babel-plugin-syntax-object-rest-spread@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - -babel-plugin-transform-async-generator-functions@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-generators "^6.5.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-class-constructor-call@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz#80dc285505ac067dcb8d6c65e2f6f11ab7765ef9" - dependencies: - babel-plugin-syntax-class-constructor-call "^6.18.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-class-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - dependencies: - babel-helper-function-name "^6.24.1" - babel-plugin-syntax-class-properties "^6.8.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-decorators@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" - dependencies: - babel-helper-explode-class "^6.24.1" - babel-plugin-syntax-decorators "^6.13.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-export-extensions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653" - dependencies: - babel-plugin-syntax-export-extensions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-flow-strip-types@^6.8.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" - dependencies: - babel-plugin-syntax-flow "^6.18.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-object-rest-spread@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.26.0" - -babel-plugin-transform-regenerator@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - dependencies: - regenerator-transform "^0.10.0" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-polyfill@6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" - dependencies: - babel-runtime "^6.22.0" - core-js "^2.4.0" - regenerator-runtime "^0.10.0" - -babel-preset-es2015@^6.9.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.24.1" - babel-plugin-transform-es2015-classes "^6.24.1" - babel-plugin-transform-es2015-computed-properties "^6.24.1" - babel-plugin-transform-es2015-destructuring "^6.22.0" - babel-plugin-transform-es2015-duplicate-keys "^6.24.1" - babel-plugin-transform-es2015-for-of "^6.22.0" - babel-plugin-transform-es2015-function-name "^6.24.1" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-plugin-transform-es2015-modules-systemjs "^6.24.1" - babel-plugin-transform-es2015-modules-umd "^6.24.1" - babel-plugin-transform-es2015-object-super "^6.24.1" - babel-plugin-transform-es2015-parameters "^6.24.1" - babel-plugin-transform-es2015-shorthand-properties "^6.24.1" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.24.1" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.22.0" - babel-plugin-transform-es2015-unicode-regex "^6.24.1" - babel-plugin-transform-regenerator "^6.24.1" - -babel-preset-stage-1@^6.5.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz#7692cd7dcd6849907e6ae4a0a85589cfb9e2bfb0" - dependencies: - babel-plugin-transform-class-constructor-call "^6.24.1" - babel-plugin-transform-export-extensions "^6.22.0" - babel-preset-stage-2 "^6.24.1" - -babel-preset-stage-2@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" - dependencies: - babel-plugin-syntax-dynamic-import "^6.18.0" - babel-plugin-transform-class-properties "^6.24.1" - babel-plugin-transform-decorators "^6.24.1" - babel-preset-stage-3 "^6.24.1" - -babel-preset-stage-3@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" - dependencies: - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-generator-functions "^6.24.1" - babel-plugin-transform-async-to-generator "^6.24.1" - babel-plugin-transform-exponentiation-operator "^6.24.1" - babel-plugin-transform-object-rest-spread "^6.22.0" - -babel-register@^6.26.0, babel-register@^6.9.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@6.x, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@^6.17.3, babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - -babylon@^7.0.0-beta.47: - version "7.0.0-beta.47" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.47.tgz#6d1fa44f0abec41ab7c780481e62fd9aafbdea80" - -balanced-match@^0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -base32.js@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/base32.js/-/base32.js-0.0.1.tgz#d045736a57b1f6c139f0c7df42518a84e91bb2ba" - -base64-js@^1.0.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - dependencies: - tweetnacl "^0.14.3" - -bcryptjs@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" - -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - -big.js@^3.1.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - -bin-build@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/bin-build/-/bin-build-2.2.0.tgz#11f8dd61f70ffcfa2bdcaa5b46f5e8fedd4221cc" - dependencies: - archive-type "^3.0.1" - decompress "^3.0.0" - download "^4.1.2" - exec-series "^1.0.0" - rimraf "^2.2.6" - tempfile "^1.0.0" - url-regex "^3.0.0" - -bin-check@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/bin-check/-/bin-check-2.0.0.tgz#86f8e6f4253893df60dc316957f5af02acb05930" - dependencies: - executable "^1.0.0" - -bin-version-check@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-2.1.0.tgz#e4e5df290b9069f7d111324031efc13fdd11a5b0" - dependencies: - bin-version "^1.0.0" - minimist "^1.1.0" - semver "^4.0.3" - semver-truncate "^1.0.0" - -bin-version@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-1.0.4.tgz#9eb498ee6fd76f7ab9a7c160436f89579435d78e" - dependencies: - find-versions "^1.0.0" - -bin-wrapper@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/bin-wrapper/-/bin-wrapper-3.0.2.tgz#67d3306262e4b1a5f2f88ee23464f6a655677aeb" - dependencies: - bin-check "^2.0.0" - bin-version-check "^2.1.0" - download "^4.0.0" - each-async "^1.1.1" - lazy-req "^1.0.0" - os-filter-obj "^1.0.0" - -binary-extensions@^1.0.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" - -binaryextensions@2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.1.tgz#3209a51ca4a4ad541a3b8d3d6a6d5b83a2485935" - -bl@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - dependencies: - inherits "~2.0.0" - -bluebird@^3.0.5, bluebird@^3.1.1, bluebird@^3.4.1, bluebird@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - -body-parser@1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" - dependencies: - bytes "3.0.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.1" - http-errors "~1.6.2" - iconv-lite "0.4.19" - on-finished "~2.3.0" - qs "6.5.1" - raw-body "2.3.2" - type-is "~1.6.15" - -body-parser@^1.12.2: - version "1.18.3" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" - dependencies: - bytes "3.0.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "~1.6.3" - iconv-lite "0.4.23" - on-finished "~2.3.0" - qs "6.5.2" - raw-body "2.3.3" - type-is "~1.6.16" - -boolbase@^1.0.0, boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - dependencies: - hoek "4.x.x" - -boom@5.x.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - dependencies: - hoek "4.x.x" - -bootstrap-vue@2.0.0-rc.6: - version "2.0.0-rc.6" - resolved "https://registry.yarnpkg.com/bootstrap-vue/-/bootstrap-vue-2.0.0-rc.6.tgz#12d0a241414f1efd647e8b14a88c51707c920c86" - dependencies: - bootstrap "^4.0.0" - lodash.get "^4.4.2" - lodash.startcase "^4.4.0" - opencollective "^1.0.3" - popper.js "^1.12.9" - vue-functional-data-merge "^2.0.5" - -bootstrap@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.1.tgz#3aec85000fa619085da8d2e4983dfd67cf2114cb" - -brace-expansion@^1.0.0, brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -braces@^2.3.0, braces@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -brorand@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - -browser-process-hrtime@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.1.tgz#3343124db6d7ad53e26a8826318712bdc8450f9c" - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - -browserify-rsa@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - dependencies: - bn.js "^4.1.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - dependencies: - pako "~1.0.5" - -browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: - version "1.7.7" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" - dependencies: - caniuse-db "^1.0.30000639" - electron-to-chromium "^1.2.7" - -bson@~1.0.4: - version "1.0.9" - resolved "https://registry.yarnpkg.com/bson/-/bson-1.0.9.tgz#12319f8323b1254739b7c6bef8d3e89ae05a2f57" - -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - -buffer-alloc@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - -buffer-equal-constant-time@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - -buffer-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" - -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - -buffer-from@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0" - -buffer-from@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04" - -buffer-shims@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" - -buffer-to-vinyl@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz#00f15faee3ab7a1dda2cde6d9121bffdd07b2262" - dependencies: - file-type "^3.1.0" - readable-stream "^2.0.2" - uuid "^2.0.1" - vinyl "^1.0.0" - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - -buffer@^4.3.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -bufferstreams@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/bufferstreams/-/bufferstreams-1.1.3.tgz#a8515ac024fa90e8fa7d58c11b13dea1f28abe72" - dependencies: - readable-stream "^2.0.2" - -builtin-modules@^1.0.0, builtin-modules@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - -busboy@^0.2.11: - version "0.2.14" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453" - dependencies: - dicer "0.2.5" - readable-stream "1.1.x" - -bytes@3.0.0, bytes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - -bytes@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.5.0.tgz#4c9423ea2d252c270c41b2bdefeff9bb6b62c06a" - -cacache@^10.0.4: - version "10.0.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460" - dependencies: - bluebird "^3.5.1" - chownr "^1.0.1" - glob "^7.1.2" - graceful-fs "^4.1.11" - lru-cache "^4.1.1" - mississippi "^2.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.2" - ssri "^5.2.4" - unique-filename "^1.1.0" - y18n "^4.0.0" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -cacheable-request@^2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" - dependencies: - clone-response "1.0.2" - get-stream "3.0.0" - http-cache-semantics "3.8.1" - keyv "3.0.0" - lowercase-keys "1.0.0" - normalize-url "2.0.1" - responselike "1.0.2" - -cafy@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/cafy/-/cafy-8.0.0.tgz#8f6ce8556d64ee145c5cdc79b5b68f7fc57ee46f" - -call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - dependencies: - callsites "^0.2.0" - -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - -camel-case@3.0.x: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" - dependencies: - no-case "^2.2.0" - upper-case "^1.1.1" - -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - -camelcase@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - -can-promise@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/can-promise/-/can-promise-0.0.1.tgz#7a7597ad801fb14c8b22341dfec314b6bd6ad8d3" - dependencies: - window-or-global "^1.0.1" - -caniuse-api@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" - dependencies: - browserslist "^1.3.6" - caniuse-db "^1.0.30000529" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000856" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000856.tgz#fbebb99abe15a5654fc7747ebb5315bdfde3358f" - -capture-stack-trace@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" - -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - -caw@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/caw/-/caw-1.2.0.tgz#ffb226fe7efc547288dc62ee3e97073c212d1034" - dependencies: - get-proxy "^1.0.1" - is-obj "^1.0.0" - object-assign "^3.0.0" - tunnel-agent "^0.4.0" - -center-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - dependencies: - align-text "^0.1.3" - lazy-cache "^1.0.3" - -chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796" - dependencies: - ansi-styles "^3.2.0" - escape-string-regexp "^1.0.5" - supports-color "^5.2.0" - -chalk@2.4.1, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.2.0, chalk@^2.3.0, chalk@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f" - dependencies: - ansi-styles "~1.0.0" - has-color "~0.1.0" - strip-ansi "~0.1.0" - -character-parser@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0" - dependencies: - is-regex "^1.0.3" - -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - -cheerio-httpcli@0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/cheerio-httpcli/-/cheerio-httpcli-0.7.2.tgz#346d41b0f00f01aaa2da8d5e7efb3f806fb277a3" - dependencies: - "@types/cheerio" "^0.22.5" - "@types/node" "^8.0.47" - async "^2.5.0" - cheerio "^0.22.0" - colors "^1.1.2" - foreach "^2.0.5" - he "^1.1.1" - iconv-lite "^0.4.19" - jschardet "^1.6.0" - object-assign "^4.1.1" - os-locale "^2.1.0" - prettyjson "^1.2.1" - request "^2.83.0" - require-uncached "^1.0.3" - rsvp "^4.7.0" - spawn-sync "^1.0.15" - tough-cookie "^2.3.3" - type-of "^2.0.1" - valid-url "^1.0.9" - yargs "^10.0.3" - -cheerio@^0.22.0: - version "0.22.0" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.0" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash.assignin "^4.0.9" - lodash.bind "^4.1.4" - lodash.defaults "^4.0.1" - lodash.filter "^4.4.0" - lodash.flatten "^4.2.0" - lodash.foreach "^4.3.0" - lodash.map "^4.4.0" - lodash.merge "^4.4.0" - lodash.pick "^4.2.1" - lodash.reduce "^4.4.0" - lodash.reject "^4.4.0" - lodash.some "^4.4.0" - -chokidar@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - dependencies: - anymatch "^1.3.0" - async-each "^1.0.0" - glob-parent "^2.0.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^2.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - optionalDependencies: - fsevents "^1.0.0" - -chokidar@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176" - dependencies: - anymatch "^2.0.0" - async-each "^1.0.0" - braces "^2.3.0" - glob-parent "^3.1.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^2.1.1" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - upath "^1.0.0" - optionalDependencies: - fsevents "^1.1.2" - -chownr@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" - -chrome-trace-event@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-0.1.3.tgz#d395af2d31c87b90a716c831fe326f69768ec084" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - -clap@^1.0.9: - version "1.2.3" - resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" - dependencies: - chalk "^1.1.3" - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -clean-css@4.1.x, clean-css@^4.1.11: - version "4.1.11" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.11.tgz#2ecdf145aba38f54740f26cefd0ff3e03e125d6a" - dependencies: - source-map "0.5.x" - -cli-cursor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" - dependencies: - restore-cursor "^1.0.1" - -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - dependencies: - restore-cursor "^2.0.0" - -cli-spinners@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" - -cli-table@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" - dependencies: - colors "1.0.3" - -cli-truncate@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" - dependencies: - slice-ansi "0.0.4" - string-width "^1.0.1" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - -cliui@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - dependencies: - center-align "^0.1.1" - right-align "^0.1.1" - wordwrap "0.0.2" - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - -clone-deep@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713" - dependencies: - for-own "^1.0.0" - is-plain-object "^2.0.4" - kind-of "^6.0.0" - shallow-clone "^1.0.0" - -clone-response@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - dependencies: - mimic-response "^1.0.0" - -clone-stats@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - -clone@^1.0.0, clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - -clone@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" - -cloneable-readable@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" - dependencies: - inherits "^2.0.1" - process-nextick-args "^2.0.0" - readable-stream "^2.3.5" - -co-body@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/co-body/-/co-body-5.2.0.tgz#5a0a658c46029131e0e3a306f67647302f71c124" - dependencies: - inflation "^2.0.0" - qs "^6.4.0" - raw-body "^2.2.0" - type-is "^1.6.14" - -co-body@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/co-body/-/co-body-6.0.0.tgz#965b9337d7f5655480787471f4237664820827e3" - dependencies: - inflation "^2.0.0" - qs "^6.5.2" - raw-body "^2.3.3" - type-is "^1.6.16" - -co@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/co/-/co-3.1.0.tgz#4ea54ea5a08938153185e15210c68d9092bc1b78" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -coa@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" - dependencies: - q "^1.1.2" - -coa@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.1.tgz#f3f8b0b15073e35d70263fb1042cb2c023db38af" - dependencies: - q "^1.1.2" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.3.0, color-convert@^1.9.0: - version "1.9.2" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" - dependencies: - color-name "1.1.1" - -color-name@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" - -color-name@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - -color-string@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" - dependencies: - color-name "^1.0.0" - -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - -color@^0.11.0: - version "0.11.4" - resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" - dependencies: - clone "^1.0.2" - color-convert "^1.3.0" - color-string "^0.3.0" - -colormin@^1.0.5: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" - dependencies: - color "^0.11.0" - css-color-names "0.0.4" - has "^1.0.1" - -colors@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - -colors@^1.1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.0.tgz#5f20c9fef6945cb1134260aab33bfbdc8295e04e" - -colors@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" - -combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - dependencies: - delayed-stream "~1.0.0" - -commander@2.15.1, commander@2.15.x, commander@^2.11.0, commander@^2.12.1, commander@^2.7.1, commander@^2.9.0, commander@~2.15.0: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - -commander@~2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" - -commander@~2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - dependencies: - graceful-readlink ">= 1.0.0" - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - -component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - -compressible@^2.0.0: - version "2.0.14" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.14.tgz#326c5f507fbb055f54116782b969a81b67a29da7" - dependencies: - mime-db ">= 1.34.0 < 2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -concat-stream@^1.4.6, concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -condense-newlines@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/condense-newlines/-/condense-newlines-0.2.1.tgz#3de985553139475d32502c83b02f60684d24c55f" - dependencies: - extend-shallow "^2.0.1" - is-whitespace "^0.3.0" - kind-of "^3.0.2" - -config-chain@~1.1.5: - version "1.1.11" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - -console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - dependencies: - date-now "^0.1.4" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - -console-stream@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/console-stream/-/console-stream-0.1.1.tgz#a095fe07b20465955f2fafd28b5d72bccd949d44" - -consolidate@^0.15.0, consolidate@^0.15.1: - version "0.15.1" - resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7" - dependencies: - bluebird "^3.1.1" - -constantinople@^3.0.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-3.1.2.tgz#d45ed724f57d3d10500017a7d3a889c1381ae647" - dependencies: - "@types/babel-types" "^7.0.0" - "@types/babylon" "^6.16.2" - babel-types "^6.26.0" - babylon "^6.18.0" - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - -content-disposition@0.5.2, content-disposition@~0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - -content-type@^1.0.0, content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - -convert-source-map@1.X, convert-source-map@^1.1.1, convert-source-map@^1.2.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - -cookies@~0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.7.1.tgz#7c8a615f5481c61ab9f16c833731bcb8f663b99b" - dependencies: - depd "~1.1.1" - keygrip "~1.0.2" - -copy-concurrently@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" - dependencies: - aproba "^1.1.1" - fs-write-stream-atomic "^1.0.8" - iferr "^0.1.5" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.0" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - -copy-to@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/copy-to/-/copy-to-2.0.1.tgz#2680fbb8068a48d08656b6098092bdafc906f4a5" - -core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0: - version "2.5.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" - -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" - -crc-32@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" - dependencies: - exit-on-epipe "~1.0.1" - printj "~1.1.0" - -create-ecdh@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - dependencies: - bn.js "^4.1.0" - elliptic "^6.0.0" - -create-error-class@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" - dependencies: - capture-stack-trace "^1.0.0" - -create-hash@^1.1.0, create-hash@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cropperjs@^1.1.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/cropperjs/-/cropperjs-1.4.0.tgz#e9851559c590d148a10c17c36cdc8126acf01a2e" - -cross-spawn@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^5.0.1, cross-spawn@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^6.0.0, cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - dependencies: - boom "2.x.x" - -cryptiles@3.x.x: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" - dependencies: - boom "5.x.x" - -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -css-color-names@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - -css-loader@0.28.11: - version "0.28.11" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.11.tgz#c3f9864a700be2711bb5a2462b2389b1a392dab7" - dependencies: - babel-code-frame "^6.26.0" - css-selector-tokenizer "^0.7.0" - cssnano "^3.10.0" - icss-utils "^2.1.0" - loader-utils "^1.0.2" - lodash.camelcase "^4.3.0" - object-assign "^4.1.1" - postcss "^5.0.6" - postcss-modules-extract-imports "^1.2.0" - postcss-modules-local-by-default "^1.2.0" - postcss-modules-scope "^1.1.0" - postcss-modules-values "^1.3.0" - postcss-value-parser "^3.3.0" - source-list-map "^2.0.0" - -css-parse@1.7.x: - version "1.7.0" - resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-1.7.0.tgz#321f6cf73782a6ff751111390fc05e2c657d8c9b" - -css-select-base-adapter@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.0.tgz#0102b3d14630df86c3eb9fa9f5456270106cf990" - -css-select@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" - -css-select@~1.3.0-rc0: - version "1.3.0-rc0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.3.0-rc0.tgz#6f93196aaae737666ea1036a8cb14a8fcb7a9231" - dependencies: - boolbase "^1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "^1.0.1" - -css-selector-tokenizer@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86" - dependencies: - cssesc "^0.1.0" - fastparse "^1.1.1" - regexpu-core "^1.0.0" - -css-tree@1.0.0-alpha.29: - version "1.0.0-alpha.29" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" - dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" - -css-tree@1.0.0-alpha25: - version "1.0.0-alpha25" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha25.tgz#1bbfabfbf6eeef4f01d9108ff2edd0be2fe35597" - dependencies: - mdn-data "^1.0.0" - source-map "^0.5.3" - -css-url-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" - -css-what@2.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" - -css@2.X, css@^2.2.1: - version "2.2.3" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.3.tgz#f861f4ba61e79bedc962aa548e5780fd95cbc6be" - dependencies: - inherits "^2.0.1" - source-map "^0.1.38" - source-map-resolve "^0.5.1" - urix "^0.1.0" - -cssesc@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" - -cssnano@^3.0.0, cssnano@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" - dependencies: - autoprefixer "^6.3.1" - decamelize "^1.1.2" - defined "^1.0.0" - has "^1.0.1" - object-assign "^4.0.1" - postcss "^5.0.14" - postcss-calc "^5.2.0" - postcss-colormin "^2.1.8" - postcss-convert-values "^2.3.4" - postcss-discard-comments "^2.0.4" - postcss-discard-duplicates "^2.0.1" - postcss-discard-empty "^2.0.1" - postcss-discard-overridden "^0.1.1" - postcss-discard-unused "^2.2.1" - postcss-filter-plugins "^2.0.0" - postcss-merge-idents "^2.1.5" - postcss-merge-longhand "^2.0.1" - postcss-merge-rules "^2.0.3" - postcss-minify-font-values "^1.0.2" - postcss-minify-gradients "^1.0.1" - postcss-minify-params "^1.0.4" - postcss-minify-selectors "^2.0.4" - postcss-normalize-charset "^1.1.0" - postcss-normalize-url "^3.0.7" - postcss-ordered-values "^2.1.0" - postcss-reduce-idents "^2.2.2" - postcss-reduce-initial "^1.0.0" - postcss-reduce-transforms "^1.0.3" - postcss-svgo "^2.1.1" - postcss-unique-selectors "^2.0.2" - postcss-value-parser "^3.2.3" - postcss-zindex "^2.0.1" - -csso@^3.5.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" - dependencies: - css-tree "1.0.0-alpha.29" - -csso@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" - dependencies: - clap "^1.0.9" - source-map "^0.5.3" - -cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": - version "0.3.2" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b" - -"cssstyle@>= 0.3.1 < 0.4.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.3.1.tgz#6da9b4cff1bc5d716e6e5fe8e04fcb1b50a49adf" - dependencies: - cssom "0.3.x" - -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - dependencies: - array-find-index "^1.0.1" - -cyclist@~0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" - -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - dependencies: - es5-ext "^0.10.9" - -dargs@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/dargs/-/dargs-5.1.0.tgz#ec7ea50c78564cd36c9d5ec18f66329fade27829" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - dependencies: - assert-plus "^1.0.0" - -data-urls@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.0.0.tgz#24802de4e81c298ea8a9388bb0d8e461c774684f" - dependencies: - abab "^1.0.4" - whatwg-mimetype "^2.0.0" - whatwg-url "^6.4.0" - -date-fns@^1.27.2: - version "1.29.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" - -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - -dateformat@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" - -de-indent@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" - -debug-fabulous@1.X: - version "1.1.0" - resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-1.1.0.tgz#af8a08632465224ef4174a9f06308c3c2a1ebc8e" - dependencies: - debug "3.X" - memoizee "0.4.X" - object-assign "4.X" - -debug@*, debug@3.1.0, debug@3.X, debug@^3.0.0, debug@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - dependencies: - ms "2.0.0" - -debug@0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" - -debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.1, debug@^2.6.3, debug@^2.6.8, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - dependencies: - ms "2.0.0" - -debuglog@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" - -decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - -decompress-response@^3.2.0, decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - dependencies: - mimic-response "^1.0.0" - -decompress-tar@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-3.1.0.tgz#217c789f9b94450efaadc5c5e537978fc333c466" - dependencies: - is-tar "^1.0.0" - object-assign "^2.0.0" - strip-dirs "^1.0.0" - tar-stream "^1.1.1" - through2 "^0.6.1" - vinyl "^0.4.3" - -decompress-tarbz2@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-3.1.0.tgz#8b23935681355f9f189d87256a0f8bdd96d9666d" - dependencies: - is-bzip2 "^1.0.0" - object-assign "^2.0.0" - seek-bzip "^1.0.3" - strip-dirs "^1.0.0" - tar-stream "^1.1.1" - through2 "^0.6.1" - vinyl "^0.4.3" - -decompress-targz@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-3.1.0.tgz#b2c13df98166268991b715d6447f642e9696f5a0" - dependencies: - is-gzip "^1.0.0" - object-assign "^2.0.0" - strip-dirs "^1.0.0" - tar-stream "^1.1.1" - through2 "^0.6.1" - vinyl "^0.4.3" - -decompress-unzip@^3.0.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-3.4.0.tgz#61475b4152066bbe3fee12f9d629d15fe6478eeb" - dependencies: - is-zip "^1.0.0" - read-all-stream "^3.0.0" - stat-mode "^0.2.0" - strip-dirs "^1.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - yauzl "^2.2.1" - -decompress@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-3.0.0.tgz#af1dd50d06e3bfc432461d37de11b38c0d991bed" - dependencies: - buffer-to-vinyl "^1.0.0" - concat-stream "^1.4.6" - decompress-tar "^3.0.0" - decompress-tarbz2 "^3.0.0" - decompress-targz "^3.0.0" - decompress-unzip "^3.0.0" - stream-combiner2 "^1.1.1" - vinyl-assign "^1.0.1" - vinyl-fs "^2.2.0" - -deep-equal@1.0.1, deep-equal@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - -deep-extend@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - -deep-is@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.2.tgz#9ced65ea0bc0b09f42a6d79c1b1903f9d913cc18" - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - -deepcopy@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/deepcopy/-/deepcopy-0.6.3.tgz#634780f2f8656ab771af8fa8431ed1ccee55c7b0" - -deepmerge@^1.2.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753" - -deepmerge@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.1.1.tgz#e862b4e45ea0555072bf51e7fd0d9845170ae768" - -defaults@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - dependencies: - clone "^1.0.2" - -define-properties@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" - dependencies: - foreach "^2.0.5" - object-keys "^1.0.8" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -defined@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - -del@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - -depd@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" - -depd@^1.1.0, depd@~1.1.1, depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - -deprecated@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19" - -des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@^1.0.3, destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - -detect-conflict@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/detect-conflict/-/detect-conflict-1.0.1.tgz#088657a66a961c05019db7c4230883b1c6b4176e" - -detect-file@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" - -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - dependencies: - repeating "^2.0.0" - -detect-indent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - -detect-newline@2.X: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" - -dezalgo@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" - dependencies: - asap "^2.0.0" - wrappy "1" - -dicer@0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f" - dependencies: - readable-stream "1.1.x" - streamsearch "0.1.2" - -diff@3.5.0, diff@^3.1.0, diff@^3.2.0, diff@^3.3.1, diff@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dijkstrajs@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.1.tgz#d3cd81221e3ea40742cfcde556d4e99e98ddc71b" - -dir-glob@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" - dependencies: - arrify "^1.0.1" - path-type "^3.0.0" - -diskusage@0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/diskusage/-/diskusage-0.2.4.tgz#e956f7a1051e0c6a1af706154efe620a2ee432ec" - dependencies: - nan "^2.5.0" - -doctrine@^2.0.0, doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - dependencies: - esutils "^2.0.2" - -doctypes@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" - -dom-serializer@0, dom-serializer@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - dependencies: - domelementtype "~1.1.1" - entities "~1.1.1" - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - -domelementtype@1, domelementtype@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" - -domelementtype@~1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - -domexception@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" - dependencies: - webidl-conversions "^4.0.2" - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - dependencies: - domelementtype "1" - -dompurify@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-1.0.4.tgz#b0655d07856c1ef76fd27ae18e8ab1174ed18819" - -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - dependencies: - dom-serializer "0" - domelementtype "1" - -dot-prop@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - dependencies: - is-obj "^1.0.0" - -double-ended-queue@^2.1.0-0: - version "2.1.0-0" - resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" - -download@^4.0.0, download@^4.1.2: - version "4.4.3" - resolved "https://registry.yarnpkg.com/download/-/download-4.4.3.tgz#aa55fdad392d95d4b68e8c2be03e0c2aa21ba9ac" - dependencies: - caw "^1.0.1" - concat-stream "^1.4.7" - each-async "^1.0.0" - filenamify "^1.0.1" - got "^5.0.0" - gulp-decompress "^1.2.0" - gulp-rename "^1.2.0" - is-url "^1.2.0" - object-assign "^4.0.1" - read-all-stream "^3.0.0" - readable-stream "^2.0.2" - stream-combiner2 "^1.1.1" - vinyl "^1.0.0" - vinyl-fs "^2.2.0" - ware "^1.2.0" - -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - dependencies: - readable-stream "~1.1.9" - -duplexer2@^0.1.4, duplexer2@~0.1.0: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - dependencies: - readable-stream "^2.0.2" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - -duplexify@^3.2.0, duplexify@^3.4.2, duplexify@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.0.tgz#592903f5d80b38d037220541264d69a198fb3410" - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -each-async@^1.0.0, each-async@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/each-async/-/each-async-1.1.1.tgz#dee5229bdf0ab6ba2012a395e1b869abf8813473" - dependencies: - onetime "^1.0.0" - set-immediate-shim "^1.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - dependencies: - jsbn "~0.1.0" - -ecdsa-sig-formatter@1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz#1c595000f04a8897dfb85000892a0f4c33af86c3" - dependencies: - safe-buffer "^5.0.1" - -editions@^1.3.3: - version "1.3.4" - resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" - -editorconfig@^0.13.2: - version "0.13.3" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.13.3.tgz#e5219e587951d60958fd94ea9a9a008cdeff1b34" - dependencies: - bluebird "^3.0.5" - commander "^2.9.0" - lru-cache "^3.2.0" - semver "^5.1.0" - sigmund "^1.0.1" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - -ejs@^2.5.9: - version "2.6.1" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" - -elasticsearch@15.0.0: - version "15.0.0" - resolved "https://registry.yarnpkg.com/elasticsearch/-/elasticsearch-15.0.0.tgz#d888ceb858bba30221b68698d72c54bdcfdf2fba" - dependencies: - agentkeepalive "^3.4.1" - chalk "^1.0.0" - lodash "^4.17.10" - -electron-to-chromium@^1.2.7: - version "1.3.48" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz#d3b0d8593814044e092ece2108fc3ac9aea4b900" - -elegant-spinner@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" - -element-ui@2.3.9: - version "2.3.9" - resolved "https://registry.yarnpkg.com/element-ui/-/element-ui-2.3.9.tgz#0c5996e74b375f2665d703c68bdb3269ae9269e0" - dependencies: - async-validator "~1.8.1" - babel-helper-vue-jsx-merge-props "^2.0.0" - deepmerge "^1.2.0" - normalize-wheel "^1.0.1" - resize-observer-polyfill "^1.5.0" - throttle-debounce "^1.0.1" - -elliptic@^6.0.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - -emojilib@2.2.12: - version "2.2.12" - resolved "https://registry.yarnpkg.com/emojilib/-/emojilib-2.2.12.tgz#29481fa5521ac5ed97a5cc0503901c3435d523fa" - -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - dependencies: - iconv-lite "~0.4.13" - -end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - dependencies: - once "^1.4.0" - -end-of-stream@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" - dependencies: - once "~1.3.0" - -enhanced-resolve@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz#e34a6eaa790f62fccd71d93959f56b2b432db10a" - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.4.0" - tapable "^1.0.0" - -entities@^1.1.1, entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - -envinfo@^5.7.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-5.10.0.tgz#503a9774ae15b93ea68bdfae2ccd6306624ea6df" - -errno@^0.1.3, errno@~0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - dependencies: - prr "~1.0.1" - -error-ex@^1.2.0, error-ex@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" - dependencies: - is-arrayish "^0.2.1" - -error-inject@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/error-inject/-/error-inject-1.0.0.tgz#e2b3d91b54aed672f309d950d154850fa11d4f37" - -error@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/error/-/error-7.0.2.tgz#a5f75fff4d9926126ddac0ea5dc38e689153cb02" - dependencies: - string-template "~0.2.1" - xtend "~4.0.0" - -es-abstract@^1.5.1, es-abstract@^1.6.1: - version "1.12.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" - dependencies: - es-to-primitive "^1.1.1" - function-bind "^1.1.1" - has "^1.0.1" - is-callable "^1.1.3" - is-regex "^1.0.4" - -es-to-primitive@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" - dependencies: - is-callable "^1.1.1" - is-date-object "^1.0.1" - is-symbol "^1.0.1" - -es5-ext@^0.10.14, es5-ext@^0.10.30, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2: - version "0.10.45" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.45.tgz#0bfdf7b473da5919d5adf3bd25ceb754fccc3653" - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.1" - next-tick "1" - -es6-iterator@^2.0.1, es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-promise@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4" - -es6-promise@^3.0.2: - version "3.3.1" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" - -es6-promise@^4.0.3, es6-promise@^4.1.1: - version "4.2.4" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - dependencies: - es6-promise "^4.0.3" - -es6-symbol@^3.1.1, es6-symbol@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - dependencies: - d "1" - es5-ext "~0.10.14" - -es6-weak-map@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-iterator "^2.0.1" - es6-symbol "^3.1.1" - -escape-html@~1.0.1, escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - -escape-regexp@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/escape-regexp/-/escape-regexp-0.0.1.tgz#f44bda12d45bbdf9cb7f862ee7e4827b3dd32254" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -escodegen@^1.9.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.10.0.tgz#f647395de22519fbd0d928ffcf1d17e0dec2603e" - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -eslint-plugin-vue@4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-4.5.0.tgz#09d6597f4849e31a3846c2c395fccf17685b69c3" - dependencies: - vue-eslint-parser "^2.0.3" - -eslint-scope@^3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-visitor-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - -eslint@4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" - dependencies: - ajv "^5.3.0" - babel-code-frame "^6.22.0" - chalk "^2.1.0" - concat-stream "^1.6.0" - cross-spawn "^5.1.0" - debug "^3.1.0" - doctrine "^2.1.0" - eslint-scope "^3.7.1" - eslint-visitor-keys "^1.0.0" - espree "^3.5.4" - esquery "^1.0.0" - esutils "^2.0.2" - file-entry-cache "^2.0.0" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.0.1" - ignore "^3.3.3" - imurmurhash "^0.1.4" - inquirer "^3.0.6" - is-resolvable "^1.0.0" - js-yaml "^3.9.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.4" - minimatch "^3.0.2" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - pluralize "^7.0.0" - progress "^2.0.0" - regexpp "^1.0.1" - require-uncached "^1.0.3" - semver "^5.3.0" - strip-ansi "^4.0.0" - strip-json-comments "~2.0.1" - table "4.0.2" - text-table "~0.2.0" - -espree@^3.5.2, espree@^3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - dependencies: - acorn "^5.5.0" - acorn-jsx "^3.0.0" - -esprima@^2.6.0: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - -esprima@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - -esprima@^4.0.0, esprima@~4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" - -esquery@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - dependencies: - estraverse "^4.0.0" - -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - dependencies: - estraverse "^4.1.0" - -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - -esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - -event-emitter@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - dependencies: - d "1" - es5-ext "~0.10.14" - -eventemitter3@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" - -events@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -exec-buffer@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/exec-buffer/-/exec-buffer-3.2.0.tgz#b1686dbd904c7cf982e652c1f5a79b1e5573082b" - dependencies: - execa "^0.7.0" - p-finally "^1.0.0" - pify "^3.0.0" - rimraf "^2.5.4" - tempfile "^2.0.0" - -exec-series@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/exec-series/-/exec-series-1.0.3.tgz#6d257a9beac482a872c7783bc8615839fc77143a" - dependencies: - async-each-series "^1.1.0" - object-assign "^4.1.0" - -execa@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" - dependencies: - cross-spawn "^6.0.0" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -executable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/executable/-/executable-1.1.0.tgz#877980e9112f3391066da37265de7ad8434ab4d9" - dependencies: - meow "^3.1.0" - -exif-js@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/exif-js/-/exif-js-2.3.0.tgz#9d10819bf571f873813e7640241255ab9ce1a814" - -exit-hook@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" - -exit-on-epipe@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - dependencies: - is-posix-bracket "^0.1.0" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - dependencies: - fill-range "^2.1.0" - -expand-tilde@^2.0.0, expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - dependencies: - homedir-polyfill "^1.0.1" - -express@^4.12.2: - version "4.16.3" - resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" - dependencies: - accepts "~1.3.5" - array-flatten "1.1.1" - body-parser "1.18.2" - content-disposition "0.5.2" - content-type "~1.0.4" - cookie "0.3.1" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.1.1" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.2" - path-to-regexp "0.1.7" - proxy-addr "~2.0.3" - qs "6.5.1" - range-parser "~1.2.0" - safe-buffer "5.1.1" - send "0.16.2" - serve-static "1.13.2" - setprototypeof "1.1.0" - statuses "~1.4.0" - type-is "~1.6.16" - utils-merge "1.0.1" - vary "~1.1.2" - -extend-shallow@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" - dependencies: - kind-of "^1.1.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extend/-/extend-1.3.0.tgz#d1516fb0ff5624d2ebf9123ea1dac5a1994004f8" - -extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - -external-editor@^2.0.1, external-editor@^2.0.4, external-editor@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - dependencies: - chardet "^0.4.0" - iconv-lite "^0.4.17" - tmp "^0.0.33" - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - dependencies: - is-extglob "^1.0.0" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - 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" - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - -fancy-log@1.3.2, fancy-log@^1.1.0, fancy-log@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - time-stamp "^1.0.0" - -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - -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" - -fast-glob@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.2.tgz#71723338ac9b4e0e2fff1d6748a2a13d5ed352bf" - dependencies: - "@mrmlnc/readdir-enhanced" "^2.2.1" - "@nodelib/fs.stat" "^1.0.1" - glob-parent "^3.1.0" - is-glob "^4.0.0" - merge2 "^1.2.1" - micromatch "^3.1.10" - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - -fast-levenshtein@~2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - -fastparse@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" - -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - dependencies: - pend "~1.2.0" - -figures@^1.3.5, figures@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" - -file-loader@1.1.11: - version "1.1.11" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-1.1.11.tgz#6fe886449b0f2a936e43cabaac0cdbfb369506f8" - dependencies: - loader-utils "^1.0.2" - schema-utils "^0.4.5" - -file-type@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-8.0.0.tgz#6e4bccc741187f4113334a4e4a4ef84d54d7cc1e" - -file-type@^3.1.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - -file-type@^4.1.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - -filename-reserved-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz#e61cf805f0de1c984567d0386dc5df50ee5af7e4" - -filenamify@^1.0.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-1.2.1.tgz#a9f2ffd11c503bed300015029272378f1f1365a5" - dependencies: - filename-reserved-regex "^1.0.0" - strip-outer "^1.0.0" - trim-repeated "^1.0.0" - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -finalhandler@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.2" - statuses "~1.4.0" - unpipe "~1.0.0" - -find-cache-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" - dependencies: - commondir "^1.0.1" - make-dir "^1.0.0" - pkg-dir "^2.0.0" - -find-index@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - dependencies: - locate-path "^2.0.0" - -find-versions@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-1.2.1.tgz#cbde9f12e38575a0af1be1b9a2c5d5fd8f186b62" - dependencies: - array-uniq "^1.0.0" - get-stdin "^4.0.1" - meow "^3.5.0" - semver-regex "^1.0.0" - -findup-sync@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" - dependencies: - detect-file "^1.0.0" - is-glob "^3.1.0" - micromatch "^3.0.4" - resolve-dir "^1.0.1" - -fined@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476" - dependencies: - expand-tilde "^2.0.2" - is-plain-object "^2.0.3" - object.defaults "^1.1.0" - object.pick "^1.2.0" - parse-filepath "^1.0.1" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - -first-chunk-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz#1bdecdb8e083c0664b91945581577a43a9f31d70" - dependencies: - readable-stream "^2.0.2" - -flagged-respawn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7" - -flat-cache@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" - dependencies: - circular-json "^0.3.1" - del "^2.0.2" - graceful-fs "^4.1.2" - write "^0.2.1" - -flatten@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" - -flow-parser@^0.*: - version "0.74.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.74.0.tgz#4acc8f55bdce5fa4da43c72c28ef8a9600ace87c" - -flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.4" - -for-in@^0.1.3: - version "0.1.8" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1" - -for-in@^1.0.1, for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - dependencies: - for-in "^1.0.1" - -for-own@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" - dependencies: - for-in "^1.0.1" - -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -form-data@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - dependencies: - asynckit "^0.4.0" - combined-stream "1.0.6" - mime-types "^2.1.12" - -format-util@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.3.tgz#032dca4a116262a12c43f4c3ec8566416c5b2d95" - -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2, fresh@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - -from2@^2.1.0, from2@^2.1.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.0" - -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - -fs-extra@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-minipass@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - dependencies: - minipass "^2.2.1" - -fs-mkdirp-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" - dependencies: - graceful-fs "^4.1.11" - through2 "^2.0.3" - -fs-write-stream-atomic@^1.0.8: - version "1.0.10" - resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" - dependencies: - graceful-fs "^4.1.2" - iferr "^0.1.5" - imurmurhash "^0.1.4" - readable-stream "1 || 2" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -fsevents@^1.0.0, fsevents@^1.1.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" - dependencies: - nan "^2.9.2" - node-pre-gyp "^0.10.0" - -fstream@^1.0.0, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -fuckadblock@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/fuckadblock/-/fuckadblock-3.2.1.tgz#17fa3237a5e15c86613406b911e608191a3e62e2" - -function-bind@^1.1.0, function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -gaze@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-0.5.2.tgz#40b709537d24d1d45767db5a908689dfe69ac44f" - dependencies: - globule "~0.1.0" - -gaze@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" - dependencies: - globule "^1.0.0" - -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - dependencies: - is-property "^1.0.0" - -get-caller-file@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" - -get-paths@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/get-paths/-/get-paths-0.0.2.tgz#a9c27b1a8d006c931a4f26fcf7d1546e3ad71bea" - dependencies: - fs-extra "^4.0.2" - -get-proxy@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-1.1.0.tgz#894854491bc591b0f147d7ae570f5c678b7256eb" - dependencies: - rc "^1.1.2" - -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - -get-stream@3.0.0, get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - dependencies: - assert-plus "^1.0.0" - -gh-got@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/gh-got/-/gh-got-6.0.0.tgz#d74353004c6ec466647520a10bd46f7299d268d0" - dependencies: - got "^7.0.0" - is-plain-obj "^1.1.0" - -gifsicle@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-3.0.4.tgz#f45cb5ed10165b665dc929e0e9328b6c821dfa3b" - dependencies: - bin-build "^2.0.0" - bin-wrapper "^3.0.0" - logalot "^2.0.0" - -github-username@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/github-username/-/github-username-4.1.0.tgz#cbe280041883206da4212ae9e4b5f169c30bf417" - dependencies: - gh-got "^6.0.0" - -glob-all@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.1.0.tgz#8913ddfb5ee1ac7812656241b03d5217c64b02ab" - dependencies: - glob "^7.0.5" - yargs "~1.2.6" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - dependencies: - is-glob "^2.0.0" - -glob-parent@^3.0.0, glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-stream@^3.1.5: - version "3.1.18" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-3.1.18.tgz#9170a5f12b790306fdfe598f313f8f7954fd143b" - dependencies: - glob "^4.3.1" - glob2base "^0.0.12" - minimatch "^2.0.1" - ordered-read-streams "^0.1.0" - through2 "^0.6.1" - unique-stream "^1.0.0" - -glob-stream@^5.3.2: - version "5.3.5" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" - dependencies: - extend "^3.0.0" - glob "^5.0.3" - glob-parent "^3.0.0" - micromatch "^2.3.7" - ordered-read-streams "^0.3.0" - through2 "^0.6.0" - to-absolute-glob "^0.1.1" - unique-stream "^2.0.2" - -glob-stream@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" - dependencies: - extend "^3.0.0" - glob "^7.1.1" - glob-parent "^3.1.0" - is-negated-glob "^1.0.0" - ordered-read-streams "^1.0.0" - pumpify "^1.3.5" - readable-stream "^2.1.5" - remove-trailing-separator "^1.0.1" - to-absolute-glob "^2.0.0" - unique-stream "^2.0.2" - -glob-to-regexp@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - -glob-watcher@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-0.0.6.tgz#b95b4a8df74b39c83298b0c05c978b4d9a3b710b" - dependencies: - gaze "^0.5.1" - -glob2base@^0.0.12: - version "0.0.12" - resolved "https://registry.yarnpkg.com/glob2base/-/glob2base-0.0.12.tgz#9d419b3e28f12e83a362164a277055922c9c0d56" - dependencies: - find-index "^0.1.1" - -glob@7.0.x: - version "7.0.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^4.3.1: - version "4.5.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "^2.0.1" - once "^1.3.0" - -glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@~3.1.21: - version "3.1.21" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" - dependencies: - graceful-fs "~1.2.0" - inherits "1" - minimatch "~0.2.11" - -global-modules@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - dependencies: - global-prefix "^1.0.1" - is-windows "^1.0.1" - resolve-dir "^1.0.0" - -global-prefix@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - dependencies: - expand-tilde "^2.0.2" - homedir-polyfill "^1.0.1" - ini "^1.3.4" - is-windows "^1.0.1" - which "^1.2.14" - -globals@^11.0.1: - version "11.5.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.5.0.tgz#6bc840de6771173b191f13d3a9c94d441ee92642" - -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -globby@^8.0.0, globby@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.1.tgz#b5ad48b8aa80b35b814fc1281ecc851f1d2b5b50" - dependencies: - array-union "^1.0.1" - dir-glob "^2.0.0" - fast-glob "^2.0.2" - glob "^7.1.2" - ignore "^3.3.5" - pify "^3.0.0" - slash "^1.0.0" - -globule@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" - dependencies: - glob "~7.1.1" - lodash "~4.17.10" - minimatch "~3.0.2" - -globule@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/globule/-/globule-0.1.0.tgz#d9c8edde1da79d125a151b79533b978676346ae5" - dependencies: - glob "~3.1.21" - lodash "~1.0.1" - minimatch "~0.2.11" - -glogg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" - dependencies: - sparkles "^1.0.0" - -gm@1.23.1: - version "1.23.1" - resolved "https://registry.yarnpkg.com/gm/-/gm-1.23.1.tgz#2edeeb958084d0f8ea7988e5d995b1c7dfc14777" - dependencies: - array-parallel "~0.1.3" - array-series "~0.1.5" - cross-spawn "^4.0.0" - debug "^3.1.0" - -got@^5.0.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/got/-/got-5.7.1.tgz#5f81635a61e4a6589f180569ea4e381680a51f35" - dependencies: - create-error-class "^3.0.1" - duplexer2 "^0.1.4" - is-redirect "^1.0.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - lowercase-keys "^1.0.0" - node-status-codes "^1.0.0" - object-assign "^4.0.1" - parse-json "^2.1.0" - pinkie-promise "^2.0.0" - read-all-stream "^3.0.0" - readable-stream "^2.0.5" - timed-out "^3.0.0" - unzip-response "^1.0.2" - url-parse-lax "^1.0.0" - -got@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - dependencies: - decompress-response "^3.2.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-plain-obj "^1.1.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - p-cancelable "^0.3.0" - p-timeout "^1.1.1" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - url-parse-lax "^1.0.0" - url-to-options "^1.0.1" - -got@^8.3.1: - version "8.3.1" - resolved "https://registry.yarnpkg.com/got/-/got-8.3.1.tgz#093324403d4d955f5a16a7a8d39955d055ae10ed" - dependencies: - "@sindresorhus/is" "^0.7.0" - cacheable-request "^2.1.1" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - into-stream "^3.1.0" - is-retry-allowed "^1.1.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - mimic-response "^1.0.0" - p-cancelable "^0.4.0" - p-timeout "^2.0.1" - pify "^3.0.0" - safe-buffer "^5.1.1" - timed-out "^4.0.1" - url-parse-lax "^3.0.0" - url-to-options "^1.0.1" - -graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -graceful-fs@^3.0.0: - version "3.0.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818" - dependencies: - natives "^1.1.0" - -graceful-fs@~1.2.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364" - -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - -grouped-queue@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/grouped-queue/-/grouped-queue-0.3.3.tgz#c167d2a5319c5a0e0964ef6a25b7c2df8996c85c" - dependencies: - lodash "^4.17.2" - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - -gulp-cssnano@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/gulp-cssnano/-/gulp-cssnano-2.1.3.tgz#02007e2817af09b3688482b430ad7db807aebf72" - dependencies: - buffer-from "^1.0.0" - cssnano "^3.0.0" - object-assign "^4.0.1" - plugin-error "^1.0.1" - vinyl-sourcemaps-apply "^0.2.1" - -gulp-decompress@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/gulp-decompress/-/gulp-decompress-1.2.0.tgz#8eeb65a5e015f8ed8532cafe28454960626f0dc7" - dependencies: - archive-type "^3.0.0" - decompress "^3.0.0" - gulp-util "^3.0.1" - readable-stream "^2.0.2" - -gulp-htmlmin@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/gulp-htmlmin/-/gulp-htmlmin-4.0.0.tgz#266feaed83588838aedda3666f67d057ec120313" - dependencies: - bufferstreams "^1.1.0" - html-minifier "^3.0.3" - plugin-error "^0.1.2" - readable-stream "^2.0.2" - tryit "^1.0.1" - -gulp-imagemin@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/gulp-imagemin/-/gulp-imagemin-4.1.0.tgz#5ce347f1d1706fed3cc8f1777ca9094a583b50b7" - dependencies: - chalk "^2.1.0" - fancy-log "^1.3.2" - imagemin "^5.3.1" - plugin-error "^0.1.2" - plur "^2.1.2" - pretty-bytes "^4.0.2" - through2-concurrent "^1.1.1" - optionalDependencies: - imagemin-gifsicle "^5.2.0" - imagemin-jpegtran "^5.0.2" - imagemin-optipng "^5.2.1" - imagemin-svgo "^6.0.0" - -gulp-mocha@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/gulp-mocha/-/gulp-mocha-6.0.0.tgz#80f32bc705ce30747f355ddb8ccd96a1c73bef13" - dependencies: - dargs "^5.1.0" - execa "^0.10.0" - mocha "^5.2.0" - npm-run-path "^2.0.2" - plugin-error "^1.0.1" - supports-color "^5.4.0" - through2 "^2.0.3" - -gulp-pug@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/gulp-pug/-/gulp-pug-4.0.1.tgz#5c5bb38303a5a565add8b200e292b4a076cf2efa" - dependencies: - "@types/pug" "^2.0.4" - fancy-log "^1.3.2" - plugin-error "^1.0.1" - pug "^2.0.3" - replace-ext "^1.0.0" - through2 "^2.0.3" - -gulp-rename@1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.2.3.tgz#37b75298e9d3e6c0fe9ac4eac13ce3be5434646b" - -gulp-rename@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.3.0.tgz#2e789d8f563ab0c924eeb62967576f37ff4cb826" - -gulp-replace@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulp-replace/-/gulp-replace-1.0.0.tgz#b32bd61654d97b8d78430a67b3e8ce067b7c9143" - dependencies: - istextorbinary "2.2.1" - readable-stream "^2.0.1" - replacestream "^4.0.0" - -gulp-sourcemaps@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" - dependencies: - convert-source-map "^1.1.1" - graceful-fs "^4.1.2" - strip-bom "^2.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - -gulp-sourcemaps@2.6.4: - version "2.6.4" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz#cbb2008450b1bcce6cd23bf98337be751bf6e30a" - dependencies: - "@gulp-sourcemaps/identity-map" "1.X" - "@gulp-sourcemaps/map-sources" "1.X" - acorn "5.X" - convert-source-map "1.X" - css "2.X" - debug-fabulous "1.X" - detect-newline "2.X" - graceful-fs "4.X" - source-map "~0.6.0" - strip-bom-string "1.X" - through2 "2.X" - -gulp-stylus@2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/gulp-stylus/-/gulp-stylus-2.7.0.tgz#f3e932626004927b75ea27ff5c1d3b0ba0b7cbb1" - dependencies: - accord "^0.26.3" - lodash.assign "^3.2.0" - plugin-error "^0.1.2" - replace-ext "0.0.1" - stylus "^0.54.0" - through2 "^2.0.0" - vinyl-sourcemaps-apply "^0.2.0" - -gulp-tslint@8.1.3: - version "8.1.3" - resolved "https://registry.yarnpkg.com/gulp-tslint/-/gulp-tslint-8.1.3.tgz#a89ed144038ae861ee7bfea9528272d126a93da1" - dependencies: - "@types/fancy-log" "1.3.0" - chalk "2.3.1" - fancy-log "1.3.2" - map-stream "~0.0.7" - plugin-error "1.0.1" - through "~2.3.8" - -gulp-typescript@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/gulp-typescript/-/gulp-typescript-4.0.2.tgz#80bb9e376e7aa87b763a6ad5fe054a5d078da1e6" - dependencies: - ansi-colors "^1.0.1" - plugin-error "^0.1.2" - source-map "^0.6.1" - through2 "^2.0.3" - vinyl "^2.1.0" - vinyl-fs "^3.0.0" - -gulp-uglify@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.0.tgz#0df0331d72a0d302e3e37e109485dddf33c6d1ca" - dependencies: - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash "^4.13.1" - make-error-cause "^1.1.1" - through2 "^2.0.0" - uglify-js "^3.0.5" - vinyl-sourcemaps-apply "^0.2.0" - -gulp-util@3.0.8, gulp-util@^3.0.0, gulp-util@^3.0.1: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulp@3.9.1: - version "3.9.1" - resolved "https://registry.yarnpkg.com/gulp/-/gulp-3.9.1.tgz#571ce45928dd40af6514fc4011866016c13845b4" - dependencies: - archy "^1.0.0" - chalk "^1.0.0" - deprecated "^0.0.1" - gulp-util "^3.0.0" - interpret "^1.0.0" - liftoff "^2.1.0" - minimist "^1.1.0" - orchestrator "^0.3.0" - pretty-hrtime "^1.0.0" - semver "^4.1.0" - tildify "^1.0.0" - v8flags "^2.0.2" - vinyl-fs "^0.3.0" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - dependencies: - glogg "^1.0.0" - -har-schema@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - -har-validator@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" - dependencies: - ajv "^4.9.1" - har-schema "^1.0.5" - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - -hard-source-webpack-plugin@0.6.10: - version "0.6.10" - resolved "https://registry.yarnpkg.com/hard-source-webpack-plugin/-/hard-source-webpack-plugin-0.6.10.tgz#bae18a97c12150d31fa9d5e40625c65b0b10034d" - dependencies: - lodash "^4.15.0" - mkdirp "^0.5.1" - node-object-hash "^1.2.0" - rimraf "^2.6.2" - tapable "^1.0.0-beta.5" - webpack-core "~0.6.0" - webpack-sources "^1.0.1" - write-json-file "^2.3.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-color@~0.1.0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - dependencies: - sparkles "^1.0.0" - -has-symbol-support-x@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - -has-to-string-tag-x@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - dependencies: - has-symbol-support-x "^1.4.1" - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -hash-sum@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.4.tgz#8b50e1f35d51bd01e5ed9ece4dbe3549ccfa0a3c" - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.0" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hawk@~6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - dependencies: - boom "4.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - sntp "2.x.x" - -he@1.1.1, he@1.1.x, he@^1.1.0, he@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - -highlight.js@9.12.0: - version "9.12.0" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" - -hmac-drbg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - -hoek@4.x.x: - version "4.2.1" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" - -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - -homedir-polyfill@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" - dependencies: - parse-passwd "^1.0.0" - -hosted-git-info@^2.1.4: - version "2.6.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz#23235b29ab230c576aab0d4f13fc046b0b038222" - -html-comment-regex@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e" - -html-encoding-sniffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" - dependencies: - whatwg-encoding "^1.0.1" - -html-entities@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" - -html-minifier@3.5.16, html-minifier@^3.0.3: - version "3.5.16" - resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.16.tgz#39f5aabaf78bdfc057fe67334226efd7f3851175" - dependencies: - camel-case "3.0.x" - clean-css "4.1.x" - commander "2.15.x" - he "1.1.x" - param-case "2.1.x" - relateurl "0.2.x" - uglify-js "3.3.x" - -htmlparser2@^3.9.1: - version "3.9.2" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" - dependencies: - domelementtype "^1.3.0" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^2.0.2" - -http-assert@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.3.0.tgz#a31a5cf88c873ecbb5796907d4d6f132e8c01e4a" - dependencies: - deep-equal "~1.0.1" - http-errors "~1.6.1" - -http-cache-semantics@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - -http-errors@1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" - dependencies: - depd "1.1.1" - inherits "2.0.3" - setprototypeof "1.0.3" - statuses ">= 1.3.1 < 2" - -http-errors@1.6.3, http-errors@^1.2.8, http-errors@^1.3.1, http-errors@^1.6.1, http-errors@~1.6.1, http-errors@~1.6.2, http-errors@~1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-signature@1.2.0, http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -http_ece@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/http_ece/-/http_ece-1.0.5.tgz#b60660faaf14215102d1493ea720dcd92b53372f" - dependencies: - urlsafe-base64 "~1.0.0" - -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - -https-proxy-agent@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" - dependencies: - agent-base "^4.1.0" - debug "^3.1.0" - -humanize-ms@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" - dependencies: - ms "^2.0.0" - -humanize-number@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/humanize-number/-/humanize-number-0.0.2.tgz#11c0af6a471643633588588048f1799541489c18" - -iconv-lite@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" - -iconv-lite@0.4.23, iconv-lite@^0.4.17, iconv-lite@^0.4.19, iconv-lite@^0.4.4, iconv-lite@~0.4.13: - version "0.4.23" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" - dependencies: - safer-buffer ">= 2.1.2 < 3" - -icss-replace-symbols@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" - -icss-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962" - dependencies: - postcss "^6.0.1" - -ieee754@^1.1.4: - version "1.1.12" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" - -iferr@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" - -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - dependencies: - minimatch "^3.0.4" - -ignore@^3.3.3, ignore@^3.3.5: - version "3.3.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.8.tgz#3f8e9c35d38708a3a7e0e9abb6c73e7ee7707b2b" - -imagemin-gifsicle@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/imagemin-gifsicle/-/imagemin-gifsicle-5.2.0.tgz#3781524c457612ef04916af34241a2b42bfcb40a" - dependencies: - exec-buffer "^3.0.0" - gifsicle "^3.0.0" - is-gif "^1.0.0" - -imagemin-jpegtran@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/imagemin-jpegtran/-/imagemin-jpegtran-5.0.2.tgz#e6882263b8f7916fddb800640cf75d2e970d2ad6" - dependencies: - exec-buffer "^3.0.0" - is-jpg "^1.0.0" - jpegtran-bin "^3.0.0" - -imagemin-optipng@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/imagemin-optipng/-/imagemin-optipng-5.2.1.tgz#d22da412c09f5ff00a4339960b98a88b1dbe8695" - dependencies: - exec-buffer "^3.0.0" - is-png "^1.0.0" - optipng-bin "^3.0.0" - -imagemin-svgo@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/imagemin-svgo/-/imagemin-svgo-6.0.0.tgz#2dd8c82946be42a8e2cbcae3c5bf007bc2b8b9e8" - dependencies: - buffer-from "^0.1.1" - is-svg "^2.0.0" - svgo "^1.0.0" - -imagemin@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/imagemin/-/imagemin-5.3.1.tgz#f19c2eee1e71ba6c6558c515f9fc96680189a6d4" - dependencies: - file-type "^4.1.0" - globby "^6.1.0" - make-dir "^1.0.0" - p-pipe "^1.1.0" - pify "^2.3.0" - replace-ext "^1.0.0" - -import-local@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" - dependencies: - pkg-dir "^2.0.0" - resolve-cwd "^2.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - -in-publish@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" - -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - dependencies: - repeating "^2.0.0" - -indent-string@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" - -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - -indx@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/indx/-/indx-0.2.3.tgz#15dcf56ee9cf65c0234c513c27fbd580e70fbc50" - -inflation@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/inflation/-/inflation-2.0.0.tgz#8b417e47c28f925a45133d914ca1fd389107f30f" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" - -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - -ini@^1.3.4, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - -inquirer@3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" - dependencies: - ansi-escapes "^1.1.0" - chalk "^1.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.1" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx "^4.1.0" - string-width "^2.0.0" - strip-ansi "^3.0.0" - through "^2.3.6" - -inquirer@5.2.0, inquirer@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-5.2.0.tgz#db350c2b73daca77ff1243962e9f22f099685726" - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.1.0" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^5.5.2" - string-width "^2.1.0" - strip-ansi "^4.0.0" - through "^2.3.6" - -inquirer@^3.0.6: - version "3.3.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.4" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx-lite "^4.0.8" - rx-lite-aggregates "^4.0.8" - string-width "^2.1.0" - strip-ansi "^4.0.0" - through "^2.3.6" - -interpret@^1.0.0, interpret@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" - -into-stream@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" - dependencies: - from2 "^2.1.1" - p-is-promise "^1.1.0" - -invariant@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - dependencies: - loose-envify "^1.0.0" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - -ip-regex@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd" - -ipaddr.js@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.6.0.tgz#e3fa357b773da619f26e95f049d055c72796f86b" - -irregular-plurals@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-1.4.0.tgz#2ca9b033651111855412f16be5d77c62a458a766" - -is-absolute-url@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - -is-absolute@^0.1.5: - version "0.1.7" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-0.1.7.tgz#847491119fccb5fb436217cc737f7faad50f603f" - dependencies: - is-relative "^0.1.0" - -is-absolute@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" - dependencies: - is-relative "^1.0.0" - is-windows "^1.0.1" - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - dependencies: - kind-of "^6.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - dependencies: - builtin-modules "^1.0.0" - -is-bzip2@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-bzip2/-/is-bzip2-1.0.0.tgz#5ee58eaa5a2e9c80e21407bedf23ae5ac091b3fc" - -is-callable@^1.1.1, is-callable@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - dependencies: - kind-of "^6.0.0" - -is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - dependencies: - is-primitive "^2.0.0" - -is-expression@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-3.0.0.tgz#39acaa6be7fd1f3471dc42c7416e61c24317ac9f" - dependencies: - acorn "~4.0.2" - object-assign "^4.0.1" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - -is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - -is-generator-function@^1.0.3: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" - -is-gif@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-gif/-/is-gif-1.0.0.tgz#a6d2ae98893007bffa97a1d8c01d63205832097e" - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - dependencies: - is-extglob "^2.1.1" - -is-gzip@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-gzip/-/is-gzip-1.0.0.tgz#6ca8b07b99c77998025900e555ced8ed80879a83" - -is-jpg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-jpg/-/is-jpg-1.0.1.tgz#296d57fdd99ce010434a7283e346ab9a1035e975" - -is-my-ip-valid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" - -is-my-json-valid@^2.12.4: - version "2.17.2" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c" - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -is-natural-number@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-2.1.1.tgz#7d4c5728377ef386c3e194a9911bf57c6dc335e7" - -is-negated-glob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - dependencies: - kind-of "^3.0.2" - -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - -is-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - -is-observable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" - dependencies: - symbol-observable "^1.1.0" - -is-odd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" - dependencies: - is-number "^4.0.0" - -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - -is-path-in-cwd@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" - dependencies: - is-path-inside "^1.0.0" - -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - dependencies: - path-is-inside "^1.0.1" - -is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - -is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - dependencies: - isobject "^3.0.1" - -is-png@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-png/-/is-png-1.1.0.tgz#d574b12bf275c0350455570b0e5b57ab062077ce" - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - -is-promise@^2.0.0, is-promise@^2.1, is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - -is-redirect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" - -is-regex@^1.0.3, is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - dependencies: - has "^1.0.1" - -is-relative@^0.1.0: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.1.3.tgz#905fee8ae86f45b3ec614bc3c15c869df0876e82" - -is-relative@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" - dependencies: - is-unc-path "^1.0.0" - -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - -is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" - -is-root@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.0.0.tgz#838d1e82318144e5a6f77819d90207645acc7019" - -is-scoped@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-scoped/-/is-scoped-1.0.0.tgz#449ca98299e713038256289ecb2b540dc437cb30" - dependencies: - scoped-regex "^1.0.0" - -is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - -is-svg@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" - dependencies: - html-comment-regex "^1.1.0" - -is-symbol@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" - -is-tar@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-tar/-/is-tar-1.0.0.tgz#2f6b2e1792c1f5bb36519acaa9d65c0d26fe853d" - -is-there@^4.0.0: - version "4.4.3" - resolved "https://registry.yarnpkg.com/is-there/-/is-there-4.4.3.tgz#a2c49366c6a487f719dbcad80cbde21248d2c18d" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - -is-unc-path@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" - dependencies: - unc-path-regex "^0.1.2" - -is-url@1.2.4, is-url@^1.2.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" - -is-utf8@^0.2.0, is-utf8@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - -is-valid-glob@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" - -is-valid-glob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" - -is-whitespace@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f" - -is-windows@^1.0.1, is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - -is-zip@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-zip/-/is-zip-1.0.0.tgz#47b0a8ff4d38a76431ccfd99a8e15a4c86ba2325" - -is2@0.0.9: - version "0.0.9" - resolved "https://registry.yarnpkg.com/is2/-/is2-0.0.9.tgz#119556d1d1651a41ba105af803267c80b299f629" - dependencies: - deep-is "0.1.2" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isarray@^2.0.1: - version "2.0.4" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.4.tgz#38e7bcbb0f3ba1b7933c86ba1894ddfc3781bbb7" - -isbinaryfile@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -istextorbinary@2.2.1, istextorbinary@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.2.1.tgz#a5231a08ef6dd22b268d0895084cf8d58b5bec53" - dependencies: - binaryextensions "2" - editions "^1.3.3" - textextensions "2" - -isurl@^1.0.0-alpha5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - dependencies: - has-to-string-tag-x "^1.2.0" - is-object "^1.0.1" - -jpegtran-bin@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/jpegtran-bin/-/jpegtran-bin-3.2.0.tgz#f60ecf4ae999c0bdad2e9fbcdf2b6f0981e7a29b" - dependencies: - bin-build "^2.0.0" - bin-wrapper "^3.0.0" - logalot "^2.0.0" - -js-base64@^2.1.8, js-base64@^2.1.9: - version "2.4.5" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.5.tgz#e293cd3c7c82f070d700fc7a1ca0a2e69f101f92" - -js-beautify@^1.6.12: - version "1.7.5" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.7.5.tgz#69d9651ef60dbb649f65527b53674950138a7919" - dependencies: - config-chain "~1.1.5" - editorconfig "^0.13.2" - mkdirp "~0.5.0" - nopt "~3.0.1" - -js-stringify@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" - -js-tokens@^3.0.0, js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - -js-yaml@3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^3.4.6, js-yaml@^3.7.0, js-yaml@^3.8.4, js-yaml@^3.9.1: - version "3.12.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@~3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@~3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" - dependencies: - argparse "^1.0.7" - esprima "^2.6.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - -jschardet@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.6.0.tgz#c7d1a71edcff2839db2f9ec30fc5d5ebd3c1a678" - -jscodeshift@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.4.1.tgz#da91a1c2eccfa03a3387a21d39948e251ced444a" - dependencies: - async "^1.5.0" - babel-plugin-transform-flow-strip-types "^6.8.0" - babel-preset-es2015 "^6.9.0" - babel-preset-stage-1 "^6.5.0" - babel-register "^6.9.0" - babylon "^6.17.3" - colors "^1.1.2" - flow-parser "^0.*" - lodash "^4.13.1" - micromatch "^2.3.7" - node-dir "0.1.8" - nomnom "^1.8.1" - recast "^0.12.5" - temp "^0.8.1" - write-file-atomic "^1.2.0" - -jscodeshift@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.5.1.tgz#4af6a721648be8638ae1464a190342da52960c33" - dependencies: - babel-plugin-transform-flow-strip-types "^6.8.0" - babel-preset-es2015 "^6.9.0" - babel-preset-stage-1 "^6.5.0" - babel-register "^6.9.0" - babylon "^7.0.0-beta.47" - colors "^1.1.2" - flow-parser "^0.*" - lodash "^4.13.1" - micromatch "^2.3.7" - neo-async "^2.5.0" - node-dir "0.1.8" - nomnom "^1.8.1" - recast "^0.15.0" - temp "^0.8.1" - write-file-atomic "^1.2.0" - -jsdom@11.11.0: - version "11.11.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.11.0.tgz#df486efad41aee96c59ad7a190e2449c7eb1110e" - dependencies: - abab "^1.0.4" - acorn "^5.3.0" - acorn-globals "^4.1.0" - array-equal "^1.0.0" - cssom ">= 0.3.2 < 0.4.0" - cssstyle ">= 0.3.1 < 0.4.0" - data-urls "^1.0.0" - domexception "^1.0.0" - escodegen "^1.9.0" - html-encoding-sniffer "^1.0.2" - left-pad "^1.2.0" - nwsapi "^2.0.0" - parse5 "4.0.0" - pn "^1.1.0" - request "^2.83.0" - request-promise-native "^1.0.5" - sax "^1.2.4" - symbol-tree "^3.2.2" - tough-cookie "^2.3.3" - w3c-hr-time "^1.0.1" - webidl-conversions "^4.0.2" - whatwg-encoding "^1.0.3" - whatwg-mimetype "^2.1.0" - whatwg-url "^6.4.1" - ws "^4.0.0" - xml-name-validator "^3.0.0" - -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - -json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - -json-schema-ref-parser@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/json-schema-ref-parser/-/json-schema-ref-parser-1.4.1.tgz#c0c2e438bf0796723b02451bae8bc7dd0b37fed0" - dependencies: - call-me-maybe "^1.0.1" - debug "^2.2.0" - es6-promise "^3.0.2" - js-yaml "^3.4.6" - ono "^2.0.1" - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - -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" - -json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - -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" - -json5@0.5.1, json5@^0.5.0, json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - 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" - dependencies: - is-promise "^2.0.0" - promise "^7.0.1" - -jwa@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.1.6.tgz#87240e76c9808dbde18783cf2264ef4929ee50e6" - dependencies: - buffer-equal-constant-time "1.0.1" - ecdsa-sig-formatter "1.0.10" - safe-buffer "^5.0.1" - -jws@^3.1.3: - version "3.1.5" - resolved "https://registry.yarnpkg.com/jws/-/jws-3.1.5.tgz#80d12d05b293d1e841e7cb8b4e69e561adcf834f" - dependencies: - jwa "^1.1.5" - safe-buffer "^5.0.1" - -keygrip@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.2.tgz#ad3297c557069dea8bcfe7a4fa491b75c5ddeb91" - -keyv@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" - dependencies: - json-buffer "3.0.0" - -kind-of@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - -koa-bodyparser@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/koa-bodyparser/-/koa-bodyparser-4.2.1.tgz#4d7dacb5e6db1106649b595d9e5ccb158b6f3b29" - dependencies: - co-body "^6.0.0" - copy-to "^2.0.1" - -koa-compose@^3.0.0, koa-compose@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-3.2.1.tgz#a85ccb40b7d986d8e5a345b3a1ace8eabcf54de7" - dependencies: - any-promise "^1.1.0" - -koa-compose@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-4.1.0.tgz#507306b9371901db41121c812e923d0d67d3e877" - -koa-compress@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/koa-compress/-/koa-compress-3.0.0.tgz#3194059c215cbc24e59bbc84c2c7453a4c88564f" - dependencies: - bytes "^3.0.0" - compressible "^2.0.0" - koa-is-json "^1.0.0" - statuses "^1.0.0" - -koa-convert@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/koa-convert/-/koa-convert-1.2.0.tgz#da40875df49de0539098d1700b50820cebcd21d0" - dependencies: - co "^4.6.0" - koa-compose "^3.0.0" - -koa-favicon@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/koa-favicon/-/koa-favicon-2.0.1.tgz#cfae363e5fd00bd5dd67c1150fbef31e0b5d6f4d" - dependencies: - mz "^2.7.0" - -koa-is-json@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/koa-is-json/-/koa-is-json-1.0.0.tgz#273c07edcdcb8df6a2c1ab7d59ee76491451ec14" - -koa-json-body@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/koa-json-body/-/koa-json-body-5.3.0.tgz#64aad3f400adfb81df54b63f7a5eb38bad62d980" - dependencies: - co-body "^5.0.0" - -koa-logger@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/koa-logger/-/koa-logger-3.2.0.tgz#8aef64d8b848fb6253a9b31aa708d0e05141f0e6" - dependencies: - bytes "^2.5.0" - chalk "^1.1.3" - humanize-number "0.0.2" - passthrough-counter "^1.0.0" - -koa-mount@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/koa-mount/-/koa-mount-3.0.0.tgz#08cab3b83d31442ed8b7e75c54b1abeb922ec197" - dependencies: - debug "^2.6.1" - koa-compose "^3.2.1" - -koa-multer@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/koa-multer/-/koa-multer-1.0.2.tgz#d38f7ffd1db97b1aad33e7774732f000ebd67259" - dependencies: - multer "1.3.0" - -koa-router@7.4.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/koa-router/-/koa-router-7.4.0.tgz#aee1f7adc02d5cb31d7d67465c9eacc825e8c5e0" - dependencies: - debug "^3.1.0" - http-errors "^1.3.1" - koa-compose "^3.0.0" - methods "^1.0.1" - path-to-regexp "^1.1.1" - urijs "^1.19.0" - -koa-send@4.1.3, koa-send@^4.0.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/koa-send/-/koa-send-4.1.3.tgz#0822207bbf5253a414c8f1765ebc29fa41353cb6" - dependencies: - debug "^2.6.3" - http-errors "^1.6.1" - mz "^2.6.0" - resolve-path "^1.4.0" - -koa-slow@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/koa-slow/-/koa-slow-2.1.0.tgz#39007ca628c620f2b307b90dbf423d7a0c9be971" - dependencies: - lodash.isregexp "3.0.5" - q "1.4.1" - -koa-views@6.1.4: - version "6.1.4" - resolved "https://registry.yarnpkg.com/koa-views/-/koa-views-6.1.4.tgz#595eb683ca17d8dfaa1d100b42ba4e34c762154d" - dependencies: - consolidate "^0.15.0" - debug "^3.1.0" - get-paths "^0.0.2" - koa-send "^4.0.0" - mz "^2.4.0" - pretty "^2.0.0" - -koa@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/koa/-/koa-2.5.1.tgz#79f8b95f8d72d04fe9a58a8da5ebd6d341103f9c" - dependencies: - accepts "^1.2.2" - content-disposition "~0.5.0" - content-type "^1.0.0" - cookies "~0.7.0" - debug "*" - delegates "^1.0.0" - depd "^1.1.0" - destroy "^1.0.3" - error-inject "~1.0.0" - escape-html "~1.0.1" - fresh "^0.5.2" - http-assert "^1.1.0" - http-errors "^1.2.8" - is-generator-function "^1.0.3" - koa-compose "^4.0.0" - koa-convert "^1.2.0" - koa-is-json "^1.0.0" - mime-types "^2.0.7" - on-finished "^2.1.0" - only "0.0.2" - parseurl "^1.3.0" - statuses "^1.2.0" - type-is "^1.5.5" - vary "^1.0.0" - -kue@0.11.6: - version "0.11.6" - resolved "https://registry.yarnpkg.com/kue/-/kue-0.11.6.tgz#5b76916bcedd56636a107861471c63c94611860a" - dependencies: - body-parser "^1.12.2" - express "^4.12.2" - lodash "^4.0.0" - nib "~1.1.2" - node-redis-warlock "~0.2.0" - pug "^2.0.0-beta3" - redis "~2.6.0-2" - stylus "~0.54.5" - yargs "^4.0.0" - optionalDependencies: - reds "^0.2.5" - -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - -lazy-req@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/lazy-req/-/lazy-req-1.1.0.tgz#bdaebead30f8d824039ce0ce149d4daa07ba1fac" - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - dependencies: - readable-stream "^2.0.5" - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - dependencies: - invert-kv "^1.0.0" - -lead@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" - dependencies: - flush-write-stream "^1.0.2" - -leb@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/leb/-/leb-0.3.0.tgz#32bee9fad168328d6aea8522d833f4180eed1da3" - -left-pad@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" - -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -license-checker@20.0.0: - version "20.0.0" - resolved "https://registry.yarnpkg.com/license-checker/-/license-checker-20.0.0.tgz#29b338ba7f4e841b850cc59ddd393dbc8927f375" - dependencies: - chalk "^2.4.1" - debug "^3.1.0" - mkdirp "^0.5.1" - nopt "^4.0.1" - read-installed "~4.0.3" - semver "^5.5.0" - spdx "^0.5.1" - spdx-correct "^3.0.0" - spdx-satisfies "^4.0.0" - strip-ansi "^4.0.0" - treeify "^1.1.0" - -liftoff@^2.1.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec" - dependencies: - extend "^3.0.0" - findup-sync "^2.0.0" - fined "^1.0.1" - flagged-respawn "^1.0.0" - is-plain-object "^2.0.4" - object.map "^1.0.0" - rechoir "^0.6.2" - resolve "^1.1.7" - -listr-silent-renderer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" - -listr-update-renderer@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz#344d980da2ca2e8b145ba305908f32ae3f4cc8a7" - dependencies: - chalk "^1.1.3" - cli-truncate "^0.2.1" - elegant-spinner "^1.0.1" - figures "^1.7.0" - indent-string "^3.0.0" - log-symbols "^1.0.2" - log-update "^1.0.2" - strip-ansi "^3.0.1" - -listr-verbose-renderer@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" - dependencies: - chalk "^1.1.3" - cli-cursor "^1.0.2" - date-fns "^1.27.2" - figures "^1.7.0" - -listr@^0.14.1: - version "0.14.1" - resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.1.tgz#8a7afa4a7135cee4c921d128e0b7dfc6e522d43d" - dependencies: - "@samverschueren/stream-to-observable" "^0.3.0" - cli-truncate "^0.2.1" - figures "^1.7.0" - indent-string "^2.1.0" - is-observable "^1.1.0" - is-promise "^2.1.0" - is-stream "^1.1.0" - listr-silent-renderer "^1.1.1" - listr-update-renderer "^0.4.0" - listr-verbose-renderer "^0.4.0" - log-symbols "^1.0.2" - log-update "^1.0.2" - ora "^0.2.3" - p-map "^1.1.1" - rxjs "^6.1.0" - strip-ansi "^3.0.1" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - -loader-runner@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" - -loader-utils@1.1.0, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" - dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - -lodash._bindcallback@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" - -lodash._createassigner@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11" - dependencies: - lodash._bindcallback "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash.restparam "^3.0.0" - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - -lodash.assign@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa" - dependencies: - lodash._baseassign "^3.0.0" - lodash._createassigner "^3.0.0" - lodash.keys "^3.0.0" - -lodash.assign@^4.0.3, lodash.assign@^4.0.6, lodash.assign@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - -lodash.assignin@^4.0.9: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" - -lodash.bind@^4.1.4: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - -lodash.clone@^4.3.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" - -lodash.clonedeep@^4.3.2, lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - -lodash.defaults@^4.0.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - dependencies: - lodash._root "^3.0.0" - -lodash.filter@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" - -lodash.flatten@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - -lodash.foreach@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" - -lodash.get@^4.0.0, lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - -lodash.isequal@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - -lodash.isregexp@3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/lodash.isregexp/-/lodash.isregexp-3.0.5.tgz#e0f596242f2fa228a840086b6c8ad82e4b71fd2d" - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.map@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - -lodash.merge@^4.4.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54" - -lodash.mergewith@^4.6.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" - -lodash.partialright@^4.1.4: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.partialright/-/lodash.partialright-4.2.1.tgz#0130d80e83363264d40074f329b8a3e7a8a1cc4b" - -lodash.pick@^4.2.1: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" - -lodash.reduce@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" - -lodash.reject@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - -lodash.some@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - -lodash.sortby@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - -lodash.startcase@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.startcase/-/lodash.startcase-4.4.0.tgz#9436e34ed26093ed7ffae1936144350915d9add8" - -lodash.tail@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - -lodash.unescape@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" - -lodash.uniq@^4.3.0, lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - -lodash@^3.10.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" - -lodash@^4.0.0, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.3.0, lodash@~4.17.10: - version "4.17.10" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" - -lodash@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" - -log-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" - dependencies: - chalk "^1.0.0" - -log-symbols@^2.1.0, log-symbols@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - dependencies: - chalk "^2.0.1" - -log-update@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" - dependencies: - ansi-escapes "^1.0.0" - cli-cursor "^1.0.2" - -logalot@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/logalot/-/logalot-2.1.0.tgz#5f8e8c90d304edf12530951a5554abb8c5e3f552" - dependencies: - figures "^1.3.5" - squeak "^1.0.0" - -long@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" - -longest@^1.0.0, longest@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - -loose-envify@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" - dependencies: - js-tokens "^3.0.0" - -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - -lower-case@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" - -lowercase-keys@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" - -lowercase-keys@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - -lpad-align@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/lpad-align/-/lpad-align-1.1.2.tgz#21f600ac1c3095c3c6e497ee67271ee08481fe9e" - dependencies: - get-stdin "^4.0.1" - indent-string "^2.1.0" - longest "^1.0.0" - meow "^3.3.0" - -lru-cache@2, lru-cache@^2.5.0: - version "2.7.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" - -lru-cache@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" - dependencies: - pseudomap "^1.0.1" - -lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -lru-queue@0.1: - version "0.1.0" - resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" - dependencies: - es5-ext "~0.10.2" - -make-dir@^1.0.0, make-dir@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - dependencies: - pify "^3.0.0" - -make-error-cause@^1.1.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" - dependencies: - make-error "^1.2.0" - -make-error@^1.1.1, make-error@^1.2.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.4.tgz#19978ed575f9e9545d2ff8c13e33b5d18a67d535" - -make-iterator@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" - dependencies: - kind-of "^6.0.2" - -map-cache@^0.2.0, map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - -map-stream@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - dependencies: - object-visit "^1.0.0" - -math-expression-evaluator@^1.2.14: - version "1.2.17" - resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" - -math-random@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" - -md5.js@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -mdn-data@^1.0.0, mdn-data@~1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" - -mecab-async@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/mecab-async/-/mecab-async-0.1.2.tgz#69efb838729216709597a57da2df03922f9b593a" - dependencies: - shell-quote "*" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - -mem-fs-editor@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/mem-fs-editor/-/mem-fs-editor-4.0.2.tgz#55a79b1e824da631254c4c95ba6366602c77af90" - dependencies: - commondir "^1.0.1" - deep-extend "^0.5.1" - ejs "^2.5.9" - glob "^7.0.3" - globby "^8.0.0" - isbinaryfile "^3.0.2" - mkdirp "^0.5.0" - multimatch "^2.0.0" - rimraf "^2.2.8" - through2 "^2.0.0" - vinyl "^2.0.1" - -mem-fs@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/mem-fs/-/mem-fs-1.1.3.tgz#b8ae8d2e3fcb6f5d3f9165c12d4551a065d989cc" - dependencies: - through2 "^2.0.0" - vinyl "^1.1.0" - vinyl-file "^2.0.0" - -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - dependencies: - mimic-fn "^1.0.0" - -memoizee@0.4.X: - version "0.4.12" - resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.12.tgz#780e99a219c50c549be6d0fc61765080975c58fb" - dependencies: - d "1" - es5-ext "^0.10.30" - es6-weak-map "^2.0.2" - event-emitter "^0.3.5" - is-promise "^2.1" - lru-queue "0.1" - next-tick "1" - timers-ext "^0.1.2" - -memory-fs@^0.4.0, memory-fs@~0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -meow@^3.1.0, meow@^3.3.0, meow@^3.5.0, meow@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - -merge-source-map@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" - dependencies: - source-map "^0.6.1" - -merge-stream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - dependencies: - readable-stream "^2.0.1" - -merge2@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.2.tgz#03212e3da8d86c4d8523cebd6318193414f94e34" - -methods@^1.0.1, methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - -micromatch@^2.1.5, micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -"mime-db@>= 1.34.0 < 2": - version "1.34.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.34.0.tgz#452d0ecff5c30346a6dc1e64b1eaee0d3719ff9a" - -mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - -mime-types@^2.0.7, mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - dependencies: - mime-db "~1.33.0" - -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - -mime@^2.0.3: - version "2.3.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369" - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - -mimic-response@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e" - -minimalistic-assert@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - -"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - dependencies: - brace-expansion "^1.1.7" - -minimatch@^2.0.1: - version "2.0.10" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" - dependencies: - brace-expansion "^1.0.0" - -minimatch@~0.2.11: - version "0.2.14" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -minimist@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de" - -minipass@^2.2.1, minipass@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" - dependencies: - minipass "^2.2.1" - -mississippi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f" - dependencies: - concat-stream "^1.5.0" - duplexify "^3.4.2" - end-of-stream "^1.1.0" - flush-write-stream "^1.0.0" - from2 "^2.1.0" - parallel-transform "^1.1.0" - pump "^2.0.1" - pumpify "^1.3.3" - stream-each "^1.1.0" - through2 "^2.0.0" - -mixin-deep@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mixin-object@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e" - dependencies: - for-in "^0.1.3" - is-extendable "^0.1.1" - -mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -mocha@5.2.0, mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - dependencies: - browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.5" - he "1.1.1" - minimatch "3.0.4" - mkdirp "0.5.1" - supports-color "5.4.0" - -moji@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/moji/-/moji-0.5.1.tgz#088eecd1c22c8f31a240adcf9c95e54f33eb54fb" - dependencies: - object-assign "^3.0.0" - -mongodb-core@2.1.19: - version "2.1.19" - resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.19.tgz#00fbd5e5a3573763b9171cfd844e60a8f2a3a18b" - dependencies: - bson "~1.0.4" - require_optional "~1.0.0" - -mongodb-core@3.0.9: - version "3.0.9" - resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-3.0.9.tgz#8327410c88811013fb3e4ac7c4c670f324349be1" - dependencies: - bson "~1.0.4" - require_optional "^1.0.1" - -mongodb@3.0.10: - version "3.0.10" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.0.10.tgz#f948cb9595adcbfcad7444f6b24a040b653b23e8" - dependencies: - mongodb-core "3.0.9" - -mongodb@^2.1.18: - version "2.2.35" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.35.tgz#cd1b5af8a9463e3f9a787fa5b3d05565579730f9" - dependencies: - es6-promise "3.2.1" - mongodb-core "2.1.19" - readable-stream "2.2.7" - -monk-middleware-cast-ids@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/monk-middleware-cast-ids/-/monk-middleware-cast-ids-0.2.1.tgz#40c40e5a6cb33ccedc289220943275ee8861c529" - -monk-middleware-fields@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/monk-middleware-fields/-/monk-middleware-fields-0.2.0.tgz#ff637af35f5948879ccb2be15a91360911bea6c1" - -monk-middleware-handle-callback@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/monk-middleware-handle-callback/-/monk-middleware-handle-callback-0.2.2.tgz#47de6cc1248726c72a2be0c81bc4e68310c32146" - -monk-middleware-options@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/monk-middleware-options/-/monk-middleware-options-0.2.1.tgz#58dae1c518d46636ebdff506fadfc773bb442886" - -monk-middleware-query@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/monk-middleware-query/-/monk-middleware-query-0.2.0.tgz#a926c677d4a5620c62151b0a56d0c0c151675874" - -monk-middleware-wait-for-connection@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/monk-middleware-wait-for-connection/-/monk-middleware-wait-for-connection-0.2.0.tgz#312958d30e588b57d09754dd7c97b4843316835a" - -monk@6.0.6: - version "6.0.6" - resolved "https://registry.yarnpkg.com/monk/-/monk-6.0.6.tgz#2ff1cd57f001bba0fea73d1eea3952a7d35450c5" - dependencies: - debug "*" - mongodb "^2.1.18" - monk-middleware-cast-ids "^0.2.1" - monk-middleware-fields "^0.2.0" - monk-middleware-handle-callback "^0.2.0" - monk-middleware-options "^0.2.1" - monk-middleware-query "^0.2.0" - monk-middleware-wait-for-connection "^0.2.0" - object-assign "^4.1.1" - -move-concurrently@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - dependencies: - aproba "^1.1.1" - copy-concurrently "^1.0.0" - fs-write-stream-atomic "^1.0.8" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.3" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - -ms@2.1.1, ms@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - -multer@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/multer/-/multer-1.3.0.tgz#092b2670f6846fa4914965efc8cf94c20fec6cd2" - dependencies: - append-field "^0.1.0" - busboy "^0.2.11" - concat-stream "^1.5.0" - mkdirp "^0.5.1" - object-assign "^3.0.0" - on-finished "^2.3.0" - type-is "^1.6.4" - xtend "^4.0.0" - -multimatch@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - dependencies: - duplexer2 "0.0.2" - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - -mz@^2.4.0, mz@^2.6.0, mz@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - dependencies: - any-promise "^1.0.0" - object-assign "^4.0.1" - thenify-all "^1.0.0" - -nan@2.10.0, nan@^2.10.0, nan@^2.3.3, nan@^2.5.0, nan@^2.9.2: - version "2.10.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" - -nanomatch@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-odd "^2.0.0" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -natives@^1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.4.tgz#2f0f224fc9a7dd53407c7667c84cf8dbe773de58" - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - -natural@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/natural/-/natural-0.2.1.tgz#1eb5156a9d90b4591949e20e94ebc77bb2339eda" - dependencies: - apparatus ">= 0.0.9" - sylvester ">= 0.0.12" - underscore ">=1.3.1" - -needle@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" - dependencies: - debug "^2.1.2" - iconv-lite "^0.4.4" - sax "^1.2.4" - -negotiator@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - -neo-async@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.1.tgz#acb909e327b1e87ec9ef15f41b8a269512ad41ee" - -next-tick@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - -nib@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/nib/-/nib-1.1.2.tgz#6a69ede4081b95c0def8be024a4c8ae0c2cbb6c7" - dependencies: - stylus "0.54.5" - -nice-try@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" - -no-case@^2.2.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" - dependencies: - lower-case "^1.1.1" - -node-dir@0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.8.tgz#55fb8deb699070707fb67f91a460f0448294c77d" - -node-fetch@1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-gyp@^3.3.1: - version "3.7.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.7.0.tgz#789478e8f6c45e277aa014f3e28f958f286f9203" - dependencies: - fstream "^1.0.0" - glob "^7.0.3" - graceful-fs "^4.1.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - osenv "0" - request ">=2.9.0 <2.82.0" - rimraf "2" - semver "~5.3.0" - tar "^2.0.0" - which "1" - -node-libs-browser@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^1.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.0" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.10.3" - vm-browserify "0.0.4" - -node-object-hash@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/node-object-hash/-/node-object-hash-1.4.1.tgz#de968492e20c493b8bbc25ad2ee828265fd60934" - -node-pre-gyp@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz#6e4ef5bb5c5203c6552448828c852c40111aac46" - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.0" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.1.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -node-redis-scripty@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/node-redis-scripty/-/node-redis-scripty-0.0.5.tgz#4bf2d365ab6dab202cc08b7ac63f8f55aadc9625" - dependencies: - extend "^1.2.1" - lru-cache "^2.5.0" - -node-redis-warlock@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/node-redis-warlock/-/node-redis-warlock-0.2.0.tgz#56395b994c828e8e32f6aae53b93b6edfcd97990" - dependencies: - node-redis-scripty "0.0.5" - uuid "^2.0.1" - -node-sass-json-importer@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/node-sass-json-importer/-/node-sass-json-importer-3.2.0.tgz#9cfe2355035d5437b7c2ecb535450bf6acde8195" - dependencies: - is-there "^4.0.0" - json5 "0.5.1" - lodash "^3.10.1" - -node-sass@4.9.0: - version "4.9.0" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.9.0.tgz#d1b8aa855d98ed684d6848db929a20771cc2ae52" - dependencies: - async-foreach "^0.1.3" - chalk "^1.1.1" - cross-spawn "^3.0.0" - gaze "^1.0.0" - get-stdin "^4.0.1" - glob "^7.0.3" - in-publish "^2.0.0" - lodash.assign "^4.2.0" - lodash.clonedeep "^4.3.2" - lodash.mergewith "^4.6.0" - meow "^3.7.0" - mkdirp "^0.5.1" - nan "^2.10.0" - node-gyp "^3.3.1" - npmlog "^4.0.0" - request "~2.79.0" - sass-graph "^2.2.4" - stdout-stream "^1.4.0" - "true-case-path" "^1.0.2" - -node-status-codes@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f" - -nomnom@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7" - dependencies: - chalk "~0.4.0" - underscore "~1.6.0" - -"nopt@2 || 3", nopt@~3.0.1: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - dependencies: - abbrev "1" - -nopt@4.0.1, nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - dependencies: - hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - -normalize-url@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" - dependencies: - prepend-http "^2.0.0" - query-string "^5.0.1" - sort-keys "^2.0.0" - -normalize-url@^1.4.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" - dependencies: - object-assign "^4.0.1" - prepend-http "^1.0.0" - query-string "^4.1.0" - sort-keys "^1.0.0" - -normalize-wheel@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz#aec886affdb045070d856447df62ecf86146ec45" - -now-and-later@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.0.tgz#bc61cbb456d79cb32207ce47ca05136ff2e7d6ee" - dependencies: - once "^1.3.2" - -npm-bundled@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" - -npm-packlist@^1.1.6: - version "1.1.10" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a" - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npm-run-path@^2.0.0, npm-run-path@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - dependencies: - path-key "^2.0.0" - -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -nprogress@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" - -nth-check@^1.0.1, nth-check@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" - dependencies: - boolbase "~1.0.0" - -num2fraction@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - -nwsapi@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.3.tgz#3f4010d6c943f34018d3dfb5f2fbc0de90476959" - -oauth-sign@~0.8.1, oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - -oauth@0.9.15: - version "0.9.15" - resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" - -object-assign-deep@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-assign-deep/-/object-assign-deep-0.4.0.tgz#43505d3679abb9686ab359b97ac14cc837a9d143" - -object-assign@4.X, object-assign@^4.0.0, 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" - -object-assign@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa" - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-keys@^1.0.11, object-keys@^1.0.8: - version "1.0.11" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - dependencies: - isobject "^3.0.0" - -object.assign@^4.0.1, object.assign@^4.0.4: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.defaults@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" - dependencies: - array-each "^1.0.1" - array-slice "^1.0.0" - for-own "^1.0.0" - isobject "^3.0.0" - -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" - -object.map@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" - dependencies: - for-own "^1.0.0" - make-iterator "^1.0.0" - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -object.pick@^1.2.0, object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - dependencies: - isobject "^3.0.1" - -object.values@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" - dependencies: - define-properties "^1.1.2" - es-abstract "^1.6.1" - function-bind "^1.1.0" - has "^1.0.1" - -on-build-webpack@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/on-build-webpack/-/on-build-webpack-0.1.0.tgz#a287c0e17766e6141926e5f2cbb0d8bb53b76814" - -on-finished@^2.1.0, on-finished@^2.3.0, on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -once@~1.3.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" - dependencies: - wrappy "1" - -onetime@^1.0.0: - version "1.1.0" - resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - dependencies: - mimic-fn "^1.0.0" - -only@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" - -ono@^2.0.1: - version "2.2.5" - resolved "https://registry.yarnpkg.com/ono/-/ono-2.2.5.tgz#daf09488b51174da7a7e4275dfab31b438ffa0e3" - -ono@^4.0.2: - version "4.0.5" - resolved "https://registry.yarnpkg.com/ono/-/ono-4.0.5.tgz#bc62740493a5c1c08b2c21e60cbb0e5c56ab7de2" - dependencies: - format-util "^1.0.3" - -opencollective@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/opencollective/-/opencollective-1.0.3.tgz#aee6372bc28144583690c3ca8daecfc120dd0ef1" - dependencies: - babel-polyfill "6.23.0" - chalk "1.1.3" - inquirer "3.0.6" - minimist "1.2.0" - node-fetch "1.6.3" - opn "4.0.2" - -opn@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/opn/-/opn-4.0.2.tgz#7abc22e644dff63b0a96d5ab7f2790c0f01abc95" - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - -optionator@^0.8.1, optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -optipng-bin@^3.0.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/optipng-bin/-/optipng-bin-3.1.4.tgz#95d34f2c488704f6fd70606bfea0c659f1d95d84" - dependencies: - bin-build "^2.0.0" - bin-wrapper "^3.0.0" - logalot "^2.0.0" - -ora@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" - dependencies: - chalk "^1.1.1" - cli-cursor "^1.0.2" - cli-spinners "^0.1.2" - object-assign "^4.0.1" - -orchestrator@^0.3.0: - version "0.3.8" - resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" - dependencies: - end-of-stream "~0.1.5" - sequencify "~0.0.7" - stream-consume "~0.1.0" - -ordered-read-streams@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz#fd565a9af8eb4473ba69b6ed8a34352cb552f126" - -ordered-read-streams@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" - dependencies: - is-stream "^1.0.1" - readable-stream "^2.0.1" - -ordered-read-streams@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" - dependencies: - readable-stream "^2.0.1" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - -os-filter-obj@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/os-filter-obj/-/os-filter-obj-1.0.3.tgz#5915330d90eced557d2d938a31c6dd214d9c63ad" - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - dependencies: - lcid "^1.0.0" - -os-locale@^2.0.0, os-locale@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - -os-shim@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" - -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - -os-utils@0.0.14: - version "0.0.14" - resolved "https://registry.yarnpkg.com/os-utils/-/os-utils-0.0.14.tgz#29e511697b1982b8c627722175fe39797ef64156" - -osenv@0, osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -p-cancelable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - -p-cancelable@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" - -p-each-series@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71" - dependencies: - p-reduce "^1.0.0" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - -p-is-promise@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" - -p-lazy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-lazy/-/p-lazy-1.0.0.tgz#ec53c802f2ee3ac28f166cc82d0b2b02de27a835" - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - dependencies: - p-try "^1.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - dependencies: - p-limit "^1.1.0" - -p-map@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" - -p-pipe@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9" - -p-reduce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" - -p-timeout@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - dependencies: - p-finally "^1.0.0" - -p-timeout@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" - dependencies: - p-finally "^1.0.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - -pako@~1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" - -parallel-transform@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" - dependencies: - cyclist "~0.2.2" - inherits "^2.0.3" - readable-stream "^2.1.5" - -param-case@2.1.x: - version "2.1.1" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" - dependencies: - no-case "^2.2.0" - -parse-asn1@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" - dependencies: - asn1.js "^4.0.0" - browserify-aes "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - -parse-filepath@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" - dependencies: - is-absolute "^1.0.0" - map-cache "^0.2.0" - path-root "^0.1.1" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parse-json@^2.1.0, parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - dependencies: - error-ex "^1.2.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - -parse5@*, parse5@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.0.0.tgz#4d02710d44f3c3846197a11e205d4ef17842b81a" - -parse5@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" - -parse5@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" - dependencies: - "@types/node" "*" - -parseurl@^1.3.0, parseurl@~1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - -passthrough-counter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/passthrough-counter/-/passthrough-counter-1.0.0.tgz#1967d9e66da572b5c023c787db112a387ab166fa" - -path-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - -path-is-absolute@1.0.1, path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -path-is-inside@^1.0.1, path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - -path-parse@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" - -path-root-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" - -path-root@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" - dependencies: - path-root-regex "^0.1.0" - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - -path-to-regexp@^1.1.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" - dependencies: - isarray "0.0.1" - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - dependencies: - pify "^2.0.0" - -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - dependencies: - pify "^3.0.0" - -pbkdf2@^3.0.3: - version "3.0.16" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.16.tgz#7404208ec6b01b62d85bf83853a8064f8d9c2a5c" - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - -pify@^2.0.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - dependencies: - find-up "^2.1.0" - -plugin-error@1.0.1, plugin-error@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c" - dependencies: - ansi-colors "^1.0.1" - arr-diff "^4.0.0" - arr-union "^3.1.0" - extend-shallow "^3.0.2" - -plugin-error@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" - dependencies: - ansi-cyan "^0.1.1" - ansi-red "^0.1.1" - arr-diff "^1.0.1" - arr-union "^2.0.1" - extend-shallow "^1.1.2" - -plur@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/plur/-/plur-2.1.2.tgz#7482452c1a0f508e3e344eaec312c91c29dc655a" - dependencies: - irregular-plurals "^1.0.0" - -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - -pn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" - -pngjs@^3.3.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.3.tgz#85173703bde3edac8998757b96e5821d0966a21b" - -popper.js@^1.12.9: - version "1.14.3" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - -postcss-calc@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" - dependencies: - postcss "^5.0.2" - postcss-message-helpers "^2.0.0" - reduce-css-calc "^1.2.6" - -postcss-colormin@^2.1.8: - version "2.2.2" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" - dependencies: - colormin "^1.0.5" - postcss "^5.0.13" - postcss-value-parser "^3.2.3" - -postcss-convert-values@^2.3.4: - version "2.6.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" - dependencies: - postcss "^5.0.11" - postcss-value-parser "^3.1.2" - -postcss-discard-comments@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" - dependencies: - postcss "^5.0.14" - -postcss-discard-duplicates@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" - dependencies: - postcss "^5.0.4" - -postcss-discard-empty@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" - dependencies: - postcss "^5.0.14" - -postcss-discard-overridden@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" - dependencies: - postcss "^5.0.16" - -postcss-discard-unused@^2.2.1: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" - dependencies: - postcss "^5.0.14" - uniqs "^2.0.0" - -postcss-filter-plugins@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz#82245fdf82337041645e477114d8e593aa18b8ec" - dependencies: - postcss "^5.0.4" - -postcss-merge-idents@^2.1.5: - version "2.1.7" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" - dependencies: - has "^1.0.1" - postcss "^5.0.10" - postcss-value-parser "^3.1.1" - -postcss-merge-longhand@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" - dependencies: - postcss "^5.0.4" - -postcss-merge-rules@^2.0.3: - version "2.1.2" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" - dependencies: - browserslist "^1.5.2" - caniuse-api "^1.5.2" - postcss "^5.0.4" - postcss-selector-parser "^2.2.2" - vendors "^1.0.0" - -postcss-message-helpers@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" - -postcss-minify-font-values@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" - dependencies: - object-assign "^4.0.1" - postcss "^5.0.4" - postcss-value-parser "^3.0.2" - -postcss-minify-gradients@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" - dependencies: - postcss "^5.0.12" - postcss-value-parser "^3.3.0" - -postcss-minify-params@^1.0.4: - version "1.2.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" - dependencies: - alphanum-sort "^1.0.1" - postcss "^5.0.2" - postcss-value-parser "^3.0.2" - uniqs "^2.0.0" - -postcss-minify-selectors@^2.0.4: - version "2.1.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" - dependencies: - alphanum-sort "^1.0.2" - has "^1.0.1" - postcss "^5.0.14" - postcss-selector-parser "^2.0.0" - -postcss-modules-extract-imports@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz#66140ecece38ef06bf0d3e355d69bf59d141ea85" - dependencies: - postcss "^6.0.1" - -postcss-modules-local-by-default@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" - dependencies: - css-selector-tokenizer "^0.7.0" - postcss "^6.0.1" - -postcss-modules-scope@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" - dependencies: - css-selector-tokenizer "^0.7.0" - postcss "^6.0.1" - -postcss-modules-values@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" - dependencies: - icss-replace-symbols "^1.1.0" - postcss "^6.0.1" - -postcss-normalize-charset@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" - dependencies: - postcss "^5.0.5" - -postcss-normalize-url@^3.0.7: - version "3.0.8" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" - dependencies: - is-absolute-url "^2.0.0" - normalize-url "^1.4.0" - postcss "^5.0.14" - postcss-value-parser "^3.2.3" - -postcss-ordered-values@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" - dependencies: - postcss "^5.0.4" - postcss-value-parser "^3.0.1" - -postcss-reduce-idents@^2.2.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" - dependencies: - postcss "^5.0.4" - postcss-value-parser "^3.0.2" - -postcss-reduce-initial@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" - dependencies: - postcss "^5.0.4" - -postcss-reduce-transforms@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" - dependencies: - has "^1.0.1" - postcss "^5.0.8" - postcss-value-parser "^3.0.1" - -postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" - dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" - dependencies: - dot-prop "^4.1.1" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-svgo@^2.1.1: - version "2.1.6" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" - dependencies: - is-svg "^2.0.0" - postcss "^5.0.14" - postcss-value-parser "^3.2.3" - svgo "^0.7.0" - -postcss-unique-selectors@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" - dependencies: - alphanum-sort "^1.0.1" - postcss "^5.0.4" - uniqs "^2.0.0" - -postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" - -postcss-zindex@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" - dependencies: - has "^1.0.1" - postcss "^5.0.4" - uniqs "^2.0.0" - -postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16: - version "5.2.18" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" - dependencies: - chalk "^1.1.3" - js-base64 "^2.1.9" - source-map "^0.5.6" - supports-color "^3.2.3" - -postcss@^6.0.1, postcss@^6.0.20: - version "6.0.22" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.22.tgz#e23b78314905c3b90cbd61702121e7a78848f2a3" - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - -prepend-http@^1.0.0, prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - -prettier@^1.12.1, prettier@^1.13.0: - version "1.13.5" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.5.tgz#7ae2076998c8edce79d63834e9b7b09fead6bfd0" - -pretty-bytes@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9" - -pretty-hrtime@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" - -pretty@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pretty/-/pretty-2.0.0.tgz#adbc7960b7bbfe289a557dc5f737619a220d06a5" - dependencies: - condense-newlines "^0.2.1" - extend-shallow "^2.0.1" - js-beautify "^1.6.12" - -prettyjson@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prettyjson/-/prettyjson-1.2.1.tgz#fcffab41d19cab4dfae5e575e64246619b12d289" - dependencies: - colors "^1.1.2" - minimist "^1.2.0" - -printj@~1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" - -private@^0.1.6, private@^0.1.8, private@~0.1.5: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - -process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - -progress-bar-webpack-plugin@1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/progress-bar-webpack-plugin/-/progress-bar-webpack-plugin-1.11.0.tgz#4f801288443c55ec029b20cbfdcbf3e1dc17f852" - dependencies: - chalk "^1.1.1" - object.assign "^4.0.1" - progress "^1.1.8" - -progress@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" - -progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" - -prominence@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/prominence/-/prominence-0.2.0.tgz#38704264981ddf65e5b00b0b5cfce6e53348f2b2" - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - -promise-sequential@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/promise-sequential/-/promise-sequential-1.1.1.tgz#f79e8950ef86e7a7a85bf320452643592f6d2fb2" - -promise@^7.0.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - dependencies: - asap "~2.0.3" - -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - -proxy-addr@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341" - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.6.0" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - -pseudomap@^1.0.1, pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - -psl@^1.1.24: - version "1.1.28" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.28.tgz#4fb6ceb08a1e2214d4fd4de0ca22dae13740bc7b" - -public-encrypt@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.2.tgz#46eb9107206bf73489f8b85b69d91334c6610994" - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - -pug-attrs@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-2.0.3.tgz#a3095f970e64151f7bdad957eef55fb5d7905d15" - dependencies: - constantinople "^3.0.1" - js-stringify "^1.0.1" - pug-runtime "^2.0.4" - -pug-code-gen@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-2.0.1.tgz#0951ec83225d74d8cfc476a7f99a259b5f7d050c" - dependencies: - constantinople "^3.0.1" - doctypes "^1.1.0" - js-stringify "^1.0.1" - pug-attrs "^2.0.3" - pug-error "^1.3.2" - pug-runtime "^2.0.4" - void-elements "^2.0.1" - with "^5.0.0" - -pug-error@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-1.3.2.tgz#53ae7d9d29bb03cf564493a026109f54c47f5f26" - -pug-filters@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-3.1.0.tgz#27165555bc04c236e4aa2b0366246dfa021b626e" - dependencies: - clean-css "^4.1.11" - constantinople "^3.0.1" - jstransformer "1.0.0" - pug-error "^1.3.2" - pug-walk "^1.1.7" - resolve "^1.1.6" - uglify-js "^2.6.1" - -pug-lexer@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-4.0.0.tgz#210c18457ef2e1760242740c5e647bd794cec278" - dependencies: - character-parser "^2.1.1" - is-expression "^3.0.0" - pug-error "^1.3.2" - -pug-linker@^3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.5.tgz#9e9a7ae4005682d027deeb96b000f88eeb83a02f" - dependencies: - pug-error "^1.3.2" - pug-walk "^1.1.7" - -pug-load@^2.0.11: - version "2.0.11" - resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.11.tgz#e648e57ed113fe2c1f45d57858ea2bad6bc01527" - dependencies: - object-assign "^4.1.0" - pug-walk "^1.1.7" - -pug-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-5.0.0.tgz#e394ad9b3fca93123940aff885c06e44ab7e68e4" - dependencies: - pug-error "^1.3.2" - token-stream "0.0.1" - -pug-runtime@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-2.0.4.tgz#e178e1bda68ab2e8c0acfc9bced2c54fd88ceb58" - -pug-strip-comments@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-1.0.3.tgz#f1559592206edc6f85310dacf4afb48a025af59f" - dependencies: - pug-error "^1.3.2" - -pug-walk@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.7.tgz#c00d5c5128bac5806bec15d2b7e7cdabe42531f3" - -pug@2.0.3, pug@^2.0.0-beta3, pug@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.3.tgz#71cba82537c95a5eab7ed04696e4221f53aa878e" - dependencies: - pug-code-gen "^2.0.1" - pug-filters "^3.1.0" - pug-lexer "^4.0.0" - pug-linker "^3.0.5" - pug-load "^2.0.11" - pug-parser "^5.0.0" - pug-runtime "^2.0.4" - pug-strip-comments "^1.0.3" - -pump@^2.0.0, pump@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^1.3.3, pumpify@^1.3.5: - version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - dependencies: - duplexify "^3.6.0" - inherits "^2.0.3" - pump "^2.0.0" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - -punycode@2.1.1, punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - -punycode@^1.2.4, punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - -q@0.9.7: - version "0.9.7" - resolved "https://registry.yarnpkg.com/q/-/q-0.9.7.tgz#4de2e6cb3b29088c9e4cbc03bf9d42fb96ce2f75" - -q@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" - -q@^1.1.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - -qrcode@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.2.0.tgz#330d24313fbf8d429a806091af9525250239e44a" - dependencies: - can-promise "^0.0.1" - dijkstrajs "^1.0.1" - isarray "^2.0.1" - pngjs "^3.3.0" - yargs "^8.0.2" - -qs@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - -qs@6.5.2, qs@^6.4.0, qs@^6.5.2, qs@~6.5.1: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - -qs@~6.3.0: - version "6.3.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" - -qs@~6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - -query-string@^4.1.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" - dependencies: - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - dependencies: - decode-uri-component "^0.2.0" - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - -randomatic@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.0.0.tgz#d35490030eb4f7578de292ce6dfb04a91a128923" - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -range-parser@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - -rangestr@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/rangestr/-/rangestr-0.0.1.tgz#f72ff9246f10f2a7d7c16e14616f617be2c2635a" - -ratelimiter@3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/ratelimiter/-/ratelimiter-3.0.3.tgz#6dbca58b05422f2a08e224d4ba3a0cfb86c30966" - -raw-body@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" - dependencies: - bytes "3.0.0" - http-errors "1.6.2" - iconv-lite "0.4.19" - unpipe "1.0.0" - -raw-body@2.3.3, raw-body@^2.2.0, raw-body@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" - dependencies: - bytes "3.0.0" - http-errors "1.6.3" - iconv-lite "0.4.23" - unpipe "1.0.0" - -rc@^1.1.2, rc@^1.1.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -read-all-stream@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/read-all-stream/-/read-all-stream-3.1.0.tgz#35c3e177f2078ef789ee4bfafa4373074eaef4fa" - dependencies: - pinkie-promise "^2.0.0" - readable-stream "^2.0.0" - -read-chunk@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-2.1.0.tgz#6a04c0928005ed9d42e1a6ac5600e19cbc7ff655" - dependencies: - pify "^3.0.0" - safe-buffer "^5.1.1" - -read-installed@~4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/read-installed/-/read-installed-4.0.3.tgz#ff9b8b67f187d1e4c29b9feb31f6b223acd19067" - dependencies: - debuglog "^1.0.1" - read-package-json "^2.0.0" - readdir-scoped-modules "^1.0.0" - semver "2 || 3 || 4 || 5" - slide "~1.1.3" - util-extend "^1.0.1" - optionalDependencies: - graceful-fs "^4.1.2" - -read-package-json@^2.0.0: - version "2.0.13" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.13.tgz#2e82ebd9f613baa6d2ebe3aa72cefe3f68e41f4a" - dependencies: - glob "^7.1.1" - json-parse-better-errors "^1.0.1" - normalize-package-data "^2.0.0" - slash "^1.0.0" - optionalDependencies: - graceful-fs "^4.1.2" - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - dependencies: - find-up "^2.0.0" - read-pkg "^3.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@1.1.x, readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@2.2.7: - version "2.2.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1" - dependencies: - buffer-shims "~1.0.0" - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - string_decoder "~1.0.0" - util-deprecate "~1.0.1" - -"readable-stream@>=1.0.33-1 <1.1.0-0": - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readdir-scoped-modules@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" - dependencies: - debuglog "^1.0.1" - dezalgo "^1.0.0" - graceful-fs "^4.1.2" - once "^1.3.0" - -readdirp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" - dependencies: - graceful-fs "^4.1.2" - minimatch "^3.0.2" - readable-stream "^2.0.2" - set-immediate-shim "^1.0.1" - -recaptcha-promise@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/recaptcha-promise/-/recaptcha-promise-0.1.3.tgz#7d3d66d045a53674054ebdfa1684e0609ef5d912" - dependencies: - bluebird "^3.4.1" - request "^2.73.0" - -recast@^0.12.5: - version "0.12.9" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.12.9.tgz#e8e52bdb9691af462ccbd7c15d5a5113647a15f1" - dependencies: - ast-types "0.10.1" - core-js "^2.4.1" - esprima "~4.0.0" - private "~0.1.5" - source-map "~0.6.1" - -recast@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.15.0.tgz#b8c8bfdda245e1580c0a4d9fc25d4e820bf57208" - dependencies: - ast-types "0.11.5" - esprima "~4.0.0" - private "~0.1.5" - source-map "~0.6.1" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - dependencies: - resolve "^1.1.6" - -reconnecting-websocket@3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-3.2.2.tgz#8097514e926e9855e03c39e76efa2e3d1f371bee" - -recursive-iterator@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/recursive-iterator/-/recursive-iterator-2.0.3.tgz#d0e0d2c7e7a83109d73091cf043fc509e5a76dc3" - -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - -redis-commands@^1.2.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.3.5.tgz#4495889414f1e886261180b1442e7295602d83a2" - -redis-parser@^2.0.0, redis-parser@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-2.6.0.tgz#52ed09dacac108f1a631c07e9b69941e7a19504b" - -redis@2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/redis/-/redis-2.8.0.tgz#202288e3f58c49f6079d97af7a10e1303ae14b02" - dependencies: - double-ended-queue "^2.1.0-0" - redis-commands "^1.2.0" - redis-parser "^2.6.0" - -redis@^0.12.1: - version "0.12.1" - resolved "https://registry.yarnpkg.com/redis/-/redis-0.12.1.tgz#64df76ad0fc8acebaebd2a0645e8a48fac49185e" - -redis@~2.6.0-2: - version "2.6.5" - resolved "https://registry.yarnpkg.com/redis/-/redis-2.6.5.tgz#87c1eff4a489f94b70871f3d08b6988f23a95687" - dependencies: - double-ended-queue "^2.1.0-0" - redis-commands "^1.2.0" - redis-parser "^2.0.0" - -reds@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/reds/-/reds-0.2.5.tgz#38a767f7663cd749036848697d82c74fd29bc01f" - dependencies: - natural "^0.2.0" - redis "^0.12.1" - -reduce-css-calc@^1.2.6: - version "1.3.0" - resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" - dependencies: - balanced-match "^0.4.2" - math-expression-evaluator "^1.2.14" - reduce-function-call "^1.0.1" - -reduce-function-call@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99" - dependencies: - balanced-match "^0.4.2" - -regenerate@^1.2.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - -regenerator-runtime@^0.10.0: - version "0.10.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - dependencies: - is-equal-shallow "^0.1.3" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexpp@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" - -regexpu-core@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - dependencies: - jsesc "~0.5.0" - -relateurl@0.2.x: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - -remove-bom-buffer@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" - dependencies: - is-buffer "^1.1.5" - is-utf8 "^0.2.1" - -remove-bom-stream@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" - dependencies: - remove-bom-buffer "^3.0.0" - safe-buffer "^5.1.0" - through2 "^2.0.3" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - -repeat-string@^1.5.2, repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - dependencies: - is-finite "^1.0.0" - -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - -replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - -replacestream@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/replacestream/-/replacestream-4.0.3.tgz#3ee5798092be364b1cdb1484308492cb3dff2f36" - dependencies: - escape-string-regexp "^1.0.3" - object-assign "^4.0.1" - readable-stream "^2.0.2" - -request-promise-core@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" - dependencies: - lodash "^4.13.1" - -request-promise-native@1.0.5, request-promise-native@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" - dependencies: - request-promise-core "1.1.1" - stealthy-require "^1.1.0" - tough-cookie ">=2.3.3" - -request@2.85.0: - version "2.85.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@2.87.0, request@^2.73.0, request@^2.83.0: - version "2.87.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -"request@>=2.9.0 <2.82.0": - version "2.81.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~4.2.1" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - performance-now "^0.2.0" - qs "~6.4.0" - safe-buffer "^5.0.1" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "^0.6.0" - uuid "^3.0.0" - -request@~2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - -require-all@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/require-all/-/require-all-2.2.0.tgz#b4420c233ac0282d0ff49b277fb880a8b5de0894" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - -require-uncached@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - -require_optional@^1.0.1, require_optional@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e" - dependencies: - resolve-from "^2.0.0" - semver "^5.1.0" - -resize-observer-polyfill@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.0.tgz#660ff1d9712a2382baa2cad450a4716209f9ca69" - -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - dependencies: - resolve-from "^3.0.0" - -resolve-dir@^1.0.0, resolve-dir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - dependencies: - expand-tilde "^2.0.0" - global-modules "^1.0.0" - -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - -resolve-from@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - -resolve-options@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" - dependencies: - value-or-function "^3.0.0" - -resolve-path@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/resolve-path/-/resolve-path-1.4.0.tgz#c4bda9f5efb2fce65247873ab36bb4d834fe16f7" - dependencies: - http-errors "~1.6.2" - path-is-absolute "1.0.1" - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2: - version "1.8.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.0.tgz#a7f2ac27b78480ecc09c83782741d9f26e4f0c3e" - dependencies: - path-parse "^1.0.5" - -responselike@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - dependencies: - lowercase-keys "^1.0.0" - -restore-cursor@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" - dependencies: - exit-hook "^1.0.0" - onetime "^1.0.0" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - -right-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - dependencies: - align-text "^0.1.1" - -rimraf@2, rimraf@2.6.2, rimraf@^2.2.6, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - dependencies: - glob "^7.0.5" - -rimraf@~2.2.6: - version "2.2.8" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rndstr@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/rndstr/-/rndstr-1.0.0.tgz#77e66fa8f9b4836853fdd91e50719591bb67d349" - dependencies: - rangestr "0.0.1" - seedrandom "2.4.2" - -rsvp@^4.7.0: - version "4.8.2" - resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.2.tgz#9d5647108735784eb13418cdddb56f75b919d722" - -run-async@^2.0.0, run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - dependencies: - is-promise "^2.1.0" - -run-queue@^1.0.0, run-queue@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - dependencies: - aproba "^1.1.1" - -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - -rx@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" - -rxjs@^5.5.2: - version "5.5.11" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.11.tgz#f733027ca43e3bec6b994473be4ab98ad43ced87" - dependencies: - symbol-observable "1.0.1" - -rxjs@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.2.1.tgz#246cebec189a6cbc143a3ef9f62d6f4c91813ca1" - dependencies: - tslib "^1.9.0" - -s-age@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/s-age/-/s-age-1.1.2.tgz#c0cf15233ccc93f41de92ea42c36d957977d1ea2" - -safe-buffer@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - -sass-graph@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" - dependencies: - glob "^7.0.0" - lodash "^4.0.0" - scss-tokenizer "^0.2.3" - yargs "^7.0.0" - -sass-loader@7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.0.1.tgz#fd937259ccba3a9cfe0d5f8a98746d48adfcc261" - dependencies: - clone-deep "^2.0.1" - loader-utils "^1.0.1" - lodash.tail "^4.1.1" - neo-async "^2.5.0" - pify "^3.0.0" - -sax@0.5.x: - version "0.5.8" - resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1" - -sax@^1.2.4, sax@~1.2.1, sax@~1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - -schema-utils@^0.4.3, schema-utils@^0.4.4, schema-utils@^0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.5.tgz#21836f0608aac17b78f9e3e24daff14a5ca13a3e" - dependencies: - ajv "^6.1.0" - ajv-keywords "^3.1.0" - -scoped-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-1.0.0.tgz#a346bb1acd4207ae70bd7c0c7ca9e566b6baddb8" - -scss-tokenizer@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" - dependencies: - js-base64 "^2.1.8" - source-map "^0.4.2" - -seedrandom@2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-2.4.2.tgz#18d78c41287d13aff8eadb29e235938b248aa9ff" - -seedrandom@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-2.4.3.tgz#2438504dad33917314bff18ac4d794f16d6aaecc" - -seek-bzip@^1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - dependencies: - commander "~2.8.1" - -semver-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9" - -semver-truncate@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8" - dependencies: - semver "^5.3.0" - -"semver@2 || 3 || 4 || 5", semver@5.5.0, semver@^5.0.1, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - -semver@^4.0.3, semver@^4.1.0: - version "4.3.6" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" - -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - -send@0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.4.0" - -sequencify@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" - -serialize-javascript@^1.4.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.5.0.tgz#1aa336162c88a890ddad5384baebc93a655161fe" - -serve-static@1.13.2: - version "1.13.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.2" - -set-blocking@^2.0.0, set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - -set-immediate-shim@^1.0.0, set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - -set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" - -set-value@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - -setprototypeof@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -shallow-clone@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571" - dependencies: - is-extendable "^0.1.1" - kind-of "^5.0.0" - mixin-object "^2.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - -shell-quote@*: - version "1.6.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" - dependencies: - array-filter "~0.0.0" - array-map "~0.0.0" - array-reduce "~0.0.0" - jsonify "~0.0.0" - -shelljs@^0.8.0: - version "0.8.2" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35" - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -shvl@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/shvl/-/shvl-1.3.1.tgz#6c20a17b4a20b08e9f8cab60c50a92229fcc176e" - -sigmund@^1.0.1, sigmund@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - -single-line-log@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-1.1.2.tgz#c2f83f273a3e1a16edb0995661da0ed5ef033364" - dependencies: - string-width "^1.0.1" - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - dependencies: - is-fullwidth-code-point "^2.0.0" - -slide@^1.1.5, slide@~1.1.3: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - dependencies: - hoek "2.x.x" - -sntp@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - dependencies: - hoek "4.x.x" - -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - dependencies: - is-plain-obj "^1.0.0" - -sort-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" - dependencies: - is-plain-obj "^1.0.0" - -sortablejs@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.7.0.tgz#80a2b2370abd568e1cec8c271131ef30a904fa28" - -source-list-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" - -source-list-map@~0.1.7: - version "0.1.8" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106" - -source-map-resolve@^0.5.0, source-map-resolve@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - dependencies: - source-map "^0.5.6" - -source-map-support@^0.5.3: - version "0.5.6" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13" - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - -source-map@0.1.x, source-map@^0.1.38: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - dependencies: - amdefine ">=0.0.4" - -source-map@0.5.x, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - -source-map@^0.4.2, source-map@~0.4.1: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - dependencies: - amdefine ">=0.0.4" - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - -sparkles@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" - -spawn-sync@^1.0.15: - version "1.0.15" - resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" - dependencies: - concat-stream "^1.4.7" - os-shim "^0.1.2" - -spdx-compare@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/spdx-compare/-/spdx-compare-1.0.0.tgz#2c55f117362078d7409e6d7b08ce70a857cd3ed7" - dependencies: - array-find-index "^1.0.2" - spdx-expression-parse "^3.0.0" - spdx-ranges "^2.0.0" - -spdx-correct@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-1.0.5.tgz#9d21ac4da4bdb71d060fb74e5a67531d032cbba6" - -spdx-exceptions@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" - -spdx-license-ids@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" - -spdx-ranges@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/spdx-ranges/-/spdx-ranges-2.0.0.tgz#257686798e5edb41d45c1aba3d3f1bb47af8d5ec" - -spdx-satisfies@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/spdx-satisfies/-/spdx-satisfies-4.0.0.tgz#ebc79eec88b68ac75618e2e5ee94fbc347587552" - dependencies: - spdx-compare "^1.0.0" - spdx-expression-parse "^3.0.0" - spdx-ranges "^2.0.0" - -spdx@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/spdx/-/spdx-0.5.1.tgz#d36c275088b48d75a9046cd44a838ce4b5339998" - dependencies: - spdx-exceptions "^1.0.0" - spdx-license-ids "^1.0.0" - -speakeasy@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/speakeasy/-/speakeasy-2.0.0.tgz#85c91a071b09a5cb8642590d983566165f57613a" - dependencies: - base32.js "0.0.1" - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - dependencies: - extend-shallow "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - -squeak@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/squeak/-/squeak-1.3.0.tgz#33045037b64388b567674b84322a6521073916c3" - dependencies: - chalk "^1.0.0" - console-stream "^0.1.1" - lpad-align "^1.0.1" - -sshpk@^1.7.0: - version "1.14.2" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - safer-buffer "^2.0.2" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -ssri@^5.2.4: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06" - dependencies: - safe-buffer "^5.1.1" - -stable@~0.1.6: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - -stat-mode@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2", statuses@^1.0.0, statuses@^1.2.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - -statuses@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - -stdout-stream@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" - dependencies: - readable-stream "^2.0.1" - -stealthy-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - -stream-browserify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-combiner2@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" - dependencies: - duplexer2 "~0.1.0" - readable-stream "^2.0.2" - -stream-consume@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.1.tgz#d3bdb598c2bd0ae82b8cac7ac50b1107a7996c48" - -stream-each@^1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd" - dependencies: - end-of-stream "^1.1.0" - stream-shift "^1.0.0" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - -streamsearch@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - -string-template@~0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" - -string-width@^1.0.1, string-width@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string_decoder@^1.0.0, string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - dependencies: - safe-buffer "~5.1.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -string_decoder@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - dependencies: - safe-buffer "~5.1.0" - -stringstream@~0.0.4, stringstream@~0.0.5: - version "0.0.6" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991" - -strip-bom-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" - dependencies: - first-chunk-stream "^1.0.0" - strip-bom "^2.0.0" - -strip-bom-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz#f87db5ef2613f6968aa545abfe1ec728b6a829ca" - dependencies: - first-chunk-stream "^2.0.0" - strip-bom "^2.0.0" - -strip-bom-string@1.X: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - -strip-bom@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-1.0.0.tgz#85b8862f3844b5a6d5ec8467a93598173a36f794" - dependencies: - first-chunk-stream "^1.0.0" - is-utf8 "^0.2.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - dependencies: - is-utf8 "^0.2.0" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - -strip-dirs@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-1.1.1.tgz#960bbd1287844f3975a4558aa103a8255e2456a0" - dependencies: - chalk "^1.0.0" - get-stdin "^4.0.1" - is-absolute "^0.1.5" - is-natural-number "^2.0.0" - minimist "^1.1.0" - sum-up "^1.0.1" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - dependencies: - get-stdin "^4.0.1" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - -strip-outer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" - dependencies: - escape-string-regexp "^1.0.2" - -style-loader@0.21.0: - version "0.21.0" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.21.0.tgz#68c52e5eb2afc9ca92b6274be277ee59aea3a852" - dependencies: - loader-utils "^1.1.0" - schema-utils "^0.4.5" - -stylus-loader@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/stylus-loader/-/stylus-loader-3.0.2.tgz#27a706420b05a38e038e7cacb153578d450513c6" - dependencies: - loader-utils "^1.0.2" - lodash.clonedeep "^4.5.0" - when "~3.6.x" - -stylus@0.54.5, stylus@^0.54.0, stylus@~0.54.5: - version "0.54.5" - resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.5.tgz#42b9560931ca7090ce8515a798ba9e6aa3d6dc79" - dependencies: - css-parse "1.7.x" - debug "*" - glob "7.0.x" - mkdirp "0.5.x" - sax "0.5.x" - source-map "0.1.x" - -sum-up@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sum-up/-/sum-up-1.0.3.tgz#1c661f667057f63bcb7875aa1438bc162525156e" - dependencies: - chalk "^1.0.0" - -summaly@2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/summaly/-/summaly-2.0.6.tgz#559561e05c267f01e7199a296dd650a994b19053" - dependencies: - cheerio-httpcli "0.7.2" - debug "3.1.0" - escape-regexp "0.0.1" - html-entities "1.2.1" - request "2.85.0" - request-promise-native "1.0.5" - require-all "2.2.0" - trace-redirect "1.0.6" - -supports-color@5.4.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-color@^5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - dependencies: - has-flag "^3.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -supports-color@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - dependencies: - has-flag "^1.0.0" - -svgo@^0.7.0: - version "0.7.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" - dependencies: - coa "~1.0.1" - colors "~1.1.2" - csso "~2.3.1" - js-yaml "~3.7.0" - mkdirp "~0.5.1" - sax "~1.2.1" - whet.extend "~0.9.9" - -svgo@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.0.5.tgz#7040364c062a0538abacff4401cea6a26a7a389a" - dependencies: - coa "~2.0.1" - colors "~1.1.2" - css-select "~1.3.0-rc0" - css-select-base-adapter "~0.1.0" - css-tree "1.0.0-alpha25" - css-url-regex "^1.1.0" - csso "^3.5.0" - js-yaml "~3.10.0" - mkdirp "~0.5.1" - object.values "^1.0.4" - sax "~1.2.4" - stable "~0.1.6" - unquote "~1.1.1" - util.promisify "~1.0.0" - -swagger-jsdoc@1.9.7: - version "1.9.7" - resolved "https://registry.yarnpkg.com/swagger-jsdoc/-/swagger-jsdoc-1.9.7.tgz#7a761d4d7ef4a54bf457cea5c67ec316bb82f8b9" - dependencies: - chokidar "^1.7.0" - commander "^2.11.0" - doctrine "^2.0.0" - glob "^7.1.2" - js-yaml "^3.8.4" - recursive-iterator "^2.0.3" - swagger-parser "^3.4.1" - -swagger-methods@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/swagger-methods/-/swagger-methods-1.0.4.tgz#2c5b844f4a22ab2f5e773f98193c28e386b1c37e" - -swagger-parser@^3.4.1: - version "3.4.2" - resolved "https://registry.yarnpkg.com/swagger-parser/-/swagger-parser-3.4.2.tgz#244d67d6eeed08c00acb5d95950d5aefbd6185a3" - dependencies: - call-me-maybe "^1.0.1" - debug "^3.0.0" - es6-promise "^4.1.1" - json-schema-ref-parser "^1.4.1" - ono "^4.0.2" - swagger-methods "^1.0.0" - swagger-schema-official "2.0.0-bab6bed" - z-schema "^3.16.1" - -swagger-schema-official@2.0.0-bab6bed: - version "2.0.0-bab6bed" - resolved "https://registry.yarnpkg.com/swagger-schema-official/-/swagger-schema-official-2.0.0-bab6bed.tgz#70070468d6d2977ca5237b2e519ca7d06a2ea3fd" - -"sylvester@>= 0.0.12", "sylvester@>= 0.0.8": - version "0.0.21" - resolved "https://registry.yarnpkg.com/sylvester/-/sylvester-0.0.21.tgz#2987b1ce2bd2f38b0dce2a34388884bfa4400ea7" - -symbol-observable@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" - -symbol-observable@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" - -symbol-tree@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" - -syuilo-password-strength@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/syuilo-password-strength/-/syuilo-password-strength-0.0.1.tgz#08f71a8f0ecb77db649f3d9a6424510d9d945f52" - -table@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" - dependencies: - ajv "^5.2.3" - ajv-keywords "^2.1.0" - chalk "^2.1.0" - lodash "^4.17.4" - slice-ansi "1.0.0" - string-width "^2.1.1" - -tapable@^1.0.0, tapable@^1.0.0-beta.5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2" - -tar-stream@^1.1.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.1.tgz#f84ef1696269d6223ca48f6e1eeede3f7e81f395" - dependencies: - bl "^1.0.0" - buffer-alloc "^1.1.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.0" - xtend "^4.0.0" - -tar@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -tar@^4: - version "4.4.4" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.4.tgz#ec8409fae9f665a4355cc3b4087d0820232bb8cd" - dependencies: - chownr "^1.0.1" - fs-minipass "^1.2.5" - minipass "^2.3.3" - minizlib "^1.1.0" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.2" - -tcp-port-used@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/tcp-port-used/-/tcp-port-used-0.1.2.tgz#9450e8768c83b416fd4d1a6a9449eeccbf496c29" - dependencies: - debug "0.7.4" - is2 "0.0.9" - q "0.9.7" - -temp-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" - -temp@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.3.tgz#e0c6bc4d26b903124410e4fed81103014dfc1f59" - dependencies: - os-tmpdir "^1.0.0" - rimraf "~2.2.6" - -tempfile@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-1.1.1.tgz#5bcc4eaecc4ab2c707d8bc11d99ccc9a2cb287f2" - dependencies: - os-tmpdir "^1.0.0" - uuid "^2.0.1" - -tempfile@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-2.0.0.tgz#6b0446856a9b1114d1856ffcbe509cccb0977265" - dependencies: - temp-dir "^1.0.0" - uuid "^3.0.1" - -text-table@^0.2.0, text-table@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - -textarea-caret@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/textarea-caret/-/textarea-caret-3.1.0.tgz#5d5a35bb035fd06b2ff0e25d5359e97f2655087f" - -textextensions@2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.2.0.tgz#38ac676151285b658654581987a0ce1a4490d286" - -thenify-all@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - dependencies: - thenify ">= 3.1.0 < 4" - -"thenify@>= 3.1.0 < 4": - version "3.3.0" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" - dependencies: - any-promise "^1.0.0" - -throttle-debounce@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-1.1.0.tgz#51853da37be68a155cb6e827b3514a3c422e89cd" - -through2-concurrent@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/through2-concurrent/-/through2-concurrent-1.1.1.tgz#11cb4ea4c9e31bca6e4c1e6dba48d1c728c3524b" - dependencies: - through2 "^2.0.0" - -through2-filter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@2.X, through2@^2.0.0, through2@^2.0.3, through2@~2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through2@^0.6.0, through2@^0.6.1: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through@^2.3.6, through@~2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -tildify@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" - dependencies: - os-homedir "^1.0.0" - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - -timed-out@^3.0.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-3.1.3.tgz#95860bfcc5c76c277f8f8326fd0f5b2e20eba217" - -timed-out@^4.0.0, timed-out@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - -timers-browserify@^2.0.4: - version "2.0.10" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" - dependencies: - setimmediate "^1.0.4" - -timers-ext@^0.1.2: - version "0.1.5" - resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.5.tgz#77147dd4e76b660c2abb8785db96574cbbd12922" - dependencies: - es5-ext "~0.10.14" - next-tick "1" - -tmp@0.0.33, tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - dependencies: - os-tmpdir "~1.0.2" - -to-absolute-glob@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" - dependencies: - extend-shallow "^2.0.1" - -to-absolute-glob@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" - dependencies: - is-absolute "^1.0.0" - is-negated-glob "^1.0.0" - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - -to-buffer@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -to-through@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" - dependencies: - through2 "^2.0.3" - -token-stream@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a" - -tough-cookie@>=2.3.3, tough-cookie@^2.3.3: - version "2.4.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.2.tgz#aa9133154518b494efab98a58247bfc38818c00c" - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - -tough-cookie@~2.3.0, tough-cookie@~2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" - dependencies: - punycode "^1.4.1" - -tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - dependencies: - punycode "^2.1.0" - -trace-redirect@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/trace-redirect/-/trace-redirect-1.0.6.tgz#ac629b5bf8247d30dde5a35fe9811b811075b504" - -treeify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" - -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - -trim-repeated@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" - dependencies: - escape-string-regexp "^1.0.2" - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - -"true-case-path@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.2.tgz#7ec91130924766c7f573be3020c34f8fdfd00d62" - dependencies: - glob "^6.0.4" - -tryit@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" - -ts-loader@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-4.3.0.tgz#4e3ba172783d1256d3a23bdfadde011a795fae9e" - dependencies: - chalk "^2.3.0" - enhanced-resolve "^4.0.0" - loader-utils "^1.0.2" - micromatch "^3.1.4" - semver "^5.0.1" - -ts-node@6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-6.0.4.tgz#245af3a8cdf3baa1121893fe12b9a54ee297c4c5" - dependencies: - arrify "^1.0.0" - chalk "^2.3.0" - diff "^3.1.0" - make-error "^1.1.1" - minimist "^1.2.0" - mkdirp "^0.5.1" - source-map-support "^0.5.3" - yn "^2.0.0" - -tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: - version "1.9.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.2.tgz#8be0cc9a1f6dc7727c38deb16c2ebd1a2892988e" - -tslint@5.10.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.10.0.tgz#11e26bccb88afa02dd0d9956cae3d4540b5f54c3" - dependencies: - babel-code-frame "^6.22.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^3.2.0" - glob "^7.1.1" - js-yaml "^3.7.0" - minimatch "^3.0.4" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.8.0" - tsutils "^2.12.1" - -tsutils@^2.12.1: - version "2.27.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.27.1.tgz#ab0276ac23664f36ce8fd4414daec4aebf4373ee" - dependencies: - tslib "^1.8.1" - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - -tunnel-agent@^0.4.0, tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - 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" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - dependencies: - prelude-ls "~1.1.2" - -type-is@^1.5.5, type-is@^1.6.14, type-is@^1.6.16, type-is@^1.6.4, type-is@~1.6.15, type-is@~1.6.16: - version "1.6.16" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" - dependencies: - media-typer "0.3.0" - mime-types "~2.1.18" - -type-of@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/type-of/-/type-of-2.0.1.tgz#e72a1741896568e9f628378d816d6912f7f23972" - -typedarray-to-buffer@^3.1.2: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - dependencies: - is-typedarray "^1.0.0" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - -typescript-eslint-parser@15.0.0: - version "15.0.0" - resolved "https://registry.yarnpkg.com/typescript-eslint-parser/-/typescript-eslint-parser-15.0.0.tgz#882fd3d7aabffbab0a7f98d2a59fb9a989c2b37f" - dependencies: - lodash.unescape "4.0.1" - semver "5.5.0" - -typescript@2.8.3: - version "2.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.3.tgz#5d817f9b6f31bb871835f4edf0089f21abe6c170" - -uglify-es@3.3.9, uglify-es@^3.3.4: - version "3.3.9" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" - dependencies: - commander "~2.13.0" - source-map "~0.6.1" - -uglify-js@3.3.x: - version "3.3.28" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.28.tgz#0efb9a13850e11303361c1051f64d2ec68d9be06" - dependencies: - commander "~2.15.0" - source-map "~0.6.1" - -uglify-js@^2.6.1, uglify-js@^2.7.0: - version "2.8.29" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - dependencies: - source-map "~0.5.1" - yargs "~3.10.0" - optionalDependencies: - uglify-to-browserify "~1.0.0" - -uglify-js@^3.0.5: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.0.tgz#796762282b5b5f0eafe7d5c8c708d1d7bd5ba11d" - dependencies: - commander "~2.15.0" - source-map "~0.6.1" - -uglify-to-browserify@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - -uglifyjs-webpack-plugin@^1.2.4: - version "1.2.5" - resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.5.tgz#2ef8387c8f1a903ec5e44fa36f9f3cbdcea67641" - dependencies: - cacache "^10.0.4" - find-cache-dir "^1.0.0" - schema-utils "^0.4.5" - serialize-javascript "^1.4.0" - source-map "^0.6.1" - uglify-es "^3.3.4" - webpack-sources "^1.1.0" - worker-farm "^1.5.2" - -unc-path-regex@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - -underscore@>=1.3.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - -underscore@~1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" - -union-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^0.4.3" - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - -unique-filename@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3" - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.0.tgz#db6676e7c7cc0629878ff196097c78855ae9f4ab" - dependencies: - imurmurhash "^0.1.4" - -unique-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" - -unique-stream@^2.0.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369" - dependencies: - json-stable-stringify "^1.0.0" - through2-filter "^2.0.0" - -universalify@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - -unquote@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -untildify@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.3.tgz#1e7b42b140bcfd922b22e70ca1265bfe3634c7c9" - -unzip-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe" - -upath@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" - -upper-case@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" - -uri-js@^4.2.1: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - dependencies: - punycode "^2.1.0" - -urijs@^1.19.0: - version "1.19.1" - resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.1.tgz#5b0ff530c0cbde8386f6342235ba5ca6e995d25a" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - -url-loader@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.0.1.tgz#61bc53f1f184d7343da2728a1289ef8722ea45ee" - dependencies: - loader-utils "^1.1.0" - mime "^2.0.3" - schema-utils "^0.4.3" - -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - dependencies: - prepend-http "^1.0.1" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - dependencies: - prepend-http "^2.0.0" - -url-regex@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/url-regex/-/url-regex-3.2.0.tgz#dbad1e0c9e29e105dd0b1f09f6862f7fdb482724" - dependencies: - ip-regex "^1.0.1" - -url-to-options@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -urlsafe-base64@^1.0.0, urlsafe-base64@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/urlsafe-base64/-/urlsafe-base64-1.0.0.tgz#23f89069a6c62f46cf3a1d3b00169cefb90be0c6" - -use@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" - dependencies: - kind-of "^6.0.2" - -user-home@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -util-extend@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" - -util.promisify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" - -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - dependencies: - inherits "2.0.1" - -util@^0.10.3: - version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - dependencies: - inherits "2.0.3" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - -uuid@3.2.1, uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" - -uuid@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" - -v-animate-css@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/v-animate-css/-/v-animate-css-0.0.2.tgz#61f233b641de5ab544ab50bc5450c747030e3bde" - -v8-compile-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz#526492e35fc616864284700b7043e01baee09f0a" - -v8flags@^2.0.2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" - dependencies: - user-home "^1.1.1" - -vali-date@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" - -valid-url@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - -validate-npm-package-license@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -validator@^10.0.0: - version "10.3.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-10.3.0.tgz#157a8c0981858cff381f59aabcdb8f83b57317cc" - -value-or-function@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" - -vary@^1.0.0, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - -vendors@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vinyl-assign@^1.0.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/vinyl-assign/-/vinyl-assign-1.2.1.tgz#4d198891b5515911d771a8cd9c5480a46a074a45" - dependencies: - object-assign "^4.0.1" - readable-stream "^2.0.0" - -vinyl-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/vinyl-file/-/vinyl-file-2.0.0.tgz#a7ebf5ffbefda1b7d18d140fcb07b223efb6751a" - dependencies: - graceful-fs "^4.1.2" - pify "^2.3.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - strip-bom-stream "^2.0.0" - vinyl "^1.1.0" - -vinyl-fs@^0.3.0: - version "0.3.14" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6" - dependencies: - defaults "^1.0.0" - glob-stream "^3.1.5" - glob-watcher "^0.0.6" - graceful-fs "^3.0.0" - mkdirp "^0.5.0" - strip-bom "^1.0.0" - through2 "^0.6.1" - vinyl "^0.4.0" - -vinyl-fs@^2.2.0: - version "2.4.4" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" - dependencies: - duplexify "^3.2.0" - glob-stream "^5.3.2" - graceful-fs "^4.0.0" - gulp-sourcemaps "1.6.0" - is-valid-glob "^0.3.0" - lazystream "^1.0.0" - lodash.isequal "^4.0.0" - merge-stream "^1.0.0" - mkdirp "^0.5.0" - object-assign "^4.0.0" - readable-stream "^2.0.4" - strip-bom "^2.0.0" - strip-bom-stream "^1.0.0" - through2 "^2.0.0" - through2-filter "^2.0.0" - vali-date "^1.0.0" - vinyl "^1.0.0" - -vinyl-fs@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" - dependencies: - fs-mkdirp-stream "^1.0.0" - glob-stream "^6.1.0" - graceful-fs "^4.0.0" - is-valid-glob "^1.0.0" - lazystream "^1.0.0" - lead "^1.0.0" - object.assign "^4.0.4" - pumpify "^1.3.5" - readable-stream "^2.3.3" - remove-bom-buffer "^3.0.0" - remove-bom-stream "^1.2.0" - resolve-options "^1.1.0" - through2 "^2.0.0" - to-through "^2.0.0" - value-or-function "^3.0.0" - vinyl "^2.0.0" - vinyl-sourcemap "^1.1.0" - -vinyl-sourcemap@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" - dependencies: - append-buffer "^1.0.2" - convert-source-map "^1.5.0" - graceful-fs "^4.1.6" - normalize-path "^2.1.1" - now-and-later "^2.0.0" - remove-bom-buffer "^3.0.0" - vinyl "^2.0.0" - -vinyl-sourcemaps-apply@^0.2.0, vinyl-sourcemaps-apply@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" - dependencies: - source-map "^0.5.1" - -vinyl@^0.4.0, vinyl@^0.4.3: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^1.0.0, vinyl@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^2.0.0, vinyl@^2.0.1, vinyl@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c" - dependencies: - clone "^2.1.1" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - dependencies: - indexof "0.0.1" - -void-elements@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" - -vue-cropperjs@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/vue-cropperjs/-/vue-cropperjs-2.2.0.tgz#cd8f00ee01914e86f114ee8aa3f7354e3c76a8fc" - dependencies: - cropperjs "^1.1.3" - -vue-eslint-parser@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz#c268c96c6d94cfe3d938a5f7593959b0ca3360d1" - dependencies: - debug "^3.1.0" - eslint-scope "^3.7.1" - eslint-visitor-keys "^1.0.0" - espree "^3.5.2" - esquery "^1.0.0" - lodash "^4.17.4" - -vue-functional-data-merge@^2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/vue-functional-data-merge/-/vue-functional-data-merge-2.0.6.tgz#f08055adfb92458debcf2ad10c3aa712277f7fc2" - -vue-hot-reload-api@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz#97976142405d13d8efae154749e88c4e358cf926" - -vue-js-modal@1.3.13: - version "1.3.13" - resolved "https://registry.yarnpkg.com/vue-js-modal/-/vue-js-modal-1.3.13.tgz#1718c3182a94a03e03422db50c60229bbbd53f18" - -vue-json-tree-view@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/vue-json-tree-view/-/vue-json-tree-view-2.1.4.tgz#b6f8ae2ba2eec4eec5b6f53b90fa187054cad79b" - dependencies: - lodash "^4.17.4" - vue "^2.5.16" - -vue-loader@15.2.1: - version "15.2.1" - resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.2.1.tgz#89a13b6b7dec63614729c73b1b46a571a69bb20e" - dependencies: - "@vue/component-compiler-utils" "^1.2.1" - hash-sum "^1.0.2" - loader-utils "^1.1.0" - vue-hot-reload-api "^2.3.0" - vue-style-loader "^4.1.0" - -vue-router@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.1.tgz#d9b05ad9c7420ba0f626d6500d693e60092cc1e9" - -vue-style-loader@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.0.tgz#7588bd778e2c9f8d87bfc3c5a4a039638da7a863" - dependencies: - hash-sum "^1.0.2" - loader-utils "^1.0.2" - -vue-template-compiler@2.5.16: - version "2.5.16" - resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.16.tgz#93b48570e56c720cdf3f051cc15287c26fbd04cb" - dependencies: - de-indent "^1.0.2" - he "^1.1.0" - -vue-template-es2015-compiler@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18" - -vue@2.5.16, vue@^2.5.16: - version "2.5.16" - resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.16.tgz#07edb75e8412aaeed871ebafa99f4672584a0085" - -vuedraggable@2.16.0: - version "2.16.0" - resolved "https://registry.yarnpkg.com/vuedraggable/-/vuedraggable-2.16.0.tgz#52127081a2adb3de5fabd214d404ff3eee63575a" - dependencies: - sortablejs "^1.7.0" - -vuex-persistedstate@^2.5.4: - version "2.5.4" - resolved "https://registry.yarnpkg.com/vuex-persistedstate/-/vuex-persistedstate-2.5.4.tgz#a19710ad7f9a08cea4e65fc585924d9fdac7384a" - dependencies: - deepmerge "^2.1.0" - shvl "^1.3.0" - -vuex@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.0.1.tgz#e761352ebe0af537d4bb755a9b9dc4be3df7efd2" - -w3c-hr-time@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" - dependencies: - browser-process-hrtime "^0.1.2" - -ware@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ware/-/ware-1.3.0.tgz#d1b14f39d2e2cb4ab8c4098f756fe4b164e473d4" - dependencies: - wrap-fn "^0.1.0" - -watchpack@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - dependencies: - chokidar "^2.0.2" - graceful-fs "^4.1.2" - neo-async "^2.5.0" - -web-push@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/web-push/-/web-push-3.3.1.tgz#6d49517b927ffb97241a719d2f7f9014de130f09" - dependencies: - asn1.js "^5.0.0" - http_ece "1.0.5" - https-proxy-agent "^2.2.1" - jws "^3.1.3" - minimist "^1.2.0" - urlsafe-base64 "^1.0.0" - -webassemblyjs@1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webassemblyjs/-/webassemblyjs-1.4.3.tgz#0591893efb8fbde74498251cbe4b2d83df9239cb" - dependencies: - "@webassemblyjs/ast" "1.4.3" - "@webassemblyjs/validation" "1.4.3" - "@webassemblyjs/wasm-parser" "1.4.3" - "@webassemblyjs/wast-parser" "1.4.3" - long "^3.2.0" - -webfinger.js@2.6.6: - version "2.6.6" - resolved "https://registry.yarnpkg.com/webfinger.js/-/webfinger.js-2.6.6.tgz#52ebdc85da8c8fb6beb690e8e32594c99d2ff4ae" - dependencies: - xhr2 "^0.1.4" - -webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - -webpack-addons@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/webpack-addons/-/webpack-addons-1.1.5.tgz#2b178dfe873fb6e75e40a819fa5c26e4a9bc837a" - dependencies: - jscodeshift "^0.4.0" - -webpack-cli@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-2.1.4.tgz#cab81e79249127384fb69b2fdfe2055f9c771b76" - dependencies: - chalk "^2.4.1" - cross-spawn "^6.0.5" - diff "^3.5.0" - enhanced-resolve "^4.0.0" - envinfo "^5.7.0" - glob-all "^3.1.0" - global-modules "^1.0.0" - got "^8.3.1" - import-local "^1.0.0" - inquirer "^5.2.0" - interpret "^1.1.0" - jscodeshift "^0.5.0" - listr "^0.14.1" - loader-utils "^1.1.0" - lodash "^4.17.10" - log-symbols "^2.2.0" - mkdirp "^0.5.1" - p-each-series "^1.0.0" - p-lazy "^1.0.0" - prettier "^1.12.1" - supports-color "^5.4.0" - v8-compile-cache "^2.0.0" - webpack-addons "^1.1.5" - yargs "^11.1.0" - yeoman-environment "^2.1.1" - yeoman-generator "^2.0.5" - -webpack-core@~0.6.0: - version "0.6.9" - resolved "https://registry.yarnpkg.com/webpack-core/-/webpack-core-0.6.9.tgz#fc571588c8558da77be9efb6debdc5a3b172bdc2" - dependencies: - source-list-map "~0.1.7" - source-map "~0.4.1" - -webpack-sources@^1.0.1, webpack-sources@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54" - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack@4.9.1: - version "4.9.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.9.1.tgz#fa7bd738b17fd7f09f37da461b2f5c16c6565f34" - dependencies: - "@webassemblyjs/ast" "1.4.3" - "@webassemblyjs/wasm-edit" "1.4.3" - "@webassemblyjs/wasm-parser" "1.4.3" - acorn "^5.0.0" - acorn-dynamic-import "^3.0.0" - ajv "^6.1.0" - ajv-keywords "^3.1.0" - chrome-trace-event "^0.1.1" - enhanced-resolve "^4.0.0" - eslint-scope "^3.7.1" - json-parse-better-errors "^1.0.2" - loader-runner "^2.3.0" - loader-utils "^1.1.0" - memory-fs "~0.4.1" - micromatch "^3.1.8" - mkdirp "~0.5.0" - neo-async "^2.5.0" - node-libs-browser "^2.0.0" - schema-utils "^0.4.4" - tapable "^1.0.0" - uglifyjs-webpack-plugin "^1.2.4" - watchpack "^1.5.0" - webpack-sources "^1.0.1" - -websocket@1.0.26: - version "1.0.26" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.26.tgz#a03a01299849c35268c83044aa919c6374be8194" - dependencies: - debug "^2.2.0" - nan "^2.3.3" - typedarray-to-buffer "^3.1.2" - yaeti "^0.0.6" - -whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz#57c235bc8657e914d24e1a397d3c82daee0a6ba3" - dependencies: - iconv-lite "0.4.19" - -whatwg-mimetype@^2.0.0, whatwg-mimetype@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz#f0f21d76cbba72362eb609dbed2a30cd17fcc7d4" - -whatwg-url@^6.4.0, whatwg-url@^6.4.1: - version "6.5.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -when@^3.7.7: - version "3.7.8" - resolved "https://registry.yarnpkg.com/when/-/when-3.7.8.tgz#c7130b6a7ea04693e842cdc9e7a1f2aa39a39f82" - -when@~3.6.x: - version "3.6.4" - resolved "https://registry.yarnpkg.com/when/-/when-3.6.4.tgz#473b517ec159e2b85005497a13983f095412e34e" - -whet.extend@~0.9.9: - version "0.9.9" - resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" - -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - -which@1, which@^1.2.14, which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - dependencies: - isexe "^2.0.0" - -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - dependencies: - string-width "^1.0.2 || 2" - -window-or-global@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/window-or-global/-/window-or-global-1.0.1.tgz#dbe45ba2a291aabc56d62cf66c45b7fa322946de" - -window-size@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - -window-size@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - -with@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/with/-/with-5.1.1.tgz#fa4daa92daf32c4ea94ed453c81f04686b575dfe" - dependencies: - acorn "^3.1.0" - acorn-globals "^3.0.0" - -wordwrap@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - -worker-farm@^1.5.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" - dependencies: - errno "~0.1.7" - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrap-fn@^0.1.0: - version "0.1.5" - resolved "https://registry.yarnpkg.com/wrap-fn/-/wrap-fn-0.1.5.tgz#f21b6e41016ff4a7e31720dbc63a09016bdf9845" - dependencies: - co "3.1.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -write-file-atomic@^1.2.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - slide "^1.1.5" - -write-file-atomic@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -write-json-file@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.3.0.tgz#2b64c8a33004d54b8698c76d585a77ceb61da32f" - dependencies: - detect-indent "^5.0.0" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - pify "^3.0.0" - sort-keys "^2.0.0" - write-file-atomic "^2.0.0" - -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - dependencies: - mkdirp "^0.5.1" - -ws@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.0.tgz#9fd95e3ac7c76f6ae8bcc868a0e3f11f1290c33e" - dependencies: - async-limiter "~1.0.0" - -ws@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - -xev@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/xev/-/xev-2.0.1.tgz#24484173a22115bc8a990ef5d4d5129695b827a7" - -xhr2@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" - -xml-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" - -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - -y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - -yallist@^3.0.0, yallist@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" - -yargs-parser@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - dependencies: - camelcase "^3.0.0" - lodash.assign "^4.0.6" - -yargs-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - dependencies: - camelcase "^3.0.0" - -yargs-parser@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - dependencies: - camelcase "^4.1.0" - -yargs-parser@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" - dependencies: - camelcase "^4.1.0" - -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - dependencies: - camelcase "^4.1.0" - -yargs@^10.0.3: - version "10.1.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^8.1.0" - -yargs@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" - -yargs@^4.0.0: - version "4.8.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - dependencies: - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - lodash.assign "^4.0.3" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.1" - which-module "^1.0.0" - window-size "^0.2.0" - y18n "^3.2.1" - yargs-parser "^2.4.1" - -yargs@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^5.0.0" - -yargs@^8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" - dependencies: - camelcase "^4.1.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - read-pkg-up "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^7.0.0" - -yargs@~1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.2.6.tgz#9c7b4a82fd5d595b2bf17ab6dcc43135432fe34b" - dependencies: - minimist "^0.1.0" - -yargs@~3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - dependencies: - camelcase "^1.0.2" - cliui "^2.1.0" - decamelize "^1.0.0" - window-size "0.1.0" - -yauzl@^2.2.1: - version "2.9.2" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.9.2.tgz#4fb1bc7ae1fc2f57037b54af6acc8fe1031c5b77" - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - -yeoman-environment@^2.0.5, yeoman-environment@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/yeoman-environment/-/yeoman-environment-2.2.0.tgz#6c0ee93a8d962a9f6dbc5ad4e90ae7ab34875393" - dependencies: - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^3.1.0" - diff "^3.3.1" - escape-string-regexp "^1.0.2" - globby "^8.0.1" - grouped-queue "^0.3.3" - inquirer "^5.2.0" - is-scoped "^1.0.0" - lodash "^4.17.10" - log-symbols "^2.1.0" - mem-fs "^1.1.0" - strip-ansi "^4.0.0" - text-table "^0.2.0" - untildify "^3.0.2" - -yeoman-generator@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/yeoman-generator/-/yeoman-generator-2.0.5.tgz#57b0b3474701293cc9ec965288f3400b00887c81" - dependencies: - async "^2.6.0" - chalk "^2.3.0" - cli-table "^0.3.1" - cross-spawn "^6.0.5" - dargs "^5.1.0" - dateformat "^3.0.3" - debug "^3.1.0" - detect-conflict "^1.0.0" - error "^7.0.2" - find-up "^2.1.0" - github-username "^4.0.0" - istextorbinary "^2.2.1" - lodash "^4.17.10" - make-dir "^1.1.0" - mem-fs-editor "^4.0.0" - minimist "^1.2.0" - pretty-bytes "^4.0.2" - read-chunk "^2.1.0" - read-pkg-up "^3.0.0" - rimraf "^2.6.2" - run-async "^2.0.0" - shelljs "^0.8.0" - text-table "^0.2.0" - through2 "^2.0.0" - yeoman-environment "^2.0.5" - -yn@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" - -z-schema@^3.16.1: - version "3.22.0" - resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-3.22.0.tgz#e1326063cb438f348c648350770258ff5e20a22b" - dependencies: - lodash.get "^4.0.0" - lodash.isequal "^4.0.0" - validator "^10.0.0" - optionalDependencies: - commander "^2.7.1"