diff --git a/.gitignore b/.gitignore index 1007f72..abbbbfa 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ dist **/coverage yarn-error.log builtin +assets diff --git a/package.json b/package.json index d54fbe9..638d37c 100644 --- a/package.json +++ b/package.json @@ -20,16 +20,14 @@ ] }, "scripts": { - "build": "rollup --bundleConfigAsCjs --config rollup.config.js --compact --environment BUILD:production && node ./scripts/build.js", + "build": "rollup --bundleConfigAsCjs --config rollup.config.js --compact --environment BUILD:production && npx ts-node --esm ./scripts/download.mts && node ./scripts/build.js", "watch": "rollup --bundleConfigAsCjs --config rollup.config.js -w", "desk:build": "node ./scripts/run.mjs build", "desk:prepare": "node ./scripts/run.mjs prepare", "desk:run": "node ./scripts/run.mjs run", "desk:clean": "node ./scripts/run.mjs clean" }, - "dependencies": { - "got": "^12.5.3" - }, + "dependencies": {}, "devDependencies": { "7zip-min": "^1.4.4", "@rollup/plugin-commonjs": "^24.0.1", @@ -37,8 +35,11 @@ "@rollup/plugin-node-resolve": "^15.0.1", "@rollup/plugin-typescript": "^11.0.0", "@types/node": "^18.14.6", + "got": "^12.5.3", + "hasha": "^5.2.2", "mkdirp": "^2.1.3", "rollup": "^3.18.0", + "ts-node": "^10.9.1", "tslib": "^2.5.0", "typescript": "^4.9.5", "zip-local": "^0.3.5" diff --git a/scripts/build.js b/scripts/build.js index ea7e3a9..d00fb8f 100755 --- a/scripts/build.js +++ b/scripts/build.js @@ -36,7 +36,6 @@ if (fs.existsSync(builtinDirectory)) { } const zip = zipper.sync.zip(path.resolve(__dirname, '../')); -zip.lowLevel().remove('assets'); zip.lowLevel().remove('.git'); zip.lowLevel().remove('node_modules'); zip.compress().save(destFile); diff --git a/scripts/download.mts b/scripts/download.mts new file mode 100644 index 0000000..acdac37 --- /dev/null +++ b/scripts/download.mts @@ -0,0 +1,161 @@ +#!/usr/bin/env node +/********************************************************************** + * Copyright (C) 2023 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import * as readline from 'node:readline'; +import got from 'got'; +import hasha from 'hasha'; +import { fileURLToPath } from 'url'; + +import bundledCrc from '../src/crc.json' assert {type: 'json'}; + + +const __filename = fileURLToPath(import.meta.url); + +const __dirname = path.dirname(__filename); + +const platform = process.platform; + +const MAX_DOWNLOAD_ATTEMPT = 3; +let downloadAttempt = 0; + +const platformToInstallFileName = { + 'darwin': 'crc-macos-installer.pkg', + 'win32': 'crc-windows-installer.zip', + 'linux': 'crc-linux-amd64.tar.xz', +}; + + +async function checkFileSha(filePath: string, shaSum: string): Promise { + const sha256sum: string = await hasha.fromFile(filePath, { algorithm: 'sha256' }); + return sha256sum === shaSum; +} + +async function downloadAndCheckSha(downloadUrl: string, destFile: string, fileSha: string): Promise{ + if (downloadAttempt >= MAX_DOWNLOAD_ATTEMPT) { + console.error('Max download attempt reached, exiting...'); + process.exit(1); + } + + let lastProgressStr = ''; + + process.stdout.write('Downloading:\n'); + + + const downloadResponse = await got(downloadUrl).on('downloadProgress', (progress) => { + const progressStr = progress.transferred + ' of ' + progress.total + ' ' + Math.round(progress.percent * 100) + '%'; + if(lastProgressStr !== progressStr) { + readline.cursorTo(process.stdout, 0); + process.stdout.write(progressStr); + readline.clearLine(process.stdout, 1); + lastProgressStr = progressStr; + } + }); + // add new line after download percentage + process.stdout.write('\n'); + + fs.appendFileSync(destFile, Buffer.from(downloadResponse.rawBody)); + console.log(`Downloaded to ${destFile}`); + + console.log(`Verifying ${destFile}...`); + + if (!(await checkFileSha(destFile, fileSha))) { + console.warn(`Checksum for downloaded ${destFile} is not match, downloading again...`); + fs.rmSync(destFile); + downloadAttempt++; + downloadAndCheckSha(downloadUrl, destFile, fileSha); + } else { + console.log(`Checksum for ${destFile} is matched.`); + } + +} + +async function downloadCrc(): Promise { + + console.info(`Found CRC: ${bundledCrc.version.crcVersion}`); + + + let releaseUrl: string; + + if(platform === 'win32'){ + releaseUrl = bundledCrc.links.windows; + } else if(platform === 'darwin') { + releaseUrl = bundledCrc.links.darwin; + } else { + releaseUrl = bundledCrc.links.linux; + } + + console.info('Download SHA sums...'); + const shaSumUrl = releaseUrl.substring(0, releaseUrl.lastIndexOf('/')) + '/sha256sum.txt'; + const shaSumContentResponse = await got.get(shaSumUrl); + + const installerFileName = platformToInstallFileName[platform]; + if(!installerFileName) { + console.error('Can\'t find installer file name. Exiting...'); + process.exit(1); + } + + + const shasSumArr = shaSumContentResponse.body.split('\n'); + + let installerSha = ''; + for(const shaLine of shasSumArr){ + if(shaLine.trim().endsWith(installerFileName)) { + installerSha = shaLine.split(' ')[0]; + break; + } + } + + if(!installerSha) { + console.error(`Can't find SHA256 sum for ${installerFileName} in:\n${shaSumContentResponse.body}`); + process.exit(1); + } + + const destDir = path.resolve(__dirname, '..', 'assets'); + if (!fs.existsSync(destDir)) { + fs.mkdirSync(destDir); + } + const destFile = path.resolve(destDir, installerFileName); + + if (!fs.existsSync(destFile)) { + console.log(`Downloading Podman package from ${releaseUrl}`); + downloadAndCheckSha(releaseUrl, destFile, installerSha); + return; + } else { + console.log(`Podman package ${releaseUrl} already downloaded.`); + } + + console.log(`Verifying ${installerFileName}...`); + + if (!(await checkFileSha(destFile, installerSha))) { + console.warn(`Checksum for downloaded ${destFile} is not match, downloading again...`); + fs.rmSync(destFile); + downloadAttempt++; + downloadAndCheckSha(releaseUrl, destFile, installerSha); + } else { + console.log(`Checksum for ${installerFileName} is matched.`); + } + +} + + +if(platform === 'win32' /*|| platform === 'darwin'*/){ + downloadCrc(); +} diff --git a/scripts/run.mjs b/scripts/run.mjs index 7dc86bc..aadc946 100644 --- a/scripts/run.mjs +++ b/scripts/run.mjs @@ -41,7 +41,11 @@ async function exec(command, args, options) { const proc = cp.spawn(command, args, options); proc.stderr.pipe(process.stderr); proc.stdout.pipe(process.stdout); - proc.on('close', () => { + proc.on('close', (code) => { + if(code !== 0){ + reject(code); + return; + } resolve(); }); diff --git a/src/crc.json b/src/crc.json new file mode 100644 index 0000000..bd1a7bb --- /dev/null +++ b/src/crc.json @@ -0,0 +1,13 @@ +{ + "version": { + "crcVersion": "2.14.0", + "gitSha": "1a1ef27", + "openshiftVersion": "4.12.1", + "podmanVersion": "4.3.1" + }, + "links": { + "linux": "https://developers.redhat.com/content-gateway/file/pub/openshift-v4/clients/crc/2.14.0/crc-linux-amd64.tar.xz", + "darwin": "https://developers.redhat.com/content-gateway/file/pub/openshift-v4/clients/crc/2.14.0/crc-macos-installer.pkg", + "windows": "https://developers.redhat.com/content-gateway/file/pub/openshift-v4/clients/crc/2.14.0/crc-windows-installer.zip" + } +} diff --git a/src/extension.ts b/src/extension.ts index 2d1e85d..b19dc28 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -23,9 +23,10 @@ import * as fs from 'node:fs'; import type { Status } from './daemon-commander'; import { DaemonCommander } from './daemon-commander'; import { LogProvider } from './log-provider'; -import { isWindows } from './util'; +import { getAssetsFolder, isWindows } from './util'; import { daemonStart, daemonStop, getCrcVersion } from './crc-cli'; import { getCrcDetectionChecks } from './detection-checks'; +import { CrcInstall } from './install/crc-install'; const commander = new DaemonCommander(); let statusFetchTimer: NodeJS.Timer; @@ -37,32 +38,16 @@ const crcLogProvider = new LogProvider(commander); const defaultStatus = { CrcStatus: 'Unknown', Preset: 'Unknown' }; export async function activate(extensionContext: extensionApi.ExtensionContext): Promise { + const crcInstaller = new CrcInstall(); + const crcVersion = await getCrcVersion(); const detectionChecks: extensionApi.ProviderDetectionCheck[] = []; let status: extensionApi.ProviderStatus = 'not-installed'; - let preset = 'unknown'; + if (crcVersion) { status = 'installed'; - - const daemonStarted = await daemonStart(); - if (!daemonStarted) { - //TODO handle this - return; - } - - try { - // initial status - crcStatus = await commander.status(); - } catch (err) { - console.error('error in CRC extension', err); - crcStatus = defaultStatus; - } - - // detect preset of CRC - preset = readPreset(crcStatus); - - startStatusUpdateTimer(); + connectToCrc(); } detectionChecks.push(...getCrcDetectionChecks(crcVersion)); @@ -109,12 +94,22 @@ export async function activate(extensionContext: extensionApi.ExtensionContext): }; provider.registerLifecycle(providerLifecycle); - if (preset === 'Podman') { - // podman connection ? - registerPodmanConnection(provider, extensionContext); - } else if (preset === 'OpenShift') { - // OpenShift - registerOpenShiftLocalCluster(provider, extensionContext); + // initial preset check + presetChanged(provider, extensionContext); + + if (crcInstaller.isAbleToInstall()) { + const installationDisposable = provider.registerInstallation({ + preflightChecks: () => { + return crcInstaller.getInstallChecks(); + }, + install: (logger: extensionApi.Logger) => { + return crcInstaller.doInstallCrc(provider, logger, async () => { + await connectToCrc(); + presetChanged(provider, extensionContext); + }); + }, + }); + extensionContext.subscriptions.push(installationDisposable); } } @@ -233,3 +228,35 @@ function readPreset(crcStatus: Status): 'Podman' | 'OpenShift' | 'unknown' { return 'unknown'; } } + +async function connectToCrc(): Promise { + const daemonStarted = await daemonStart(); + if (!daemonStarted) { + //TODO handle this + return; + } + + try { + // initial status + crcStatus = await commander.status(); + } catch (err) { + console.error('error in CRC extension', err); + crcStatus = defaultStatus; + } + + startStatusUpdateTimer(); +} + +function presetChanged(provider: extensionApi.Provider, extensionContext: extensionApi.ExtensionContext): void { + // TODO: handle situation if some cluster/connection was registered already + + // detect preset of CRC + const preset = readPreset(crcStatus); + if (preset === 'Podman') { + // podman connection ? + registerPodmanConnection(provider, extensionContext); + } else if (preset === 'OpenShift') { + // OpenShift + registerOpenShiftLocalCluster(provider, extensionContext); + } +} diff --git a/src/install/base-install.ts b/src/install/base-install.ts new file mode 100644 index 0000000..e1aa553 --- /dev/null +++ b/src/install/base-install.ts @@ -0,0 +1,59 @@ +/********************************************************************** + * Copyright (C) 2022 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ +import type * as extensionApi from '@podman-desktop/api'; + +export abstract class BaseCheck implements extensionApi.InstallCheck { + abstract title: string; + abstract execute(): Promise; + + protected createFailureResult(description?: string, title?: string, url?: string): extensionApi.CheckResult { + const result: extensionApi.CheckResult = { successful: false, description }; + if (title && url) { + result.docLinks = [{ url, title }]; + } + return result; + } + + protected createSuccessfulResult(): extensionApi.CheckResult { + return { successful: true }; + } +} + +export interface Installer { + getPreflightChecks(): extensionApi.InstallCheck[] | undefined; + getUpdatePreflightChecks(): extensionApi.InstallCheck[] | undefined; + install(logger?: extensionApi.Logger): Promise; + requireUpdate(installedVersion: string): boolean; + update(): Promise; +} + +export abstract class BaseInstaller implements Installer { + abstract install(logger?: extensionApi.Logger): Promise; + + abstract update(): Promise; + + abstract getUpdatePreflightChecks(): extensionApi.InstallCheck[]; + + abstract getPreflightChecks(): extensionApi.InstallCheck[]; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + requireUpdate(installedVersion: string): boolean { + // return compare(installedVersion, getBundledPodmanVersion(), '<'); + throw new Error('requireUpdate is not implemented yet'); + } +} diff --git a/src/install/crc-install.ts b/src/install/crc-install.ts new file mode 100644 index 0000000..4f42a4e --- /dev/null +++ b/src/install/crc-install.ts @@ -0,0 +1,87 @@ +/********************************************************************** + * Copyright (C) 2023 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ +import * as extensionApi from '@podman-desktop/api'; +import * as os from 'node:os'; + +import type { Installer } from './base-install'; +import { WinInstall } from './win-install'; + +import * as bundledCrc from '../crc.json'; +import { getCrcVersion } from '../crc-cli'; +import { getCrcDetectionChecks } from '../detection-checks'; + +function getBundledCrcVersion(): string { + return bundledCrc.version.crcVersion; +} + +export class CrcInstall { + private installers = new Map(); + + constructor() { + this.installers.set('win32', new WinInstall()); + } + + isAbleToInstall(): boolean { + return this.installers.has(os.platform()); + } + + getInstallChecks(): extensionApi.InstallCheck[] | undefined { + const installer = this.getInstaller(); + if (installer) { + return installer.getPreflightChecks(); + } + return undefined; + } + + public async doInstallCrc( + provider: extensionApi.Provider, + logger: extensionApi.Logger, + installFinishedFn: () => void, + ): Promise { + const dialogResult = await extensionApi.window.showInformationMessage( + `CRC is not installed on this system, would you like to install CRC ${getBundledCrcVersion()}?`, + 'Yes', + 'No', + ); + if (dialogResult === 'Yes') { + await this.installCrc(logger); + const newInstalledCrc = await getCrcVersion(); + // // write podman version + // if (newInstalledCrc) { + // this.crcInfo.crcVersion = newInstalledCrc.version; + // } + // update detections checks + provider.updateDetectionChecks(getCrcDetectionChecks(newInstalledCrc)); + installFinishedFn(); + } else { + return; + } + } + + private async installCrc(logger: extensionApi.Logger): Promise { + const installer = this.getInstaller(); + if (installer) { + return installer.install(logger); + } + return false; + } + + private getInstaller(): Installer | undefined { + return this.installers.get(os.platform()); + } +} diff --git a/src/install/win-install.ts b/src/install/win-install.ts new file mode 100644 index 0000000..6ec7170 --- /dev/null +++ b/src/install/win-install.ts @@ -0,0 +1,182 @@ +/********************************************************************** + * Copyright (C) 2022 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import * as os from 'node:os'; +import * as path from 'node:path'; +import * as fs from 'node:fs'; +import * as zipper from 'zip-local'; + +import * as extensionApi from '@podman-desktop/api'; +import { BaseCheck, BaseInstaller } from './base-install'; +import { getAssetsFolder, runCliCommand } from '../util'; + +export class WinInstall extends BaseInstaller { + install(logger: extensionApi.Logger): Promise { + return extensionApi.window.withProgress({ location: extensionApi.ProgressLocation.APP_ICON }, async progress => { + progress.report({ increment: 5 }); + const setupPath = path.resolve(getAssetsFolder(), 'crc-windows-installer.zip'); + let msiPath = ''; + try { + if (fs.existsSync(setupPath)) { + logger.log(`Extracting msi file from ${setupPath}`); + msiPath = await this.extractMsiFromZip(setupPath); + progress.report({ increment: 10 }); + + const runResult = await runCliCommand('msiexec.exe', ['/i', msiPath, '/qr', '/norestart']); + + if (runResult.exitCode !== 0) { + // installed successfully, but reboot required + if (runResult.exitCode === 3010) { + progress.report({ increment: 99 }); + extensionApi.window.showInformationMessage( + 'CRC is successfully installed. Reboot required to finalize system changes.', + 'OK', + ); + return true; + } else { + throw new Error(runResult.stdErr); + } + } + progress.report({ increment: 80 }); + extensionApi.window.showNotification({ body: 'CRC is successfully installed.' }); + return true; + } else { + throw new Error(`Can't find CRC setup package! Path: ${setupPath} doesn't exists.`); + } + } catch (err) { + console.error('Error during CRC install!'); + console.error(err); + await extensionApi.window.showErrorMessage('Unexpected error, during CRC installation: ' + err, 'OK'); + return false; + } finally { + progress.report({ increment: -1 }); + if (msiPath) { + fs.unlinkSync(msiPath); + } + } + }); + } + + getPreflightChecks(): extensionApi.InstallCheck[] { + return [new WinBitCheck(), new CpuCoreCheck(), new WinVersionCheck(), new WinMemoryCheck()]; + } + + update(): Promise { + throw new Error('Method not implemented.'); + } + getUpdatePreflightChecks(): extensionApi.InstallCheck[] { + throw new Error('Method not implemented.'); + } + + private extractMsiFromZip(zipPath: string): Promise { + return new Promise((resolve, reject) => { + const outPath = path.join(os.tmpdir(), 'crc'); + if (!fs.existsSync(outPath)) { + fs.mkdirSync(outPath); + } + + zipper.unzip(zipPath, (err, res) => { + if (err) { + reject(err); + } else { + res.save(outPath, saveErr => { + if (saveErr) { + reject(saveErr); + } else { + resolve(path.join(outPath, 'crc-windows-amd64.msi')); + } + }); + } + }); + }); + } +} + +class WinBitCheck extends BaseCheck { + title = 'Windows 64bit'; + + private ARCH_X64 = 'x64'; + private ARCH_ARM = 'arm64'; + + async execute(): Promise { + const currentArch = process.arch; + if (this.ARCH_X64 === currentArch || this.ARCH_ARM === currentArch) { + return this.createSuccessfulResult(); + } else { + return this.createFailureResult( + 'WSL2 works only on 64bit OS.', + 'https://docs.microsoft.com/en-us/windows/wsl/install-manual#step-2---check-requirements-for-running-wsl-2', + ); + } + } +} + +class CpuCoreCheck extends BaseCheck { + title = 'CPU Cores'; + + async execute(): Promise { + const cpus = os.cpus(); + if (cpus.length >= 4) { + return this.createSuccessfulResult(); + } else { + return this.createFailureResult('СRC requires at least 4 CPU Core to run'); + } + } +} + +class WinVersionCheck extends BaseCheck { + title = 'Windows Version'; + + private MIN_BUILD = 18362; + async execute(): Promise { + const winRelease = os.release(); + if (winRelease.startsWith('10.0.')) { + const splitRelease = winRelease.split('.'); + const winBuild = splitRelease[2]; + if (Number.parseInt(winBuild) >= this.MIN_BUILD) { + return { successful: true }; + } else { + return this.createFailureResult( + 'To be able to run WSL2 you need Windows 10 Build 18362 or later.', + 'WSL2 Install Manual', + 'https://docs.microsoft.com/en-us/windows/wsl/install-manual#step-2---check-requirements-for-running-wsl-2', + ); + } + } else { + return this.createFailureResult( + 'WSL2 works only on Windows 10 and newest OS', + 'WSL2 Install Manual', + 'https://docs.microsoft.com/en-us/windows/wsl/install-manual#step-2---check-requirements-for-running-wsl-2', + ); + } + } +} + +class WinMemoryCheck extends BaseCheck { + title = 'RAM'; + private REQUIRED_MEM = 9 * 1024 * 1024 * 1024; // 9Gb + + async execute(): Promise { + const totalMem = os.totalmem(); + if (this.REQUIRED_MEM <= totalMem) { + return this.createSuccessfulResult(); + } else { + return this.createFailureResult('You need at least 9GB to run CRC.'); + } + } +} diff --git a/src/util.ts b/src/util.ts index ef87b14..11de563 100644 --- a/src/util.ts +++ b/src/util.ts @@ -17,6 +17,8 @@ ***********************************************************************/ import * as os from 'node:os'; +import * as path from 'node:path'; +import { spawn } from 'node:child_process'; const windows = os.platform() === 'win32'; export function isWindows(): boolean { @@ -30,3 +32,56 @@ const linux = os.platform() === 'linux'; export function isLinux(): boolean { return linux; } + +/** + * @returns true if app running in dev mode + */ +export function isDev(): boolean { + const isEnvSet = 'ELECTRON_IS_DEV' in process.env; + const envSet = Number.parseInt(process.env.ELECTRON_IS_DEV, 10) === 1; + return isEnvSet ? envSet : false; +} + +export function getAssetsFolder(): string { + return path.resolve( __dirname, '..', 'assets'); +} + +export interface SpawnResult { + exitCode: number; + stdOut: string; + stdErr: string; +} + +export function runCliCommand(command: string, args: string[]): Promise { + return new Promise((resolve, reject) => { + let output = ''; + let err = ''; + const env = Object.assign({}, process.env); + + if (isWindows()) { + // Escape any whitespaces in command + command = `"${command}"`; + } else if (env.FLATPAK_ID) { + // need to execute the command on the host + args = ['--host', command, ...args]; + command = 'flatpak-spawn'; + } + + const spawnProcess = spawn(command, args, { shell: isWindows(), env }); + spawnProcess.on('error', err => { + reject(err); + }); + spawnProcess.stdout.setEncoding('utf8'); + spawnProcess.stdout.on('data', data => { + output += data; + }); + spawnProcess.stderr.setEncoding('utf8'); + spawnProcess.stderr.on('data', data => { + err += data; + }); + + spawnProcess.on('close', exitCode => { + resolve({ exitCode, stdOut: output, stdErr: err }); + }); + }); +} diff --git a/tsconfig.json b/tsconfig.json index 398e3bf..6fc5c90 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,18 +1,27 @@ { - "compilerOptions": { - "lib": [ - "ES2017", - "webworker" + "compilerOptions": { + "lib": [ + "ES2017", + "webworker" + ], + "sourceMap": true, + "rootDir": "src", + "outDir": "dist", + "skipLibCheck": true, + "resolveJsonModule": true, + "types": [ + "node", + ] + }, + "include": [ + "src" ], - "sourceMap": true, - "rootDir": "src", - "outDir": "dist", - "skipLibCheck": true, - "types": [ - "node", - ] -}, -"include": [ - "src" -] -} + "ts-node": { + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node16" + } + } + } + diff --git a/yarn.lock b/yarn.lock index 6ced6fb..71d1e9a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14,11 +14,31 @@ dependencies: "7zip-bin" "5.1.1" -"@jridgewell/sourcemap-codec@^1.4.13": +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@rollup/plugin-commonjs@^24.0.1": version "24.0.1" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.1.tgz#d54ba26a3e3c495dc332bd27a81f7e9e2df46f90" @@ -79,6 +99,26 @@ dependencies: defer-to-connect "^2.0.1" +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + "@types/estree@*", "@types/estree@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" @@ -99,6 +139,21 @@ resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + async@^1.4.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -144,6 +199,11 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -161,6 +221,11 @@ defer-to-connect@^2.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" @@ -231,6 +296,14 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hasha@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" + integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== + dependencies: + is-stream "^2.0.0" + type-fest "^0.8.0" + http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" @@ -283,6 +356,11 @@ is-reference@1.2.1: dependencies: "@types/estree" "*" +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -314,6 +392,11 @@ magic-string@^0.27.0: dependencies: "@jridgewell/sourcemap-codec" "^1.4.13" +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + mimic-response@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" @@ -411,21 +494,55 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +ts-node@^10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + tslib@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== +type-fest@^0.8.0: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + typescript@^4.9.5: version "4.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + zip-local@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/zip-local/-/zip-local-0.3.5.tgz#566c099d0903df1f6bbdd5c060bd62a96a7ad10a"