From 7f8fb24993de08c07d3ddb8d6e3c1f6564024e19 Mon Sep 17 00:00:00 2001 From: yyh1102 Date: Sat, 9 Feb 2019 19:47:59 +0800 Subject: [PATCH] optimize network choosing, fix some bugs --- config.xml | 4 +- package.json | 3 +- src/app/app-routing.module.ts | 4 +- src/app/common/config.ts | 63 ++++++++++++++----- .../create-wallet/create-wallet.component.ts | 11 ++-- .../home-pop-menu/home-pop-menu.component.ts | 6 +- .../import-wallet/import-wallet.component.ts | 10 +-- .../dapp-container/dapp-container.page.ts | 15 +++-- src/app/pages/network/network.page.html | 11 +++- src/app/pages/network/network.page.ts | 40 ++++++++++-- src/app/pages/qr-scan/qr-scan.page.ts | 8 ++- src/app/pages/share/share.page.html | 3 + src/app/pages/share/share.page.scss | 11 ++++ .../pages/token-detail/token-detail.page.html | 5 +- .../pages/token-detail/token-detail.page.scss | 16 ++--- .../pages/token-detail/token-detail.page.ts | 24 +++++-- src/app/services/account.service.ts | 3 + src/app/services/network.service.ts | 12 ++++ src/app/tabs/tabs.router.module.ts | 2 +- yarn.lock | 54 +++++++++++----- 20 files changed, 228 insertions(+), 77 deletions(-) diff --git a/config.xml b/config.xml index 33f5aff..0b49674 100644 --- a/config.xml +++ b/config.xml @@ -92,8 +92,6 @@ - - @@ -102,4 +100,6 @@ + + diff --git a/package.json b/package.json index ba6c7f0..60eab30 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ "iconv-lite": "^0.4.24", "is-buffer": "^2.0.3", "moment": "^2.24.0", - "moment-timezone": "^0.5.23", "rxjs": "^6.4.0", "socket.io": "^2.2.0", "stream": "^0.0.2", @@ -130,4 +129,4 @@ "android" ] } -} \ No newline at end of file +} diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 18ef000..4d6c855 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -2,7 +2,7 @@ import {NgModule} from '@angular/core'; import {Routes, RouterModule} from '@angular/router'; const routes: Routes = [ - {path: '', loadChildren: './tabs/tabs.module#TabsPageModule'}, + {path: 'tabs', loadChildren: './tabs/tabs.module#TabsPageModule'}, {path: 'login', loadChildren: './pages/login/login.module#LoginPageModule'}, {path: 'transfer', loadChildren: './pages/transfer/transfer.module#TransferPageModule'}, {path: 'bill', loadChildren: './pages/bill/bill.module#BillPageModule'}, @@ -17,7 +17,7 @@ const routes: Routes = [ {path: 'dapp/:url', loadChildren: './pages/dapp-container/dapp-container.module#DappContainerPageModule'}, {path: 'export-key/:privkey', loadChildren: './pages/export-key/export-key.module#ExportKeyPageModule'}, {path: 'dapp-list/:group', loadChildren: './pages/dapp-list/dapp-list.module#DappListPageModule'}, - { path: 'share', loadChildren: './pages/share/share.module#SharePageModule' }, + {path: 'share', loadChildren: './pages/share/share.module#SharePageModule'}, ]; @NgModule({ diff --git a/src/app/common/config.ts b/src/app/common/config.ts index 674599d..9bfdc97 100644 --- a/src/app/common/config.ts +++ b/src/app/common/config.ts @@ -10,23 +10,52 @@ export const tokenCode = 'zjubcatokent'; // kylin testnet chain id export const CHAINID = '5fff1dae8dc8e2fc4d5b23b2c7665c97f9e9d8edf2b6485a86ba311c25639191'; -export const endpoints = [ - { - name: 'EOSLaomao', - endpoint: 'https://api-kylin.eoslaomao.com' - }, - { - name: 'MEET.ONE', - endpoint: 'https://api-kylin.meet.one', - }, - { - name: 'EOS Asia', - endpoint: 'https://api-kylin.eosasia.one' - } - -]; - -export const timezone = 'Asia/Shanghai'; +export const endpoints = { + 'normal': [ + { + name: 'MEET.ONE', + endpoint: 'http://kylin.meet.one:8888', + }, + { + name: 'EOSpacex', + endpoint: 'https://api.kylin-testnet.eospacex.com' + }, + { + name: 'EOSbixin', + endpoint: 'http://kylin.fn.eosbixin.com' + }, + { + name: 'Alohaeos', + endpoint: 'https://api.kylin.alohaeos.com' + }, + { + name: 'EOScanada', + endpoint: 'https://kylin.eoscanada.com' + }, + { + name: 'EOSbeijing', + endpoint: 'http://api.kylin.eosbeijing.one:8880' + }, + { + name: 'StartEOS', + endpoint: 'http://api-kylin.starteos.io' + } + ], + // support `get_action` + 'actions': [ + { + name: 'EOSLaomao', + endpoint: 'https://api-kylin.eoslaomao.com' + }, + { + name: 'EOS Asia', + endpoint: 'https://api-kylin.eosasia.one' + } + ] +}; + +// export const timezone = 'Asia/Shanghai'; +export const timezone = 960; /* ===== storage key ===== */ diff --git a/src/app/components/create-wallet/create-wallet.component.ts b/src/app/components/create-wallet/create-wallet.component.ts index f01c9d5..fd7e8ea 100644 --- a/src/app/components/create-wallet/create-wallet.component.ts +++ b/src/app/components/create-wallet/create-wallet.component.ts @@ -1,6 +1,5 @@ import {Component, OnInit} from '@angular/core'; -import {ToastController, AlertController, LoadingController} from '@ionic/angular'; -import {Route, Router} from '@angular/router'; +import {ToastController, AlertController, LoadingController, NavController} from '@ionic/angular'; import axios from '../../common/axios'; import {AccountService} from '../../services/account.service'; import {WalletService} from '../../services/wallet.service'; @@ -34,7 +33,7 @@ export class CreateWalletComponent implements OnInit { private walletService: WalletService, private eosService: EosService, private storage: Storage, - private router: Router, + private navCtrl: NavController, private clipboard: Clipboard, private loadingCtrl: LoadingController ) { @@ -120,12 +119,14 @@ export class CreateWalletComponent implements OnInit { name: name, permissions: permissions }]); + await this.walletService.saveWallet(this.form.name, pubKey, privateKey, this.form.password); const curr = await this.accService.current(); if (!curr) { await this.accService.setCurrent(name); + await this.navCtrl.navigateRoot('/tabs/assets'); + } else { + await this.navCtrl.navigateBack('/tabs/assets', {replaceUrl: true}); } - await this.walletService.saveWallet(this.form.name, pubKey, privateKey, this.form.password); - await this.router.navigate(['/tabs/assets'], {replaceUrl: true}); } else { throw new Error(resp.msg); } diff --git a/src/app/components/home-pop-menu/home-pop-menu.component.ts b/src/app/components/home-pop-menu/home-pop-menu.component.ts index c409200..dc6cdb4 100644 --- a/src/app/components/home-pop-menu/home-pop-menu.component.ts +++ b/src/app/components/home-pop-menu/home-pop-menu.component.ts @@ -1,5 +1,5 @@ import {Component, OnInit} from '@angular/core'; -import {PopoverController} from '@ionic/angular'; +import {NavController, PopoverController} from '@ionic/angular'; import {Router} from '@angular/router'; @Component({ @@ -10,7 +10,7 @@ import {Router} from '@angular/router'; export class HomePopMenuComponent implements OnInit { constructor( - private router: Router, + private navCtrl: NavController, private popoverCtrl: PopoverController ) { } @@ -19,7 +19,7 @@ export class HomePopMenuComponent implements OnInit { } async nav(url) { - await this.router.navigateByUrl(url); + await this.navCtrl.navigateForward(url); await this.popoverCtrl.dismiss(); } } diff --git a/src/app/components/import-wallet/import-wallet.component.ts b/src/app/components/import-wallet/import-wallet.component.ts index db87b86..fa95f15 100644 --- a/src/app/components/import-wallet/import-wallet.component.ts +++ b/src/app/components/import-wallet/import-wallet.component.ts @@ -1,5 +1,5 @@ import {Component, OnInit} from '@angular/core'; -import {ToastController, LoadingController} from '@ionic/angular'; +import {ToastController, LoadingController, NavController} from '@ionic/angular'; import {EosService} from '../../services/eos.service'; import {AccountService} from '../../services/account.service'; import {Router} from '@angular/router'; @@ -29,7 +29,7 @@ export class ImportWalletComponent implements OnInit { private eosService: EosService, private accService: AccountService, private walletService: WalletService, - private router: Router, + private navCtrl: NavController, ) { this.form = new ImportForm(); } @@ -90,12 +90,14 @@ export class ImportWalletComponent implements OnInit { ); // @ts-ignore await this.accService.saveAccounts(accounts); + await this.walletService.saveWallet(this.form.name, pubkey, privKey, this.form.password); const curr = await this.accService.current(); if (!curr) { await this.accService.setCurrent(names[0]); + await this.navCtrl.navigateRoot('/tabs/assets'); + } else { + await this.navCtrl.navigateBack('/tabs/assets', {replaceUrl: true}); } - await this.walletService.saveWallet(this.form.name, pubkey, privKey, this.form.password); - await this.router.navigate(['/tabs/assets'], {replaceUrl: true}); } else { await this.alert('该密钥下无账户名'); } diff --git a/src/app/pages/dapp-container/dapp-container.page.ts b/src/app/pages/dapp-container/dapp-container.page.ts index 1a11898..4c81878 100644 --- a/src/app/pages/dapp-container/dapp-container.page.ts +++ b/src/app/pages/dapp-container/dapp-container.page.ts @@ -9,10 +9,10 @@ import Error from '../../common/Error'; import {LoadingController, ModalController, ToastController} from '@ionic/angular'; import {TransactModalComponent} from '../../modals/transact-modal/transact-modal.component'; import {Action} from '../../../classes'; -import moment from 'moment-timezone'; import {beautifyValue} from '../../common/helper'; import {ActivatedRoute} from '@angular/router'; import {DomSanitizer} from '@angular/platform-browser'; +import * as moment from 'moment'; @Component({ @@ -273,11 +273,16 @@ class ApiService { if (network.chainId === CHAINID) { return this.response(Error.notKylinChain()); } - network = endpoints.find(x => x.endpoint === `${network.prototype}://${network.host}`); - if (!network) { - return this.response(Error.noNetwork()); + network = endpoints.normal.find(x => x.endpoint === `${network.prototype}://${network.host}`); + if (network) { + return this.response(true); } - this.response(true); + network = endpoints.actions.find(x => x.endpoint === `${network.prototype}://${network.host}`); + if (network) { + return this.response(true); + } + this.response(Error.noNetwork()); + } suggestNetwork() { diff --git a/src/app/pages/network/network.page.html b/src/app/pages/network/network.page.html index ea80476..5b6cf86 100644 --- a/src/app/pages/network/network.page.html +++ b/src/app/pages/network/network.page.html @@ -11,12 +11,21 @@ + + 可选节点(支持获取历史action) + + + {{peer.name}} + + {{peer.delay}} + 可选节点 - + {{peer.name}} + {{peer.delay}} diff --git a/src/app/pages/network/network.page.ts b/src/app/pages/network/network.page.ts index e4451d4..b1fb5a9 100644 --- a/src/app/pages/network/network.page.ts +++ b/src/app/pages/network/network.page.ts @@ -5,6 +5,7 @@ import {NetworkService} from '../../services/network.service'; interface Peer { name: string; endpoint: string; + delay?: string; } @Component({ @@ -13,11 +14,12 @@ interface Peer { styleUrls: ['./network.page.scss'], }) export class NetworkPage implements OnInit { - peers: Peer[]; + normalPeers: Peer[]; + actionsPeers: Peer[]; currPeer: Peer = { endpoint: '', - name: '' + name: '', }; constructor( @@ -26,14 +28,42 @@ export class NetworkPage implements OnInit { } async ngOnInit() { - this.peers = endpoints; + this.normalPeers = endpoints.normal; + this.actionsPeers = endpoints.actions; this.currPeer = await this.networkSvc.getNetwork(); + + const peers = await Promise.all([ + await this.getDelay(this.normalPeers), + await this.getDelay(this.actionsPeers) + ]); + this.normalPeers = peers[0]; + this.actionsPeers = peers[1]; } async peerChange(ev) { const name = ev.detail.value; - this.currPeer = this.peers.find(item => item.name === name); - await this.networkSvc.setNetwork(this.currPeer); + let currPeer = this.normalPeers.find(item => item.name === name); + if (!currPeer) { + currPeer = this.actionsPeers.find(item => item.name === name); + } + try { + await this.networkSvc.setNetwork(currPeer); + this.currPeer = currPeer; + } catch (e) { + console.log(e); + } + } + + async getDelay(peers: Peer[]): Promise { + return await Promise.all(peers.map(async peer => { + let delay = ''; + try { + delay = (await this.networkSvc.ping(peer.endpoint)) + ' ms'; + } catch (e) { + delay = '超时'; + } + return Object.assign(peer, {delay}); + })); } } diff --git a/src/app/pages/qr-scan/qr-scan.page.ts b/src/app/pages/qr-scan/qr-scan.page.ts index a45ce16..8f4533d 100644 --- a/src/app/pages/qr-scan/qr-scan.page.ts +++ b/src/app/pages/qr-scan/qr-scan.page.ts @@ -1,4 +1,4 @@ -import {Component, OnInit} from '@angular/core'; +import {Component, OnDestroy, OnInit} from '@angular/core'; import {QRScanner, QRScannerStatus} from '@ionic-native/qr-scanner/ngx'; import {QRData} from '../../../classes'; import {NavController} from '@ionic/angular'; @@ -9,7 +9,7 @@ import {NavController} from '@ionic/angular'; templateUrl: './qr-scan.page.html', styleUrls: ['./qr-scan.page.scss'], }) -export class QrScanPage implements OnInit { +export class QrScanPage implements OnInit, OnDestroy { noCameraPermission = false; errorMessage: string; @@ -24,6 +24,10 @@ export class QrScanPage implements OnInit { this.qrScan(); } + ngOnDestroy() { + this.qrScanner.hide(); + } + async qrScan() { try { const status: QRScannerStatus = await this.qrScanner.prepare(); diff --git a/src/app/pages/share/share.page.html b/src/app/pages/share/share.page.html index c600bfc..dbcb600 100644 --- a/src/app/pages/share/share.page.html +++ b/src/app/pages/share/share.page.html @@ -10,6 +10,9 @@
+
+ 浙大区块链协会官方钱包 +
diff --git a/src/app/pages/share/share.page.scss b/src/app/pages/share/share.page.scss index e69de29..a596b6b 100644 --- a/src/app/pages/share/share.page.scss +++ b/src/app/pages/share/share.page.scss @@ -0,0 +1,11 @@ +.qrcode { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + .name { + text-align: center; + margin-bottom: 10px; + } +} diff --git a/src/app/pages/token-detail/token-detail.page.html b/src/app/pages/token-detail/token-detail.page.html index 8539662..a042298 100644 --- a/src/app/pages/token-detail/token-detail.page.html +++ b/src/app/pages/token-detail/token-detail.page.html @@ -34,6 +34,9 @@ 交易记录 +
+ 所选网络节点不支持获取历史action,请更换节点 +
{{action.type ? action.to : action.from}} @@ -44,7 +47,7 @@
-
+
到底了
x.name === currPeer.name) < 0) { + this.noSupportActions = true; + } else { + this.getHistoryActions(); + } } async fetchDetails() { @@ -154,9 +162,13 @@ export class TokenDetailPage implements OnInit { to, quantity: quantity.split(' ')[0], type, - time: moment.tz(item.action_trace.block_time, timezone).format('YYYY-MM-DD HH:mm:ss') + time: moment(item.action_trace.block_time).utcOffset(timezone).format('YYYY-MM-DD HH:mm:ss') }; }); + if (actions.length === 0 && !this.noMoreActions) { + this.actionsLoading = false; + return await this.getHistoryActions(); + } this.historyActions = this.historyActions.concat(actions); // console.log(this.historyActions); } catch (e) { diff --git a/src/app/services/account.service.ts b/src/app/services/account.service.ts index e6f4611..6b19c59 100644 --- a/src/app/services/account.service.ts +++ b/src/app/services/account.service.ts @@ -28,6 +28,9 @@ export class AccountService { * @param name */ async setCurrent(name: string): Promise { + if (typeof name === 'undefined') { + return await this.storage.remove(CURRENT_ACC_KEY); + } return await this.storage.set(CURRENT_ACC_KEY, name); } diff --git a/src/app/services/network.service.ts b/src/app/services/network.service.ts index 39ace12..9776de7 100644 --- a/src/app/services/network.service.ts +++ b/src/app/services/network.service.ts @@ -1,6 +1,7 @@ import {Injectable} from '@angular/core'; import {Storage} from '@ionic/storage'; import {ENDPOINT_KEY, endpoints} from '../common/config'; +import axios from '../common/axios'; interface Peer { name: string; @@ -29,4 +30,15 @@ export class NetworkService { } return peer; } + + /** + * ping a server and returns the delay time(ms). + * + * @param url + */ + async ping(url): Promise { + const begin = Date.now(); + await axios.get(`${url}/v1/chain/get_info`); + return Date.now() - begin; + } } diff --git a/src/app/tabs/tabs.router.module.ts b/src/app/tabs/tabs.router.module.ts index 334b6ad..2a0a6f7 100644 --- a/src/app/tabs/tabs.router.module.ts +++ b/src/app/tabs/tabs.router.module.ts @@ -5,7 +5,7 @@ import {TabsPage} from './tabs.page'; const routes: Routes = [ { - path: 'tabs', + path: '', component: TabsPage, children: [ { diff --git a/yarn.lock b/yarn.lock index aa7da07..2eaf119 100644 --- a/yarn.lock +++ b/yarn.lock @@ -529,6 +529,13 @@ opn "^5.1.0" tiny-lr "^1.0.5" +"@types/cordova-plugin-file-transfer@^1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@types/cordova-plugin-file-transfer/-/cordova-plugin-file-transfer-1.6.2.tgz#fd87d3f91781a1519dab8b87723d756eefdda998" + integrity sha512-jWZQefyVn/GiQAdummRoY1v5cUY4dT7GNk3Hg40iUtL68y40jKWD3ALAtMM4pnYt9RSMTlsgs1I7/apXexddvw== + dependencies: + cordova-plugin-file-transfer "*" + "@types/cordova@latest": version "0.0.34" resolved "http://registry.npm.taobao.org/@types/cordova/download/@types/cordova-0.0.34.tgz#ea7addf74ecec3d7629827a0c39e2c9addc73d04" @@ -2203,6 +2210,16 @@ cordova-plugin-device@^2.0.2: resolved "https://registry.yarnpkg.com/cordova-plugin-device/-/cordova-plugin-device-2.0.2.tgz#fc08f3722e67eef7b6c67bfc99a83df6add0baba" integrity sha1-/Ajzci5n7ve2xnv8mag99q3Quro= +cordova-plugin-file-transfer@*, cordova-plugin-file-transfer@1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/cordova-plugin-file-transfer/-/cordova-plugin-file-transfer-1.7.1.tgz#a75d8be2ebc3bb9b23c5b1bbd199214ec267586b" + integrity sha1-p12L4uvDu5sjxbG70ZkhTsJnWGs= + +cordova-plugin-file@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/cordova-plugin-file/-/cordova-plugin-file-6.0.1.tgz#49606b8c15a5688d4728f92e4a7325a061de07f5" + integrity sha1-SWBrjBWlaI1HKPkuSnMloGHeB/U= + cordova-plugin-httpd@0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/cordova-plugin-httpd/-/cordova-plugin-httpd-0.9.3.tgz#7cd658d83a661c76210db2b3e07f7044dea0599e" @@ -2218,6 +2235,17 @@ cordova-plugin-ionic-webview@^2.3.2: resolved "https://registry.yarnpkg.com/cordova-plugin-ionic-webview/-/cordova-plugin-ionic-webview-2.3.2.tgz#f4b1d669cefe7d25cfe47cfc9c6fe820211b63fa" integrity sha512-f7nXWTT93ZAJP4fMUxZWd8BacegTJNUK9Cocu0n2SH8gliAIjKzJtvSzEONSJ5b1Xp2osdUF6f5x+oWvyM90jQ== +cordova-plugin-ionic@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/cordova-plugin-ionic/-/cordova-plugin-ionic-5.3.0.tgz#9713a40b53a0e2938e4bf04611fd4efc2f7cd88a" + integrity sha512-INMNiPlBsgAndLBqOGvrvGhz/gV4PtLu7yOgRZ6cwQq7qBSnO59GheRZC97rh/1j5LakkKi9lJEeve8+xoz8jg== + dependencies: + "@types/cordova-plugin-file-transfer" "^1.6.2" + mkpath ">=1.0.0" + node-version-compare ">=1.0.1" + plist ">=1.2.0" + xml2js ">=0.4" + cordova-plugin-qrscanner@2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/cordova-plugin-qrscanner/-/cordova-plugin-qrscanner-2.6.0.tgz#e981be29d024cb37c11e28bbee87ba2544a29e2a" @@ -2241,11 +2269,6 @@ cordova-plugin-themeablebrowser@0.2.17: resolved "https://registry.yarnpkg.com/cordova-plugin-themeablebrowser/-/cordova-plugin-themeablebrowser-0.2.17.tgz#e55ba5da37694d51e61a06949580040dc9b69d7c" integrity sha1-5Vul2jdpTVHmGgaUlYAEDcm2nXw= -cordova-plugin-wechat@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/cordova-plugin-wechat/-/cordova-plugin-wechat-2.6.0.tgz#2c0e43570c2942fb42859b0e2ada737d3678435f" - integrity sha512-VyJSNGvBss46DYh7Wd+TRg0UMbiMJjZaV+PGa+U+UCvSjqk5+sq8OomBMwYc0mVneygbLBbpZbCT9ydQrJnRgA== - cordova-plugin-whitelist@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/cordova-plugin-whitelist/-/cordova-plugin-whitelist-1.3.3.tgz#b5e85ecdbbfe5aeded40a1bf4ee2372e67d96fb4" @@ -5367,14 +5390,12 @@ mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: dependencies: minimist "0.0.8" -moment-timezone@^0.5.23: - version "0.5.23" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.23.tgz#7cbb00db2c14c71b19303cb47b0fb0a6d8651463" - integrity sha512-WHFH85DkCfiNMDX5D3X7hpNH3/PUhjTGcD0U1SgfBGZxJ3qUmJh5FdvaFjcClxOvB3rzdfj4oRffbI38jEnC1w== - dependencies: - moment ">= 2.9.0" +mkpath@>=1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mkpath/-/mkpath-1.0.0.tgz#ebb3a977e7af1c683ae6fda12b545a6ba6c5853d" + integrity sha1-67Opd+evHGg65v2hK1Raa6bFhT0= -"moment@>= 2.9.0", moment@^2.24.0: +moment@^2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== @@ -5579,6 +5600,11 @@ node-sass@4.10.0: stdout-stream "^1.4.0" "true-case-path" "^1.0.2" +node-version-compare@>=1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/node-version-compare/-/node-version-compare-1.0.1.tgz#d85bfd20f0acade33577f56682c7109c34c550cd" + integrity sha1-2Fv9IPCsreM1d/VmgscQnDTFUM0= + nopt@1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.9.tgz#3bc0d7cba7bfb0d5a676dbed7c0ebe48a4fd454e" @@ -6223,7 +6249,7 @@ plist@2.1.0, plist@^2.1.0: xmlbuilder "8.2.2" xmldom "0.1.x" -plist@^3.0.1: +plist@>=1.2.0, plist@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" integrity sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ== @@ -8726,7 +8752,7 @@ xml-escape@1.1.0: resolved "https://registry.yarnpkg.com/xml-escape/-/xml-escape-1.1.0.tgz#3904c143fa8eb3a0030ec646d2902a2f1b706c44" integrity sha1-OQTBQ/qOs6ADDsZG0pAqLxtwbEQ= -xml2js@^0.4.17, xml2js@^0.4.19, xml2js@~0.4.19: +xml2js@>=0.4, xml2js@^0.4.17, xml2js@^0.4.19, xml2js@~0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==