Turn domain logic into its own component

This commit is contained in:
Hunter 2019-09-05 12:34:45 -04:00
parent bef658a6ef
commit 5ed12f6fd6
No known key found for this signature in database
GPG key ID: 54A2E2B4055799B8
11 changed files with 443 additions and 198 deletions

8
.editorconfig Normal file
View file

@ -0,0 +1,8 @@
root = true
[*.(vue,js,ts)]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 4
trim_trailing_whitespace = true

209
package-lock.json generated
View file

@ -1073,6 +1073,12 @@
}
}
},
"@types/eslint-visitor-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
"integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
"dev": true
},
"@types/events": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
@ -1090,6 +1096,12 @@
"@types/node": "*"
}
},
"@types/json-schema": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz",
"integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==",
"dev": true
},
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@ -1114,6 +1126,83 @@
"integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==",
"dev": true
},
"@types/webpack-env": {
"version": "1.14.0",
"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.14.0.tgz",
"integrity": "sha512-Fv+0gYJzE/czLoRKq+gnXWr4yBpPM3tO3C8pDLFwqVKlMICQUq5OsxwwFZYDaVr7+L6mgNDp16iOcJHEz3J5RQ==",
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.13.0.tgz",
"integrity": "sha512-WQHCozMnuNADiqMtsNzp96FNox5sOVpU8Xt4meaT4em8lOG1SrOv92/mUbEHQVh90sldKSfcOc/I0FOb/14G1g==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "1.13.0",
"eslint-utils": "^1.3.1",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^2.0.1",
"tsutils": "^3.7.0"
},
"dependencies": {
"regexpp": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
"integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
"dev": true
},
"tsutils": {
"version": "3.17.1",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz",
"integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==",
"dev": true,
"requires": {
"tslib": "^1.8.1"
}
}
}
},
"@typescript-eslint/experimental-utils": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz",
"integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/typescript-estree": "1.13.0",
"eslint-scope": "^4.0.0"
}
},
"@typescript-eslint/parser": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.13.0.tgz",
"integrity": "sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ==",
"dev": true,
"requires": {
"@types/eslint-visitor-keys": "^1.0.0",
"@typescript-eslint/experimental-utils": "1.13.0",
"@typescript-eslint/typescript-estree": "1.13.0",
"eslint-visitor-keys": "^1.0.0"
}
},
"@typescript-eslint/typescript-estree": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz",
"integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==",
"dev": true,
"requires": {
"lodash.unescape": "4.0.1",
"semver": "5.5.0"
},
"dependencies": {
"semver": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
"dev": true
}
}
},
"@vue/babel-helper-vue-jsx-merge-props": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0.tgz",
@ -1460,6 +1549,22 @@
}
}
},
"@vue/cli-plugin-typescript": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/@vue/cli-plugin-typescript/-/cli-plugin-typescript-3.11.0.tgz",
"integrity": "sha512-oL0ctNVvbD7gZr3DDv6gxxWjw0lUrh4sGMk7InCakEooo/790DqZRX6lx9stXEv/+zELkgddcY3hjNEopbJg+w==",
"dev": true,
"requires": {
"@types/webpack-env": "^1.13.9",
"@vue/cli-shared-utils": "^3.11.0",
"fork-ts-checker-webpack-plugin": "^0.5.2",
"globby": "^9.2.0",
"ts-loader": "^5.3.3",
"tslint": "^5.15.0",
"webpack": "^4.0.0",
"yorkie": "^2.0.0"
}
},
"@vue/cli-service": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-3.11.0.tgz",
@ -1601,6 +1706,16 @@
}
}
},
"@vue/eslint-config-typescript": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-4.0.0.tgz",
"integrity": "sha512-uSMAMgw4xDgVdZQhpbtJRo8nMV4oOy3Ht8olfOo7xvYFYLMF2JZ1tDRKd9/NSusxA72O2Vma+HzmyzDHg9evcQ==",
"dev": true,
"requires": {
"@typescript-eslint/eslint-plugin": "^1.1.0",
"@typescript-eslint/parser": "^1.1.0"
}
},
"@vue/preload-webpack-plugin": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.1.tgz",
@ -2674,6 +2789,12 @@
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
"dev": true
},
"builtin-modules": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
"dev": true
},
"builtin-status-codes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
@ -3472,9 +3593,9 @@
}
},
"core-js": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw=="
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz",
"integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A=="
},
"core-js-compat": {
"version": "3.2.1",
@ -4145,6 +4266,12 @@
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
"dev": true
},
"diff": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
"dev": true
},
"diffie-hellman": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
@ -5372,6 +5499,20 @@
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"fork-ts-checker-webpack-plugin": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-0.5.2.tgz",
"integrity": "sha512-a5IG+xXyKnpruI0CP/anyRLAoxWtp3lzdG6flxicANnoSzz64b12dJ7ASAVRrI2OaWwZR2JyBaMHFQqInhWhIw==",
"dev": true,
"requires": {
"babel-code-frame": "^6.22.0",
"chalk": "^2.4.1",
"chokidar": "^2.0.4",
"micromatch": "^3.1.10",
"minimatch": "^3.0.4",
"tapable": "^1.0.0"
}
},
"form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
@ -7466,6 +7607,12 @@
"integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=",
"dev": true
},
"lodash.unescape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz",
"integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=",
"dev": true
},
"lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@ -11426,12 +11573,55 @@
"integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
"dev": true
},
"ts-loader": {
"version": "5.4.5",
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz",
"integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==",
"dev": true,
"requires": {
"chalk": "^2.3.0",
"enhanced-resolve": "^4.0.0",
"loader-utils": "^1.0.2",
"micromatch": "^3.1.4",
"semver": "^5.0.1"
}
},
"tslib": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
"dev": true
},
"tslint": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.19.0.tgz",
"integrity": "sha512-1LwwtBxfRJZnUvoS9c0uj8XQtAnyhWr9KlNvDIdB+oXyT+VpsOAaEhEgKi1HrZ8rq0ki/AAnbGSv4KM6/AfVZw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.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.13.1",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"resolve": "^1.3.2",
"semver": "^5.3.0",
"tslib": "^1.8.0",
"tsutils": "^2.29.0"
}
},
"tsutils": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
"dev": true,
"requires": {
"tslib": "^1.8.1"
}
},
"tty-browserify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
@ -11817,6 +12007,11 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz",
"integrity": "sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ=="
},
"vue-class-component": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-7.1.0.tgz",
"integrity": "sha512-G9152NzUkz0i0xTfhk0Afc8vzdXxDR1pfN4dTwE72cskkgJtdXfrKBkMfGvDuxUh35U500g5Ve4xL8PEGdWeHg=="
},
"vue-eslint-parser": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz",
@ -11874,6 +12069,14 @@
"vue-style-loader": "^4.1.0"
}
},
"vue-property-decorator": {
"version": "8.2.2",
"resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-8.2.2.tgz",
"integrity": "sha512-3gRrIeoUtjXvkoMX2stJsVs7805Pa9MXEndnk21ej+sWO7AIc5HF1TKqK0Pox5TEjpO02UbadIF0QWNrx6ZwXQ==",
"requires": {
"vue-class-component": "^7.0.1"
}
},
"vue-style-loader": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",

