about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVeetaha <gerzoh1@gmail.com>2020-02-07 03:11:24 +0200
committerVeetaha <gerzoh1@gmail.com>2020-02-08 04:34:11 +0200
commit3e0e4e90aeeff25db674f8db562c611bd8016482 (patch)
tree638756f88bf4c370135b3984667c2618438f6d01
parent1bdb78a89f6618527f2dc23f8f76e83ee77e3ea5 (diff)
downloadrust-3e0e4e90aeeff25db674f8db562c611bd8016482.tar.gz
rust-3e0e4e90aeeff25db674f8db562c611bd8016482.zip
added fetchLatestArtifactMetadata() and downloadFile() functions
-rw-r--r--editors/code/package-lock.json25
-rw-r--r--editors/code/package.json6
-rw-r--r--editors/code/src/github/download_file.ts26
-rw-r--r--editors/code/src/github/fetch_latest_artifact_metadata.ts55
4 files changed, 111 insertions, 1 deletions
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json
index 353af06bf73..5c056463e08 100644
--- a/editors/code/package-lock.json
+++ b/editors/code/package-lock.json
@@ -82,6 +82,15 @@
             "integrity": "sha512-nf1LMGZvgFX186geVZR1xMZKKblJiRfiASTHw85zED2kI1yDKHDwTKMdkaCbTlXoRKlGKaDfYywt+V0As30q3w==",
             "dev": true
         },
+        "@types/node-fetch": {
+            "version": "2.5.4",
+            "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.4.tgz",
+            "integrity": "sha512-Oz6id++2qAOFuOlE1j0ouk1dzl3mmI1+qINPNBhi9nt/gVOz0G+13Ao6qjhdF0Ys+eOkhu6JnFmt38bR3H0POQ==",
+            "dev": true,
+            "requires": {
+                "@types/node": "*"
+            }
+        },
         "@types/resolve": {
             "version": "0.0.8",
             "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
@@ -91,6 +100,12 @@
                 "@types/node": "*"
             }
         },
+        "@types/throttle-debounce": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz",
+            "integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==",
+            "dev": true
+        },
         "@types/vscode": {
             "version": "1.41.0",
             "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.41.0.tgz",
@@ -536,6 +551,11 @@
             "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
             "dev": true
         },
+        "node-fetch": {
+            "version": "2.6.0",
+            "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
+            "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
+        },
         "nth-check": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
@@ -719,6 +739,11 @@
                 "has-flag": "^3.0.0"
             }
         },
+        "throttle-debounce": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.1.0.tgz",
+            "integrity": "sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg=="
+        },
         "tmp": {
             "version": "0.0.29",
             "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz",
diff --git a/editors/code/package.json b/editors/code/package.json
index 11d37053eb4..8e23718cda3 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -25,18 +25,22 @@
     },
     "dependencies": {
         "jsonc-parser": "^2.1.0",
+        "node-fetch": "^2.6.0",
+        "throttle-debounce": "^2.1.0",
         "vscode-languageclient": "^6.1.0"
     },
     "devDependencies": {
         "@rollup/plugin-commonjs": "^11.0.2",
         "@rollup/plugin-node-resolve": "^7.1.1",
         "@types/node": "^12.12.25",
+        "@types/node-fetch": "^2.5.4",
+        "@types/throttle-debounce": "^2.1.0",
         "@types/vscode": "^1.41.0",
         "rollup": "^1.31.0",
         "tslib": "^1.10.0",
         "tslint": "^5.20.1",
-        "typescript-formatter": "^7.2.2",
         "typescript": "^3.7.5",
+        "typescript-formatter": "^7.2.2",
         "vsce": "^1.71.0"
     },
     "activationEvents": [
diff --git a/editors/code/src/github/download_file.ts b/editors/code/src/github/download_file.ts
new file mode 100644
index 00000000000..f40750be905
--- /dev/null
+++ b/editors/code/src/github/download_file.ts
@@ -0,0 +1,26 @@
+import fetch from "node-fetch";
+import { throttle } from "throttle-debounce";
+import * as fs from "fs";
+
+export async function downloadFile(
+    url: string,
+    destFilePath: fs.PathLike,
+    onProgress: (readBytes: number, totalBytes: number) => void
+): Promise<void> {
+    onProgress = throttle(100, /* noTrailing: */ true, onProgress);
+
+    const response = await fetch(url);
+
+    const totalBytes = Number(response.headers.get('content-length'));
+    let readBytes = 0;
+
+    return new Promise<void>((resolve, reject) => response.body
+        .on("data", (chunk: Buffer) => {
+            readBytes += chunk.length;
+            onProgress(readBytes, totalBytes);
+        })
+        .on("end", resolve)
+        .on("error", reject)
+        .pipe(fs.createWriteStream(destFilePath))
+    );
+}
diff --git a/editors/code/src/github/fetch_latest_artifact_metadata.ts b/editors/code/src/github/fetch_latest_artifact_metadata.ts
new file mode 100644
index 00000000000..52641ca67d6
--- /dev/null
+++ b/editors/code/src/github/fetch_latest_artifact_metadata.ts
@@ -0,0 +1,55 @@
+import fetch from "node-fetch";
+
+const GITHUB_API_ENDPOINT_URL = "https://api.github.com";
+
+export interface FetchLatestArtifactMetadataOpts {
+    repoName: string;
+    repoOwner: string;
+    artifactFileName: string;
+}
+
+export interface ArtifactMetadata {
+    releaseName: string;
+    releaseDate: Date;
+    downloadUrl: string;
+}
+
+export async function fetchLatestArtifactMetadata(
+    opts: FetchLatestArtifactMetadataOpts
+): Promise<ArtifactMetadata | null> {
+
+    const repoOwner = encodeURIComponent(opts.repoOwner);
+    const repoName  = encodeURIComponent(opts.repoName);
+
+    const apiEndpointPath = `/repos/${repoOwner}/${repoName}/releases/latest`;
+    const requestUrl = GITHUB_API_ENDPOINT_URL + apiEndpointPath;
+
+    // We skip runtime type checks for simplicity (here we cast from `any` to `Release`)
+
+    const response: GithubRelease = await fetch(requestUrl, {
+            headers: { Accept: "application/vnd.github.v3+json" }
+        })
+        .then(res => res.json());
+
+    const artifact = response.assets.find(artifact => artifact.name === opts.artifactFileName);
+
+    return !artifact ? null : {
+        releaseName: response.name,
+        releaseDate: new Date(response.published_at),
+        downloadUrl: artifact.browser_download_url
+    };
+
+    // Noise denotes tremendous amount of data that we are not using here
+    interface GithubRelease {
+        name: string;
+        published_at: Date;
+        assets: Array<{
+            browser_download_url: string;
+
+            [noise: string]: unknown;
+        }>;
+
+        [noise: string]: unknown;
+    }
+
+}