Skip to content

Commit

Permalink
Restore the TypeScript sources
Browse files Browse the repository at this point in the history
  • Loading branch information
cedx committed Jul 12, 2024
1 parent 21a00a6 commit 07b31a3
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 46 deletions.
2 changes: 1 addition & 1 deletion etc/eslint.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export default ts.config(
"no-implicit-globals": "error",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-invalid-this": "error",
"no-invalid-this": "off",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
Expand Down
8 changes: 6 additions & 2 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ import {readFile, writeFile} from "node:fs/promises";
import {env} from "node:process";
import {deleteAsync} from "del";
import esbuild from "esbuild";
import {$} from "execa";
import {execa} from "execa";
import gulp from "gulp";
import pkg from "./package.json" with {type: "json"};

// Runs a command.
const $ = execa({preferLocal: true, stdio: "inherit"});

// Builds the project.
export async function build() {
await $`tsc --project src`;
return esbuild.build({
banner: {js: "#!/usr/bin/env node"},
bundle: true,
entryPoints: ["src/cli.js"],
entryPoints: ["src/cli.ts"],
legalComments: "none",
minify: true,
outfile: "bin/setup_ant.cjs",
Expand Down
6 changes: 3 additions & 3 deletions src/cli.js → src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {Setup} from "./setup.js";

/**
* Application entry point.
* @returns {Promise<void>} Resolves when Apache Ant has been installed.
* @returns Resolves when Apache Ant has been installed.
*/
async function main() {
async function main(): Promise<void> {
const version = getInput("version");
const release = Release.find(!version || version == "latest" ? "*" : version);
if (!release) throw Error("No release matching the version constraint.");
Expand All @@ -18,4 +18,4 @@ async function main() {
}

// Start the application.
main().catch(error => setFailed(error instanceof Error ? error : String(error)));
main().catch((error: unknown) => setFailed(error instanceof Error ? error : String(error)));
File renamed without changes.
File renamed without changes.
37 changes: 14 additions & 23 deletions src/release.js → src/release.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,72 +8,63 @@ export class Release {

/**
* The base URL of the releases.
* @type {URL}
* @readonly
*/
static #baseUrl = new URL("https://dlcdn.apache.org/ant/binaries/");
static readonly #baseUrl = new URL("https://dlcdn.apache.org/ant/binaries/");

/**
* The list of all releases.
* @type {Release[]}
* @readonly
*/
static #data = data.map(release => new this(release.version));
static readonly #data: Release[] = data.map(release => new this(release.version));

/**
* The version number.
* @type {string}
* @readonly
*/
version;
readonly version: string;

/**
* Creates a new release.
* @param {string} version The version number.
* @param version The version number.
*/
constructor(version) {
constructor(version: string) {
this.version = version;
}

/**
* The latest release.
* @type {Release}
*/
static get latest() {
static get latest(): Release {
return this.#data[0];
}

/**
* Value indicating whether this release exists.
* @type {boolean}
*/
get exists() {
get exists(): boolean {
return Release.#data.some(release => release.version == this.version);
}

/**
* The download URL.
* @type {URL}
*/
get url() {
get url(): URL {
return new URL(`apache-ant-${this.version}-bin.zip`, Release.#baseUrl);
}

/**
* Finds a release that matches the specified version constraint.
* @param {string} constraint The version constraint.
* @returns {Release|null} The release corresponding to the specified constraint.
* @param constraint The version constraint.
* @returns The release corresponding to the specified constraint.
*/
static find(constraint) {
static find(constraint: string): Release|null {
return this.#data.find(release => semver.satisfies(release.version, constraint)) ?? null;
}

/**
* Gets the release corresponding to the specified version.
* @param {string} version The version number of a release.
* @returns {Release|null} The release corresponding to the specified version.
* @param version The version number of a release.
* @returns The release corresponding to the specified version.
*/
static get(version) {
static get(version: string): Release|null {
return this.#data.find(release => release.version == version) ?? null;
}
}
33 changes: 16 additions & 17 deletions src/setup.js → src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {join} from "node:path";
import {promisify} from "node:util";
import {addPath, exportVariable} from "@actions/core";
import {cacheDir, downloadTool, extractZip, find} from "@actions/tool-cache";
import type {Release} from "./release.js";

/**
* Manages the download and installation of Apache Ant.
Expand All @@ -12,25 +13,23 @@ export class Setup {

/**
* The release to download and install.
* @type {import("./release.js").Release}
* @readonly
*/
release;
readonly release: Release;

/**
* Creates a new setup.
* @param {import("./release.js").Release} release The release to download and install.
* @param release The release to download and install.
*/
constructor(release) {
constructor(release: Release) {
this.release = release;
}

/**
* Downloads and extracts the ZIP archive of Apache Ant.
* @param {Partial<{optionalTasks: boolean}>} options Value indicating whether to fetch the Ant optional tasks.
* @returns {Promise<string>} The path to the extracted directory.
* @param options Value indicating whether to fetch the Ant optional tasks.
* @returns The path to the extracted directory.
*/
async download(options = {}) {
async download(options: Partial<{optionalTasks: boolean}> = {}): Promise<string> {
const path = await extractZip(await downloadTool(this.release.url.href));
const directory = join(path, await this.#findSubfolder(path));
if (options.optionalTasks) await this.#fetchOptionalTasks(directory);
Expand All @@ -39,10 +38,10 @@ export class Setup {

/**
* Installs Apache Ant, after downloading it if required.
* @param {Partial<{optionalTasks: boolean}>} options Value indicating whether to fetch the Ant optional tasks.
* @returns Promise<string> The path to the installation directory.
* @param options Value indicating whether to fetch the Ant optional tasks.
* @returns The path to the installation directory.
*/
async install(options = {}) {
async install(options: Partial<{optionalTasks: boolean}> = {}): Promise<string> {
let directory = find("ant", this.release.version);
if (!directory) {
const path = await this.download(options);
Expand All @@ -56,19 +55,19 @@ export class Setup {

/**
* Fetches the external libraries required by Ant optional tasks.
* @param {string} antHome The path to the Ant directory.
* @returns {Promise<unknown>} Resolves when the optional tasks have been fetched.
* @param antHome The path to the Ant directory.
* @returns Resolves when the optional tasks have been fetched.
*/
#fetchOptionalTasks(antHome) {
#fetchOptionalTasks(antHome: string): Promise<unknown> {
return promisify(exec)("ant -buildfile fetch.xml -noinput -silent -Ddest=system", {cwd: antHome, env: {ANT_HOME: antHome}});
}

/**
* Determines the name of the single subfolder in the specified directory.
* @param {string} directory The directory path.
* @returns {Promise<string>} The name of the single subfolder in the specified directory.
* @param directory The directory path.
* @returns The name of the single subfolder in the specified directory.
*/
async #findSubfolder(directory) {
async #findSubfolder(directory: string): Promise<string> {
const folders = (await readdir(directory, {withFileTypes: true})).filter(entity => entity.isDirectory());
switch (folders.length) {
case 0: throw Error(`No subfolder found in: ${directory}.`);
Expand Down

0 comments on commit 07b31a3

Please sign in to comment.