UNPKG

electron-info

Version:

Get useful data about Electron releases.

97 lines (96 loc) 4.07 kB
import logdown from 'logdown'; import { promises as fs, constants as fsConstants } from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import { URL } from 'node:url'; import { HTTPService } from './HTTPService.js'; export class FileService { constructor(options) { this.options = options; this.logger = logdown('electron-info/FileService', { logger: console, markdown: false, }); if (this.options.debug) { this.logger.state.isEnabled = true; } this.logger.log('Initialized', this.options); this.httpService = new HTTPService({ debug: this.options.debug, timeout: this.options.timeout, }); } async getReleases() { this.logger.log('Parsing releases URL', { releasesUrl: this.options.releasesUrl }); const parsedUrl = new URL(this.options.releasesUrl); if (!parsedUrl.href) { throw new Error('Invalid releases URL provided'); } if (parsedUrl.protocol === 'file') { this.logger.log('Releases URL points to a local file:', { releasesUrl: this.options.releasesUrl }); return this.loadReleasesFile(path.resolve(this.options.releasesUrl)); } this.logger.log('Releases URL points to a URL:', { releasesUrl: this.options.releasesUrl }); const tempDirectory = await this.createTempDir(); const tempFile = path.join(tempDirectory, 'latest.json'); const tempFileExists = await this.isPathReadable(tempFile); if (this.options.forceUpdate) { this.logger.log(`Force download of the releases file requested`, { forceUpdate: this.options.forceUpdate, releasesUrl: this.options.releasesUrl, tempFile, }); return this.httpService.downloadReleasesFile(this.options.releasesUrl, tempFile); } if (tempFileExists) { this.logger.log('Found a local copy of the releases file:', { tempFile }); const tempFileFromToday = await this.isFileFromToday(tempFile); this.logger.log(`Releases file "${tempFile}" is less than 24 hours old:`, tempFileFromToday); if (tempFileFromToday) { return this.loadReleasesFile(tempFile); } } return this.httpService.downloadReleasesFile(this.options.releasesUrl, tempFile); } async createTempDir() { const tempDirectory = this.options.tempDirectory || path.join(os.tmpdir(), 'electron-info'); const tempDirectoryExists = await this.isPathReadable(tempDirectory); if (!tempDirectoryExists) { this.logger.log('Creating temp directory', { tempDirectory }); await fs.mkdir(tempDirectory); } else { this.logger.log('Temp directory exists', { tempDirectory }); } return tempDirectory; } async isFileFromToday(fileName) { const { mtime: fileModifiedDate } = await fs.stat(fileName); this.logger.log(`File "${fileName}" is from "${fileModifiedDate.toString()}"`); return isWithinLastDay(fileModifiedDate); } async isPathReadable(filePath) { try { await fs.access(filePath, fsConstants.F_OK | fsConstants.R_OK); return true; } catch (error) { this.logger.log('File is not readable:', { errorMessage: error.message }); return false; } } async loadReleasesFile(localPath) { this.logger.log('Loading local releases file:', { localPath }); const rawData = await fs.readFile(localPath, 'utf8'); const releases = JSON.parse(rawData); if (!Array.isArray(releases)) { throw new Error('Invalid data in releases file'); } return releases; } } export function isWithinLastDay(date, now = new Date()) { const yesterday = new Date(now); yesterday.setUTCDate(yesterday.getUTCDate() - 1); return date > yesterday; }