View file

@ -5,27 +5,31 @@
"scripts": {
"serve": "vue-cli-service serve",
"build": "cross-env NODE_ENV=production vue-cli-service build",
"populate": "cross-env NODE_ENV=production tsc misc/populate_list.ts && cross-env node misc/populate_list.js",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"populate": "cross-env NODE_ENV=production tsc misc/populate_list.ts && cross-env node misc/populate_list.js"
},
"dependencies": {
"axios": "^0.19.0",
"bulma": "^0.7.5",
"core-js": "^3.2.1",
"core-js": "^2.6.9",
"node-sass": "^4.12.0",
"sass-loader": "^8.0.0",
"vue": "^2.6.10"
"vue": "^2.6.10",
"vue-class-component": "^7.1.0",
"vue-property-decorator": "^8.2.2"
},
"devDependencies": {
"@babel/preset-env": "^7.5.5",
"@vue/cli-plugin-babel": "^3.11.0",
"@vue/cli-plugin-eslint": "^3.11.0",
"@vue/cli-service": "^3.11.0",
"@vue/eslint-config-typescript": "^4.0.0",
"babel-eslint": "^10.0.3",
"cross-env": "^5.2.1",
"eslint": "^6.3.0",
"eslint-plugin-vue": "^5.2.3",
"typescript": "^3.6.2",
"@vue/cli-plugin-typescript": "^3.11.0",
"vue-template-compiler": "^2.6.10"
},
"eslintConfig": {
@ -35,11 +39,12 @@
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
"eslint:recommended",
"@vue/typescript"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
"parser": "@typescript-eslint/parser"
}
},
"postcss": {

View file

@ -6,7 +6,6 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="preload" href="<$= BASE_URL %>iata.json" as="fetch">
<title>cloudflare-test.judge.sh</title>
</head>

View file

@ -1,18 +1,19 @@
<template>
<div id="app" class="container">
<div id="app" class="container">
<Main/>
</div>
</div>
</template>
<script>
import Main from './components/Main.vue'
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Main from './components/Main.vue';
export default {
name: 'app',
@Component({
components: {
Main
}
}
Main,
},
})
export default class App extends Vue {}
</script>
<style lang="scss">

