76 lines
2.0 KiB
TypeScript
76 lines
2.0 KiB
TypeScript
import { IncomingMessage, net } from 'electron'
|
|
import fs from 'fs'
|
|
import path from 'path'
|
|
import { pipeline as pipelineFn } from 'stream'
|
|
import { promisify } from 'util'
|
|
import { MessageType } from '../../../../test/TestIpcMessage'
|
|
import { ensureDirectoryExists } from '../Utils/FileUtils'
|
|
import { handleTestMessage } from '../Utils/Testing'
|
|
import { isTesting } from '../Utils/Utils'
|
|
|
|
const pipeline = promisify(pipelineFn)
|
|
|
|
if (isTesting()) {
|
|
handleTestMessage(MessageType.GetJSON, getJSON)
|
|
handleTestMessage(MessageType.DownloadFile, downloadFile)
|
|
}
|
|
|
|
/**
|
|
* Downloads a file to the specified destination.
|
|
* @param filePath path to the saved file (will be created if it does
|
|
* not exist)
|
|
*/
|
|
export async function downloadFile(url: string, filePath: string): Promise<void> {
|
|
await ensureDirectoryExists(path.dirname(filePath))
|
|
const response = await get(url)
|
|
await pipeline(
|
|
/**
|
|
* IncomingMessage doesn't implement *every* property of ReadableStream
|
|
* but still all the ones that pipeline needs
|
|
* @see https://www.electronjs.org/docs/api/incoming-message
|
|
*/
|
|
response as any,
|
|
fs.createWriteStream(filePath),
|
|
)
|
|
}
|
|
|
|
export async function getJSON<T>(url: string): Promise<T | undefined> {
|
|
const response = await get(url)
|
|
let data = ''
|
|
return new Promise((resolve, reject) => {
|
|
response
|
|
.on('data', (chunk) => {
|
|
data += chunk
|
|
})
|
|
.on('error', reject)
|
|
.on('end', () => {
|
|
try {
|
|
const parsed = JSON.parse(data)
|
|
resolve(parsed)
|
|
} catch (error) {
|
|
resolve(undefined)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
export function get(url: string): Promise<IncomingMessage> {
|
|
const enum Method {
|
|
Get = 'GET',
|
|
}
|
|
const enum RedirectMode {
|
|
Follow = 'follow',
|
|
}
|
|
|
|
return new Promise<IncomingMessage>((resolve, reject) => {
|
|
const request = net.request({
|
|
url,
|
|
method: Method.Get,
|
|
redirect: RedirectMode.Follow,
|
|
})
|
|
request.on('response', resolve)
|
|
request.on('error', reject)
|
|
request.end()
|
|
})
|
|
}
|