Skip to content

Commit

Permalink
successfully compiles but vscode still does not support ESM extension…
Browse files Browse the repository at this point in the history
  • Loading branch information
ArquintL committed Nov 7, 2024
1 parent fb0e1b7 commit fc9a5ec
Show file tree
Hide file tree
Showing 24 changed files with 1,457 additions and 1,029 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ module.exports = {
"eol-last": "off",
"eqeqeq": [
"error",
"always"
"smart"
],
"guard-for-in": "error",
"id-denylist": "error",
Expand Down
2,232 changes: 1,322 additions & 910 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"name": "vs-verification-toolbox",
"version": "1.0.0",
"description": "Useful component to build VS Code extensions for verifiers.",
"main": "out/index.js",
"type": "module",
"exports": "./out/index.js",
"activationEvents": [
"this property is required to run vs code tests"
],
Expand All @@ -25,15 +26,17 @@
"npm",
"node"
],
"author": "Julian Dunskus",
"author": {
"name": "Chair of Programming Methodology, ETH Zurich"
},
"license": "MPL-2.0",
"bugs": {
"url": "https://github.com/viperproject/vs-verification-toolbox/issues"
},
"homepage": "https://github.com/viperproject/vs-verification-toolbox#readme",
"engines": {
"vscode": "^1.43.0",
"node": "*"
"node": ">=18"
},
"devDependencies": {
"@types/fs-extra": "^11.0.4",
Expand Down Expand Up @@ -61,6 +64,6 @@
"@octokit/rest": "^20.0.2",
"extract-zip": "^2.0.0",
"fs-extra": "^11.2.0",
"got": "^11.8.6"
"got": "^14.4.4"
}
}
4 changes: 2 additions & 2 deletions src/dependencies/Dependency.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as path from 'path';

import { ConfirmResult, InstallResult, Success } from './';
import { Location, ProgressListener } from '../util';
import { ConfirmResult, InstallResult, Success } from './index.js';
import { Location, ProgressListener } from '../util/index.js';

