import { createWriteStream, promises as fs } from 'fs'; import { Readable, pipeline } from 'stream'; import { promisify } from 'util'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import * as smartarchive from '@push.rocks/smartarchive'; const streamPipeline = promisify(pipeline); interface IRelease { id: number; tag_name: string; assets: IAsset[]; } interface IAsset { url: string; name: string; } class ResticReleaseDownloader { private baseUrl: string; constructor() { this.baseUrl = 'https://api.github.com/repos/restic/restic/releases'; } public async getPackageVersion(): Promise { // Get the directory of the current module const currentDir = dirname(fileURLToPath(import.meta.url)); // Construct the path to the package.json file const packageJsonPath = join(currentDir, '../package.json'); // Read the package.json file const packageJsonData = await fs.readFile(packageJsonPath, 'utf8'); // Parse the package.json file const packageJson = JSON.parse(packageJsonData); // Return the version return packageJson.version; }; public async downloadAllReleases(targetFolder: string): Promise { const releases = await this.fetchReleases(); for (const release of releases) { if (release.tag_name === `v${await this.getPackageVersion()}`) { console.log(`Downloading restic v${await this.getPackageVersion()}`); await this.downloadAssets(release, targetFolder); } else { continue; } } } private async fetchReleases(): Promise { const response = await fetch(this.baseUrl); if (!response.ok) { throw new Error(`Failed to fetch releases: ${response.statusText}`); } return response.json(); } private async downloadAssets(release: IRelease, targetFolder: string): Promise { for (const asset of release.assets) { console.error(`Downloading: ${asset.name}`); const response = await fetch(asset.url, { headers: { 'Accept': 'application/octet-stream' } }); if (!response.ok) { console.error(`Failed to download asset: ${asset.name}`); continue; } else { console.log(`Downloaded asset: ${asset.name} successfully!!!`); } const asyncIterable = { async *[Symbol.asyncIterator]() { const reader = response.body.getReader(); while (true) { const { done, value } = await reader.read(); if (done) break; yield value; } } }; const readableStream = Readable.from(asyncIterable); const unpackStream = smartarchive.SmartArchive.fromArchiveStream(readableStream) unpackStream } } } // lets do the actual work const downloader = new ResticReleaseDownloader(); const targetFolder = join(dirname(fileURLToPath(import.meta.url)), '../.nogit/resticbins/'); await fs.mkdir(targetFolder, { recursive: true }); await downloader.downloadAllReleases(targetFolder);