View file

@ -0,0 +1,66 @@
<template>
<div>
<p class="heading" v-text="hostname" />
<div v-if="finished">
<p class="title" v-text="datacenter" />
<p class="heading" v-text="airport" />
<p class="heading">First ping: {{ firstPing }}</p>
<p class="heading">Second ping: {{ secondPing }}</p>
</div>
<div v-if="broken">
<p>Likely not a Cloudflare website, or not proxied</p>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop } from "vue-property-decorator";
import Axios from "axios";
@Component
export default class DomainItem extends Vue {
// @ts-ignore
@Prop(String) readonly hostname: string;
finished = false;
broken = false;
datacenter = "";
airport = "";
firstPing = 0;
secondPing = 0;
mounted() {
this.loadHostname(this.hostname)
.then(datacenter => {
this.datacenter = datacenter;
// @ts-ignore
this.airport = this.$parent.getAirport(datacenter);
})
.then(() => this.loadHostname(this.hostname, 1))
.then(() => {
this.firstPing = this.loadPing(this.hostname, 0);
this.secondPing = this.loadPing(this.hostname, 1);
this.finished = true;
})
.catch(() => {
this.broken = true;
});
}
loadPing(hostname: string, loadNumber = 0) {
let timing = performance
.getEntriesByType("resource")
.filter(timing => timing.name.includes(hostname))
.filter(timing => timing.name.includes(`load=${loadNumber}`))[0];
// @ts-ignore
return Math.floor(timing.responseEnd - timing.startTime);
}
loadHostname(hostname: string, loadNumber = 0): Promise<string> {
return Axios.get(
`https://${hostname}/cdn-cgi/trace?load=${loadNumber}`
).then(response => {
return response.data
.split("\n")
.map((n: string) => n.split("="))
.filter((element: string[]) => element[0] == "colo")[0][1];
});
}
}
</script>

View file