/**
* Manages the installation for a dependency, maintaining separate installations for each source (in a folder using their name).
Expand Down
6 changes: 3 additions & 3 deletions src/dependencies/FileDownloader.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import * as path from 'node:path';
import got, { Headers, Options, Progress } from 'got';
import * as stream from 'stream';
import { promisify } from 'util';

import { Canceled, ConfirmResult, DependencyInstaller, InstallResult, Success } from './';
import { Location, ProgressListener } from '../util';
import { Canceled, ConfirmResult, DependencyInstaller, InstallResult, Success } from './index.js';
import { Location, ProgressListener } from '../util/index.js';


const pipeline = promisify(stream.pipeline);
Expand Down
10 changes: 5 additions & 5 deletions src/dependencies/GitHubReleaseAsset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ export class GitHubReleaseAsset {
// get the first release which corresponds to the latest pre- or non-pre-release.
// note that draft releases do not show up for unauthenticated users
// see https://octokit.github.io/rest.js/v18#repos-list-releases
let listReleasesParams: RestEndpointMethodTypes["repos"]["listReleases"]["parameters"] = {
owner: owner,
repo: repo,
}
const listReleasesParams: RestEndpointMethodTypes["repos"]["listReleases"]["parameters"] = {
owner,
repo,
};
if (token == null) {
listReleasesParams.per_page = 1;
listReleasesParams.page = 1;
Expand Down Expand Up @@ -88,7 +88,7 @@ export class GitHubReleaseAsset {
* @param token personal access token, OAuth token, installation access token, or JSON Web Token for GitHub App authentication
*/
private static buildOctokit(token?: string): Octokit {
if (token) {
if (token != null) {
return new Octokit({
auth: token,
});
Expand Down
12 changes: 5 additions & 7 deletions src/dependencies/GitHubZipExtractor.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import * as path from 'path';

import { ConfirmResult, DependencyInstaller, FileDownloader, InstallerSequence, InstallResult, Success, ZipExtractor } from './';
import { Location, ProgressListener } from '../util';
import { ConfirmResult, DependencyInstaller, FileDownloader, InstallerSequence, InstallResult, Success, ZipExtractor } from './index.js';
import { Location, ProgressListener } from '../util/index.js';

/**
* Extension of RemoteZipExtractor with the following features:
* - no remote URL needed at construction time: a (potentially expensive) computation of the remote URL is only
* performed when a download will actually take place.
* performed when a download will actually take place.
* - the correct header for downloading a GitHub release asset is set
* - if a GitHub token is provided it is used to perform the download as an authenticated user
*/
Expand All @@ -32,8 +30,8 @@ export class GitHubZipExtractor implements DependencyInstaller {
const downloadHeaders: Record<string, string | string[] | undefined> = {
"Accept": "application/octet-stream"
};
if (this.token) {
downloadHeaders["Authorization"] = `token ${this.token}`;
if (this.token != null) {
downloadHeaders.Authorization = `token ${this.token}`;
}

// lazily initialize sequence:
Expand Down
5 changes: 3 additions & 2 deletions src/dependencies/InstallResult.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-underscore-dangle */
export interface InstallResult<T> {
isSuccess(): boolean;
}
Expand All @@ -7,8 +8,8 @@ export class Success<T> implements InstallResult<T> {
private readonly _value: T;

/**
* @param t non-null
*/
* @param t non-null
*/
constructor(t: T) {
if (t == null) {
throw new Error(`Invalid argument: Success(v) can only be constructed with a non-null value`);
Expand Down
14 changes: 7 additions & 7 deletions src/dependencies/InstallerSequence.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ConfirmResult, DependencyInstaller, InstallResult, Success } from './';
import { Location, ProgressListener } from '../util';
import { ConfirmResult, DependencyInstaller, InstallResult, Success } from './index.js';
import { Location, ProgressListener } from '../util/index.js';

export class InstallerSequence {
constructor(readonly installers: DependencyInstaller[]) {
Expand All @@ -16,17 +16,17 @@ export class InstallerSequence {

public async install(location: Location, shouldUpdate: boolean, progressListener: ProgressListener, confirm:() => Promise<ConfirmResult>): Promise<InstallResult<Location>> {
let index = 0;
let firstConfirmPromise: Promise<ConfirmResult> | undefined = undefined;
let firstConfirmPromise: Promise<ConfirmResult> | undefined;
let result: InstallResult<Location> = new Success(location);
const total = this.installers.length;
for (const installer of this.installers) {
function intermediateListener(fraction: number, message: string) {
const intermediateListener = (fraction: number, message: string) => {
progressListener(
(index + fraction) / total,
`${message} (step ${index + 1} of ${total})`
);
}
function intermediateConfirm(): Promise<ConfirmResult> {
};
const intermediateConfirm = () => {
// only ask once
if (firstConfirmPromise == null) {
firstConfirmPromise = confirm();
Expand All @@ -35,7 +35,7 @@ export class InstallerSequence {
// return same promise:
return firstConfirmPromise;
}
}
};

if (result instanceof Success) {
// continue with next installer
Expand Down
4 changes: 2 additions & 2 deletions src/dependencies/LocalReference.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as fs from 'fs-extra';

import { ConfirmResult, DependencyInstaller, InstallResult, Success } from './';
import { Location, ProgressListener } from '../util';
import { ConfirmResult, DependencyInstaller, InstallResult, Success } from './index.js';
import { Location, ProgressListener } from '../util/index.js';

export class LocalReference implements DependencyInstaller {
constructor(
Expand Down
6 changes: 3 additions & 3 deletions src/dependencies/RemoteZipExtractor.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as path from 'path';
import * as path from 'node:path';

import { ConfirmResult, DependencyInstaller, FileDownloader, InstallerSequence, InstallResult, Success, ZipExtractor } from './';
import { Location, ProgressListener } from '../util';
import { ConfirmResult, DependencyInstaller, FileDownloader, InstallerSequence, InstallResult, Success, ZipExtractor } from './index.js';
import { Location, ProgressListener } from '../util/index.js';

export class RemoteZipExtractor implements DependencyInstaller {
private readonly sequence: InstallerSequence;
Expand Down
8 changes: 4 additions & 4 deletions src/dependencies/ZipExtractor.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as extractZip from 'extract-zip';
import * as extract from 'extract-zip';
import * as fs from 'fs-extra';

import { Canceled, ConfirmResult, DependencyInstaller, InstallResult, Success } from './';
import { Location, ProgressListener } from '../util';
import { Canceled, ConfirmResult, DependencyInstaller, InstallResult, Success } from './index.js';
import { Location, ProgressListener } from '../util/index.js';

/** Extracts the zip at the location provided to `install` to a folder named `targetName`. */
export class ZipExtractor implements DependencyInstaller {
Expand All @@ -29,7 +29,7 @@ export class ZipExtractor implements DependencyInstaller {

let extractedBytes = 0;
let prevEntrySize = 0;
await extractZip(location.basePath, {
await extract.default(location.basePath, {
dir: target.basePath,
onEntry: (entry, zip) => {
extractedBytes += prevEntrySize;
Expand Down
18 changes: 9 additions & 9 deletions src/dependencies/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export * from './Dependency';
export * from './FileDownloader';
export * from './GitHubReleaseAsset';
export * from './GitHubZipExtractor';
export * from './ZipExtractor';
export * from './InstallerSequence';
export * from './InstallResult';
export * from './LocalReference';
export * from './RemoteZipExtractor';
export * from './Dependency.js';
export * from './FileDownloader.js';
export * from './GitHubReleaseAsset.js';
export * from './GitHubZipExtractor.js';
export * from './ZipExtractor.js';
export * from './InstallerSequence.js';
export * from './InstallResult.js';
export * from './LocalReference.js';
export * from './RemoteZipExtractor.js';
6 changes: 3 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// exports all modules of this package

export * from './dependencies';
export * from './util';
export * from './vscode-util';
export * from './dependencies/index.js';
export * from './util/index.js';
export * from './vscode-util/index.js';
51 changes: 25 additions & 26 deletions src/test/dependencies.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import * as path from 'path';
import * as fs from 'fs';
import * as assert from 'assert';
/* eslint-disable import/no-extraneous-dependencies */
import * as path from 'node:path';
import { fileURLToPath } from 'node:url';
import * as fs from 'node:fs';
import * as assert from 'node:assert';
import * as md5File from 'md5-file';

import { Canceled, ConfirmResult, Dependency, FileDownloader, GitHubReleaseAsset, GitHubZipExtractor, InstallerSequence, LocalReference, Success, ZipExtractor } from '..';
import { withProgressInWindow } from '../vscode-util';
import { Canceled, ConfirmResult, Dependency, FileDownloader, GitHubReleaseAsset, GitHubZipExtractor, InstallerSequence, LocalReference, Success, ZipExtractor } from '../index.js';
import { withProgressInWindow } from '../vscode-util/index.js';

suite("dependencies", () => {

const PROJECT_ROOT = path.join(__dirname, "../../");
const FILE_NAME = fileURLToPath(import.meta.url); // get the resolved path to the file
const DIRNAME = path.dirname(FILE_NAME); // get the name of the directory
const PROJECT_ROOT = path.join(DIRNAME, "../../");
const TMP_PATH: string = path.join(PROJECT_ROOT, "src", "test", "tmp");
const HTTP_DOWNLOAD_URL: string = "http://viper.ethz.ch/examples/";
const HTTP_DOWNLOAD_TIMEOUT_MS: number = 10 * 1000; // 10s
Expand All @@ -20,7 +24,7 @@ suite("dependencies", () => {
const ASSET_OWNER: string = "viperproject";
const ASSET_REPO: string = "vs-verification-toolbox-release-testing";

suiteSetup(function() {
suiteSetup(() => {
// create a tmp directory for downloading files to it
if (!fs.existsSync(TMP_PATH)) {
fs.mkdirSync(TMP_PATH);
Expand Down Expand Up @@ -138,10 +142,9 @@ suite("dependencies", () => {
// latest non-pre-release is v1
const md5HashOfExtractedFile = "3cf1da395ac560a38415620e43b0f759"; // md5 of small.bin

function getUrl(): Promise<string> {
return GitHubReleaseAsset.getLatestAssetUrl(
const getUrl = () =>
GitHubReleaseAsset.getLatestAssetUrl(
ASSET_OWNER, ASSET_REPO, assetName, false, getToken());
}

const myDependency = new Dependency<"remote">(
TMP_PATH,
Expand All @@ -154,24 +157,22 @@ suite("dependencies", () => {
listener => myDependency.install("remote", true, listener));
// check md5 of this file
if (unzippedDestination instanceof Success) {
const actual: string = await md5File(unzippedDestination.value.child(unzippedFilename).basePath);
const actual: string = await md5File.default(unzippedDestination.value.child(unzippedFilename).basePath);
assert.strictEqual(actual, md5HashOfExtractedFile, `md5 hash does not match for file named '${unzippedFilename}`);
} else {
assert.fail(`expected installation success but got ${unzippedDestination}`)
assert.fail(`expected installation success but got ${unzippedDestination}`);
}
});

function getToken(): string | undefined {
return process.env["GITHUB_TOKEN"];
}
const getToken: () => string | undefined = () => process.env.GITHUB_TOKEN;

async function downloadAndCheckGitHubAsset(url: string, assetName: string, md5Hash: string): Promise<void> {
const downloadAndCheckGitHubAsset: (url: string, assetName: string, md5Hash: string) => Promise<void> = async (url, assetName, md5Hash) => {
const headers: Record<string, string | string[] | undefined> = {
"Accept": "application/octet-stream"
};
const token = getToken();
if (token) {
headers["Authorization"] = `token ${token}`;
if (token != null) {
headers.Authorization = `token ${token}`;
}
const myDependency = new Dependency<"remote">(
TMP_PATH,
Expand All @@ -182,33 +183,31 @@ suite("dependencies", () => {
]
);
let confirmCallbackCalls: number = 0;
async function confirm(): Promise<ConfirmResult> {
const confirm: () => Promise<ConfirmResult> = async () => {
confirmCallbackCalls++;
return ConfirmResult.Continue;
}
};
const { result: downloadDestination } = await withProgressInWindow(
`Downloading GitHub asset ${assetName}`,
listener => myDependency.install("remote", true, listener, confirm));
assert.strictEqual(confirmCallbackCalls, 1, `callback to confirm download should only be called once`);
if (downloadDestination instanceof Success) {
// check md5 of this file
const actual: string = await md5File(downloadDestination.value.basePath);
const actual: string = await md5File.default(downloadDestination.value.basePath);
assert.strictEqual(actual, md5Hash, `md5 hash does not match for asset named '${assetName} (downloaded from ${url})`);
} else {
assert.fail(`expected success but got ${downloadDestination}`);
}

// test that installation is aborted if confirmation is canceled:
async function cancelConfirmation(): Promise<ConfirmResult> {
return ConfirmResult.Cancel;
}
const cancelConfirmation: () => Promise<ConfirmResult> = async () => ConfirmResult.Cancel;
const canceledResult = await myDependency.install("remote", true, undefined, cancelConfirmation);
if (!(canceledResult instanceof Canceled)) {
assert.fail(`expected cancellation of installation due to cancel confirmation but got ${canceledResult}`);
}
}
};

suiteTeardown(function() {
suiteTeardown(() => {
// delete tmp directory containing downloaded files:
if (fs.existsSync(TMP_PATH)) {
fs.rmdirSync(TMP_PATH, { recursive: true });
Expand Down
14 changes: 9 additions & 5 deletions src/test/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
/* eslint-disable import/no-extraneous-dependencies */
import { glob } from 'glob';
import * as path from 'path';
import * as path from 'node:path';
import { fileURLToPath } from 'node:url';
import * as Mocha from 'mocha';

// kept as-is (except for the mocha config) from `yo code` extension template
export async function run(): Promise<void> {
export const run: () => Promise<void> = async () => {
// Create the mocha test
const mocha = new Mocha({
const mocha = new Mocha.default({
ui: 'tdd',
timeout: 2000, // ms
color: true,
});

const testsRoot = path.resolve(__dirname, '..');
const filename = fileURLToPath(import.meta.url); // get the resolved path to the file
const dirname = path.dirname(filename); // get the name of the directory
const testsRoot = path.resolve(dirname, '..');

const files = await glob('**/**.test.js', { cwd: testsRoot });

Expand All @@ -32,4 +36,4 @@ export async function run(): Promise<void> {
e(err);
}
});
}
};
Loading

0 comments on commit fc9a5ec

Please sign in to comment.