@ -2,10 +2,14 @@
<div class="main-content">
<div class="container has-text-centered">
<h1 class="title">Cloudflare datacenter reachability</h1>
<h2 class="subtitle"><a href="https://github.com/judge2020/cloudflare-connectivity-test/wiki/Explanation">Explanation</a></h2>
<h2 class="subtitle">
<a
href="https://github.com/judge2020/cloudflare-connectivity-test/wiki/Explanation"
>Explanation</a>
</h2>
<p class="subtitle">Test your website:</p>
<form @submit="loadTestHostname(testHostname)">
<form @submit.prevent="loadTestHostname(testHostname)">
<div class="field has-addons has-addons-centered">
<div class="control">
<input
@ -13,7 +17,6 @@
type="text"
placeholder="example.com"
v-model="testHostname"
@blur="loadTestHostname(testHostname)"
/>
</div>
<div class="control">
@ -22,15 +25,8 @@
</div>
</form>
<div class="domain-item" v-if="testHostname">
<p class="heading" v-text="testHostname" />
<div v-if="testHostname in finished">
<p class="title" v-text="finished[testHostname]" />
<p class="heading" v-text="iata[finished[testHostname]]" />
<p class="heading">First ping: {{ timingsFirst[testHostname] }}</p>
<p class="heading">Second ping: {{ timingsSecond[testHostname] }}</p>
</div>
<p v-show="testHostname in broken">Likely not a Cloudflare website!</p>
<div class="domain-item" v-if="testHostname" :key="testHostname">
<domain-item :hostname="testHostname" />
</div>
<hr />
</div>
@ -39,53 +35,28 @@
<div class="column">
<p class="title">FREE</p>
<div class="domain-item" v-for="(site, index) in free" :key="index">
<p class="heading" v-text="site" />
<div v-if="site in finished">
<p class="title" v-text="finished[site]" />
<p class="heading" v-text="iata[finished[site]]" />
<p class="heading">First ping: {{ timingsFirst[site] }}</p>
<p class="heading">Second ping: {{ timingsSecond[site] }}</p>
</div>
<domain-item :hostname="site" />
<hr />
</div>
</div>
<div class="column list-domains">
<p class="title">PRO</p>
<div class="domain-item" v-for="(site, index) in pro" :key="index">
<p class="heading" v-text="site" />
<div v-if="site in finished">
<p class="title" v-text="finished[site]" />
<p class="heading" v-text="iata[finished[site]]" />
<p class="heading">First ping: {{ timingsFirst[site] }}</p>
<p class="heading">Second ping: {{ timingsSecond[site] }}</p>
</div>
<domain-item :hostname="site" />
<hr />
</div>
</div>
<div class="column list-domains">
<p class="title">BUSINESS</p>
<div class="domain-item" v-for="(site, index) in business" :key="index">
<p class="heading" v-text="site" />
<div v-if="site in finished">
<p class="title" v-text="finished[site]" />
<p class="heading" v-text="iata[finished[site]]" />
<p class="heading">First ping: {{ timingsFirst[site] }}</p>
<p class="heading">Second ping: {{ timingsSecond[site] }}</p>
</div>
<domain-item :hostname="site" />
<hr />
</div>
</div>
<div class="column list-domains">
<p class="title">ENTERPRISE</p>
<div class="domain-item" v-for="(site, index) in enterprise" :key="index">
<p class="heading" v-text="site" />
<div v-if="site in finished">
<p class="title" v-text="finished[site]" />
<p class="heading" v-text="iata[finished[site]]" />
<p class="heading">First ping: {{ timingsFirst[site] }}</p>
<p class="heading">Second ping: {{ timingsSecond[site] }}</p>
</div>
<domain-item :hostname="site" />
<hr />
</div>
</div>
@ -112,153 +83,89 @@
</template>
<script>
import Vue from "vue";
import { Vue, Component, Prop } from "vue-property-decorator";
import Axios from "axios";
export default {
name: "Main",
props: {},
data() {
return {
testHostname: "",
iata: [],
timingsFirst: [],
timingsSecond: [],
finished: [],
broken: [],
free: [
"judge2020.com",
"domjh.net",
"digital.com",
"firing.it",
"www.shoutmeloud.com",
"judge2020.me",
"cloudeereviews.com"
],
pro: [
"js.org",
"git-scm.com",
"nodejs.org",
"cdnjs.com",
"getbootstrap.com",
"reactjs.org",
"html5boilerplate.com",
"yarnpkg.com",
"d3js.org"
],
business: [
"judge.sh",
"www.mozilla.org",
"domjh.com",
"manfredi.io",
"corporateclash.net",
"sontusdatos.org",
"www.opentech.fund",
"cpj.org",
"www.amnestyusa.org",
"cdt.org",
"www.counterextremism.com",
"www.ndi.org",
"www.findlaw.com",
"www.codeguard.com",
"www.techagainstterrorism.org",
"www.thetrevorproject.org"
],
enterprise: [
"cloudflare.com",
"cdnjs.cloudflare.com",
"medium.com",
"discordapp.com",
"www.zendesk.com",
"ghost.io",
"unpkg.com",
"www.loc.gov",
"www.artstation.com",
"www.digitalocean.com",
"quizlet.com",
"i.gyazo.com"
]
};
},
import DomainItem from "./DomainItem";
@Component({
components: {
DomainItem
}
})
export default class Main extends Vue {
iata = [];
free = [
"judge2020.com",
"domjh.net",
"digital.com",
"firing.it",
"www.shoutmeloud.com",
"judge2020.me",
"cloudeereviews.com"
];
pro = [
"js.org",
"git-scm.com",
"nodejs.org",
"cdnjs.com",
"getbootstrap.com",
"reactjs.org",
"html5boilerplate.com",
"yarnpkg.com",
"d3js.org"
];
business = [
"judge.sh",
"www.mozilla.org",
"domjh.com",
"manfredi.io",
"corporateclash.net",
"sontusdatos.org",
"www.opentech.fund",
"cpj.org",
"www.amnestyusa.org",
"cdt.org",
"www.counterextremism.com",
"www.ndi.org",
"www.findlaw.com",
"www.codeguard.com",
"www.techagainstterrorism.org",
"www.thetrevorproject.org"
];
enterprise = [
"cloudflare.com",
"cdnjs.cloudflare.com",
"medium.com",
"discordapp.com",
"www.zendesk.com",
"ghost.io",
"unpkg.com",
"www.loc.gov",
"www.artstation.com",
"www.digitalocean.com",
"quizlet.com",
"i.gyazo.com"
];
mounted() {
this.preloadAirports();
this.free
.concat(this.pro, this.business, this.enterprise)
.forEach(hostname => {
this.loadHostname(hostname, 0)
.then(() => {
// load UI with ping data
this.loadPing(hostname, 0);
// begin promise for second ping (TCP and DNS overhead should be gone)
return this.loadHostname(hostname, 1);
})
.then(() => {
// load UI with second ping data
this.loadPing(hostname, 1);
});
});
// load query string hostname
if (location.hash) {
this.testHostname = location.hash.replace("#", "");
this.loadTestHostname(this.testHostname);
this.$forceUpdate();
}
},
methods: {
loadPing(hostname, loadNumber = 0) {
performance
.getEntriesByType("resource")
.filter(timing => timing.name.includes(hostname))
.filter(timing => timing.name.includes(`load=${loadNumber}`))
.forEach(timing => {
if (loadNumber == 0) {
this.timingsFirst[new URL(timing.name).hostname] = Math.floor(
timing.responseEnd - timing.startTime
);
} else {
this.timingsSecond[new URL(timing.name).hostname] = Math.floor(
timing.responseEnd - timing.startTime
);
}
});
this.$forceUpdate();
},
preloadAirports() {
Axios.get("/iata.json").then(response => {
this.iata = response.data;
});
},
loadTestHostname(hostname) {
history.replaceState(
"",
"",
hostname.includes("#") ? hostname : "#" + hostname
);
this.loadHostname(hostname, 0)
.then(() => {
this.loadPing(hostname, 0);
return this.loadHostname(hostname, 1);
})
.then(() => {
this.loadPing(hostname, 1);
});
},
loadHostname(hostname, loadNumber = 0) {
return Axios.get(
`https://${hostname}/cdn-cgi/trace?load=${loadNumber}`
).then(response => {
response.data
.split("\n")
.map(n => n.split("="))
.forEach(element => {
if (element[0] == "colo") {
Vue.set(this.finished, hostname, element[1]);
}
});
});
}
}
};
loadTestHostname() {
this.$forceUpdate();
}
getAirport(code) {
return this.iata[code];
}
preloadAirports() {
Axios.get("/iata.json").then(response => {
this.iata = response.data;
});
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->

13
src/shims-tsx.d.ts vendored Normal file
View file

@ -0,0 +1,13 @@
import Vue, { VNode } from 'vue'
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any
}
}
}

4
src/shims-vue.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}

39
tsconfig.json Normal file
View file

@ -0,0 +1,39 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}