diff --git a/package.json b/package.json index ebab08c..549b0fb 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ }, "devDependencies": { "@types/async": "^3.2.7", + "@types/atom": "^1.40.11", "@types/express": "^4.17.13", "@types/first-mate": "^7.0.6", "@types/fs-plus": "3.0.2", diff --git a/src/apm-cli.ts b/src/apm-cli.ts index 9069d3b..3a9f201 100644 --- a/src/apm-cli.ts +++ b/src/apm-cli.ts @@ -114,8 +114,10 @@ const commands = { show: viewClass, } -function parseOptions(args = []) { - const options = yargs(args).wrap(Math.min(100, yargs.terminalWidth())) +export type CliOptions = yargs.Argv<{}> & { commandArgs: string[] } // TODO pass commandArgs directly + +function parseOptions(args: string[] = []): CliOptions { + const options = yargs(args).wrap(Math.min(100, yargs.terminalWidth())) as CliOptions options.usage(`\ apm - Atom Package Manager powered by https://atom.io @@ -141,7 +143,7 @@ Run \`apm help \` to see the more details about a specific command.\ return options } -function showHelp(options) { +function showHelp(options: CliOptions) { if (options == null) { return } @@ -266,7 +268,9 @@ function getPythonVersion(callback) { }) } -export function run(args, callback) { +export type RunCallback = (error?: string | Error | null) => any + +export function run(args, callback: RunCallback) { let Command config.setupApmRcFile() const options = parseOptions(args) @@ -276,7 +280,7 @@ export function run(args, callback) { } let callbackCalled = false - const handleErrorCallback = (error) => { + const handleErrorCallback = (error?: string | Error) => { if (callbackCalled) { return } diff --git a/src/apm.ts b/src/apm.ts index 1cf6570..e6c2e52 100644 --- a/src/apm.ts +++ b/src/apm.ts @@ -184,7 +184,7 @@ export function visualStudioIsInstalled(version) { } } -export function loadNpm(callback) { +export function loadNpm(callback: (config: null, npmVar: typeof npm) => void) { const npmOptions = { userconfig: getUserConfigPath(), globalconfig: getGlobalConfigPath(), diff --git a/src/ci.ts b/src/ci.ts index 8d0d80b..fd8f4dc 100644 --- a/src/ci.ts +++ b/src/ci.ts @@ -9,17 +9,19 @@ import fs from "./fs" import yargs from "yargs" import async from "async" import * as config from "./apm" -import Command from "./command" +import Command, { LogCommandResultsArgs } from "./command" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Ci extends Command { + private atomDirectory = config.getAtomDirectory() + private atomNpmPath = require.resolve("npm/bin/npm-cli") + private atomNodeDirectory: string constructor() { super() - this.atomDirectory = config.getAtomDirectory() this.atomNodeDirectory = path.join(this.atomDirectory, ".node-gyp") - this.atomNpmPath = require.resolve("npm/bin/npm-cli") } - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ Usage: apm ci @@ -63,12 +65,12 @@ but cannot be used to install new packages or dependencies.\ const installOptions = { env, streaming: options.argv.verbose } - return this.fork(this.atomNpmPath, installArgs, installOptions, (...args) => { - return this.logCommandResults(callback, ...Array.from(args)) + return this.fork(this.atomNpmPath, installArgs, installOptions, (...args: LogCommandResultsArgs) => { + return this.logCommandResults(callback, ...args) }) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { const opts = this.parseOptions(options.commandArgs) const commands = [] diff --git a/src/clean.ts b/src/clean.ts index 42dd84f..fd3209d 100644 --- a/src/clean.ts +++ b/src/clean.ts @@ -5,15 +5,13 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ import yargs from "yargs" -import Command from "./command" +import Command, { LogCommandResultsArgs } from "./command" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Clean extends Command { - constructor() { - super() - this.atomNpmPath = require.resolve("npm/bin/npm-cli") - } + private atomNpmPath = require.resolve("npm/bin/npm-cli") - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -25,10 +23,10 @@ as a dependency in the package.json file.\ return options.alias("h", "help").describe("help", "Print this usage message") } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { process.stdout.write("Removing extraneous modules ") - return this.fork(this.atomNpmPath, ["prune"], (...args) => { - return this.logCommandResults(callback, ...Array.from(args)) + return this.fork(this.atomNpmPath, ["prune"], (...args: LogCommandResultsArgs) => { + return this.logCommandResults(callback, ...args) }) } } diff --git a/src/command.ts b/src/command.ts index eeb82b6..2000a02 100644 --- a/src/command.ts +++ b/src/command.ts @@ -13,7 +13,13 @@ import semver from "semver" import * as config from "./apm" import * as git from "./git" +export type LogCommandResultsArgs = [code: number, stderr?: string, stdout?: string] + export default class Command { + protected electronVersion: string + installedAtomVersion: string + protected resourcePath: string + npm: typeof import("npm") constructor() { this.logCommandResults = this.logCommandResults.bind(this) this.logCommandResultsIfFail = this.logCommandResultsIfFail.bind(this) @@ -89,7 +95,7 @@ export default class Command { } } - logCommandResults(callback, code, stderr = "", stdout = "") { + logCommandResults(callback: (error?: string) => void, code: number, stderr = "", stdout = "") { if (code === 0) { this.logSuccess() return callback() @@ -99,7 +105,7 @@ export default class Command { } } - logCommandResultsIfFail(callback, code, stderr = "", stdout = "") { + logCommandResultsIfFail(callback: (error?: string) => void, code: number, stderr = "", stdout = "") { if (code === 0) { return callback() } else { @@ -108,7 +114,7 @@ export default class Command { } } - normalizeVersion(version) { + normalizeVersion(version: string) { if (typeof version === "string") { // Remove commit SHA suffix return version.replace(/-.*$/, "") @@ -119,11 +125,15 @@ export default class Command { loadInstalledAtomMetadata(callback) { return this.getResourcePath((resourcePath) => { - let electronVersion + let electronVersion: string | undefined try { - let left, version - ;({ version, electronVersion } = (left = require(path.join(resourcePath, "package.json"))) != null ? left : {}) - version = this.normalizeVersion(version) + const resourcePathJson: { version: string; electronVersion: string } & Record = + require(path.join(resourcePath, "package.json")) ?? {} + + electronVersion = resourcePath.electronVersion + + const version = this.normalizeVersion(resourcePathJson.version) + if (semver.valid(version)) { this.installedAtomVersion = version } diff --git a/src/config.ts b/src/config.ts index 3308bf1..7a80154 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,16 +7,18 @@ import path from "path" import yargs from "yargs" import * as apm from "./apm" import Command from "./command" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Config extends Command { + private atomDirectory = apm.getAtomDirectory() + private atomNpmPath = require.resolve("npm/bin/npm-cli") + private atomNodeDirectory: string constructor() { super() - const atomDirectory = apm.getAtomDirectory() - this.atomNodeDirectory = path.join(atomDirectory, ".node-gyp") - this.atomNpmPath = require.resolve("npm/bin/npm-cli") + this.atomNodeDirectory = path.join(this.atomDirectory, ".node-gyp") } - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -30,7 +32,7 @@ Usage: apm config set return options.alias("h", "help").describe("help", "Print this usage message") } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) let configArgs = ["--globalconfig", apm.getGlobalConfigPath(), "--userconfig", apm.getUserConfigPath(), "config"] diff --git a/src/dedupe.ts b/src/dedupe.ts index 2f3ea23..b49df5e 100644 --- a/src/dedupe.ts +++ b/src/dedupe.ts @@ -8,19 +8,22 @@ import path from "path" import async from "async" import yargs from "yargs" import * as config from "./apm" -import Command from "./command" +import Command, { LogCommandResultsArgs } from "./command" import fs from "./fs" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Dedupe extends Command { + private atomDirectory = config.getAtomDirectory() + private atomNpmPath = require.resolve("npm/bin/npm-cli") + atomPackagesDirectory: string + private atomNodeDirectory: string constructor() { super() - this.atomDirectory = config.getAtomDirectory() this.atomPackagesDirectory = path.join(this.atomDirectory, "packages") this.atomNodeDirectory = path.join(this.atomDirectory, ".node-gyp") - this.atomNpmPath = require.resolve("npm/bin/npm-cli") } - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -36,8 +39,8 @@ This command is experimental.\ dedupeModules(options, callback) { process.stdout.write("Deduping modules ") - return this.forkDedupeCommand(options, (...args) => { - return this.logCommandResults(callback, ...Array.from(args)) + return this.forkDedupeCommand(options, (...args: LogCommandResultsArgs) => { + return this.logCommandResults(callback, ...args) }) } @@ -79,7 +82,7 @@ This command is experimental.\ return fs.makeTreeSync(this.atomNodeDirectory) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { const { cwd } = options options = this.parseOptions(options.commandArgs) options.cwd = cwd diff --git a/src/deprecated-packages.ts b/src/deprecated-packages.ts index f9aa20a..344b321 100644 --- a/src/deprecated-packages.ts +++ b/src/deprecated-packages.ts @@ -1,19 +1,22 @@ -/* - * decaffeinate suggestions: - * DS102: Remove unnecessary code created because of implicit returns - * DS104: Avoid inline assignments - * DS207: Consider shorter variations of null checks - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md - */ import semver from "semver" -let deprecatedPackages = null +let deprecatedPackages: DeprecatedPackages | undefined -export function isDeprecatedPackage(name, version) { - if (deprecatedPackages == null) { - let left - deprecatedPackages = (left = require("../deprecated-packages")) != null ? left : {} +type DeprecatedPackage = { + version?: string + hasDeprecations?: boolean + latestHasDeprecations?: boolean + message?: string + hasAlternative?: boolean + alternative?: string +} + +type DeprecatedPackages = Record + +export function isDeprecatedPackage(name: string, version: string) { + if (deprecatedPackages === undefined) { + deprecatedPackages = require("../deprecated-packages") as DeprecatedPackages } - if (!deprecatedPackages.hasOwnProperty(name)) { + if (!(name in deprecatedPackages)) { return false } diff --git a/src/develop.ts b/src/develop.ts index e5650ec..cd75fc4 100644 --- a/src/develop.ts +++ b/src/develop.ts @@ -11,20 +11,23 @@ import path from "path" import async from "async" import yargs from "yargs" import * as config from "./apm" -import Command from "./command" +import Command, { LogCommandResultsArgs } from "./command" import Install from "./install" import * as git from "./git" import Link from "./link" import * as request from "./request" +import { PackageMetadata, unkownPackage } from "./packages" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Develop extends Command { + private atomDirectory = config.getAtomDirectory() + atomDevPackagesDirectory: string constructor() { super() - this.atomDirectory = config.getAtomDirectory() this.atomDevPackagesDirectory = path.join(this.atomDirectory, "dev", "packages") } - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -44,17 +47,17 @@ cmd-shift-o to run the package out of the newly cloned repository.\ return options.alias("h", "help").describe("help", "Print this usage message") } - getRepositoryUrl(packageName, callback) { + getRepositoryUrl(packageName: string, callback) { const requestSettings = { url: `${config.getAtomPackagesUrl()}/${packageName}`, json: true, } - return request.get(requestSettings, function (error, response, body = {}) { + return request.get(requestSettings, function (error, response, body: PackageMetadata = unkownPackage) { if (error != null) { return callback(`Request for package information failed: ${error.message}`) } else if (response.statusCode === 200) { - let repositoryUrl - if ((repositoryUrl = body.repository.url)) { + const repositoryUrl = body.repository?.url + if (repositoryUrl) { return callback(null, repositoryUrl) } else { return callback(`No repository URL found for package: ${packageName}`) @@ -66,7 +69,7 @@ cmd-shift-o to run the package out of the newly cloned repository.\ }) } - cloneRepository(repoUrl, packageDirectory, options, callback = function () {}) { + cloneRepository(repoUrl: string, packageDirectory: string, options, callback = function () {}) { return config.getSetting("git", (command) => { if (command == null) { command = "git" @@ -76,30 +79,30 @@ cmd-shift-o to run the package out of the newly cloned repository.\ process.stdout.write(`Cloning ${repoUrl} `) } git.addGitToEnv(process.env) - return this.spawn(command, args, (...args) => { + return this.spawn(command, args, (...logargs: LogCommandResultsArgs) => { if (options.argv.json) { - return this.logCommandResultsIfFail(callback, ...Array.from(args)) + return this.logCommandResultsIfFail(callback, ...logargs) } else { - return this.logCommandResults(callback, ...Array.from(args)) + return this.logCommandResults(callback, ...logargs) } }) }) } - installDependencies(packageDirectory, options, callback = function () {}) { + installDependencies(packageDirectory: string, options, callback = function () {}) { process.chdir(packageDirectory) const installOptions = { ...options } return new Install().run(installOptions, callback) } - linkPackage(packageDirectory, options, callback = function () {}) { + linkPackage(packageDirectory: string, options, callback = function () {}) { const linkOptions = { ...options } linkOptions.commandArgs = [packageDirectory, "--dev"] return new Link().run(linkOptions, callback) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { let left const packageName = options.commandArgs.shift() diff --git a/src/disable.ts b/src/disable.ts index 447c909..4afffd8 100644 --- a/src/disable.ts +++ b/src/disable.ts @@ -12,9 +12,10 @@ import yargs from "yargs" import * as config from "./apm" import Command from "./command" import List from "./list" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Disable extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -43,7 +44,7 @@ Disables the named package(s).\ ) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { let settings options = this.parseOptions(options.commandArgs) diff --git a/src/docs.ts b/src/docs.ts index fe32e10..80806ea 100644 --- a/src/docs.ts +++ b/src/docs.ts @@ -8,9 +8,10 @@ import yargs from "yargs" import open from "open" import View from "./view" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Docs extends View { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -26,7 +27,7 @@ Open a package's homepage in the default browser.\ return open(repositoryUrl) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) const [packageName] = Array.from(options.argv._) diff --git a/src/enable.ts b/src/enable.ts index 81530d1..8acbb7c 100644 --- a/src/enable.ts +++ b/src/enable.ts @@ -11,9 +11,10 @@ import CSON from "season" import yargs from "yargs" import * as config from "./apm" import Command from "./command" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Enable extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -24,7 +25,7 @@ Enables the named package(s).\ return options.alias("h", "help").describe("help", "Print this usage message") } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { let error, left, settings options = this.parseOptions(options.commandArgs) let packageNames = this.packageNamesFromArgv(options.argv) diff --git a/src/featured.ts b/src/featured.ts index 281d7a1..637cacc 100644 --- a/src/featured.ts +++ b/src/featured.ts @@ -11,9 +11,10 @@ import Command from "./command" import * as config from "./apm" import * as request from "./request" import { tree } from "./tree" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Featured extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -81,7 +82,7 @@ atom.io registry.\ }) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) const listCallback = function (error, packages) { diff --git a/src/fs.ts b/src/fs.ts index b481705..477e231 100644 --- a/src/fs.ts +++ b/src/fs.ts @@ -49,7 +49,9 @@ const fsAdditions = { }, } -export default new Proxy( +type ProxyFS = typeof import("fs-plus") & typeof fsAdditions + +export default new Proxy( {}, { get(target, key) { diff --git a/src/init.ts b/src/init.ts index c73297f..3511345 100644 --- a/src/init.ts +++ b/src/init.ts @@ -9,11 +9,12 @@ import path from "path" import yargs from "yargs" import Command from "./command" import fs from "./fs" +import type { CliOptions, RunCallback } from "./apm-cli" const supportedSyntaxes = ["coffeescript", "javascript"] export default class Init extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -49,7 +50,7 @@ on the option selected.\ return options.string("template").describe("template", "Path to the package or theme template") } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { let templatePath options = this.parseOptions(options.commandArgs) if (options.argv.package?.length > 0) { diff --git a/src/install.ts b/src/install.ts index d5d0771..ef4722e 100644 --- a/src/install.ts +++ b/src/install.ts @@ -22,18 +22,23 @@ import fs from "./fs" import RebuildModuleCache from "./rebuild-module-cache" import * as request from "./request" import { isDeprecatedPackage } from "./deprecated-packages" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Install extends Command { + private atomDirectory = config.getAtomDirectory() + private atomPackagesDirectory: string + private atomNodeDirectory: string + private atomNpmPath = require.resolve("npm/bin/npm-cli") + private repoLocalPackagePathRegex = /^file:(?!\/\/)(.*)/ + verbose: boolean + constructor() { super() - this.atomDirectory = config.getAtomDirectory() this.atomPackagesDirectory = path.join(this.atomDirectory, "packages") this.atomNodeDirectory = path.join(this.atomDirectory, ".node-gyp") - this.atomNpmPath = require.resolve("npm/bin/npm-cli") - this.repoLocalPackagePathRegex = /^file:(?!\/\/)(.*)/ } - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -749,7 +754,7 @@ Run apm -v after installing Git to see what version has been detected.\ } } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { let packageNames options = this.parseOptions(options.commandArgs) const packagesFilePath = options.argv["packages-file"] diff --git a/src/link.ts b/src/link.ts index 3f251a5..b25395c 100644 --- a/src/link.ts +++ b/src/link.ts @@ -11,9 +11,10 @@ import yargs from "yargs" import Command from "./command" import * as config from "./apm" import fs from "./fs" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Link extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -28,7 +29,7 @@ Run \`apm links\` to view all the currently linked packages.\ return options.alias("d", "dev").boolean("dev").describe("dev", "Link to ~/.atom/dev/packages") } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { let left, targetPath options = this.parseOptions(options.commandArgs) diff --git a/src/links.ts b/src/links.ts index c36d3cb..1cfd8cf 100644 --- a/src/links.ts +++ b/src/links.ts @@ -9,15 +9,13 @@ import Command from "./command" import * as config from "./apm" import fs from "./fs" import { tree } from "./tree" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Links extends Command { - constructor() { - super() - this.devPackagesPath = path.join(config.getAtomDirectory(), "dev", "packages") - this.packagesPath = path.join(config.getAtomDirectory(), "packages") - } + private devPackagesPath = path.join(config.getAtomDirectory(), "dev", "packages") + private packagesPath = path.join(config.getAtomDirectory(), "packages") - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -62,7 +60,7 @@ List all of the symlinked atom packages in ~/.atom/packages and }) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { this.logLinks(this.devPackagesPath) this.logLinks(this.packagesPath) return callback() diff --git a/src/list.ts b/src/list.ts index 7432313..5c534e6 100644 --- a/src/list.ts +++ b/src/list.ts @@ -13,13 +13,16 @@ import fs from "./fs" import * as config from "./apm" import { tree } from "./tree" import { getRepository } from "./packages" +import type { CliOptions, RunCallback } from "./apm-cli" export default class List extends Command { + private userPackagesDirectory = path.join(config.getAtomDirectory(), "packages") + private devPackagesDirectory = path.join(config.getAtomDirectory(), "dev", "packages") + private disabledPackages?: string[] constructor() { super() - let configPath - this.userPackagesDirectory = path.join(config.getAtomDirectory(), "packages") - this.devPackagesDirectory = path.join(config.getAtomDirectory(), "dev", "packages") + let configPath: string + if ((configPath = CSON.resolve(path.join(config.getAtomDirectory(), "config")))) { try { this.disabledPackages = CSON.readFileSync(configPath)?.["*"]?.core?.disabledPackages @@ -32,7 +35,7 @@ export default class List extends Command { } } - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -284,7 +287,7 @@ List all the installed packages and also the packages bundled with Atom.\ }) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) if (options.argv.json) { diff --git a/src/login.ts b/src/login.ts index 00f09a6..7d61ce8 100644 --- a/src/login.ts +++ b/src/login.ts @@ -12,13 +12,14 @@ import open from "open" import * as auth from "./auth" import Command from "./command" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Login extends Command { - constructor(...args) { + constructor() { + super() this.welcomeMessage = this.welcomeMessage.bind(this) this.getToken = this.getToken.bind(this) this.saveToken = this.saveToken.bind(this) - super(...args) } static getTokenOrLogin(callback) { @@ -31,7 +32,7 @@ export default class Login extends Command { }) } - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -44,7 +45,7 @@ be used to identify you when publishing packages to atom.io.\ return options.string("token").describe("token", "atom.io API token") } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) return Q({ token: options.argv.token }) .then(this.welcomeMessage) diff --git a/src/package-converter.ts b/src/package-converter.ts index f413834..d4bc3c5 100644 --- a/src/package-converter.ts +++ b/src/package-converter.ts @@ -20,7 +20,11 @@ import * as request from "./request" // Convert a TextMate bundle to an Atom package export default class PackageConverter { - constructor(sourcePath, destinationPath) { + sourcePath: string + destinationPath: string + plistExtensions: string[] + directoryMappings: { Preferences: string; Snippets: string; Syntaxes: string } + constructor(sourcePath: string, destinationPath: string) { this.sourcePath = sourcePath this.destinationPath = path.resolve(destinationPath) @@ -33,7 +37,7 @@ export default class PackageConverter { } } - convert(callback) { + convert(callback: Function) { const { protocol } = url.parse(this.sourcePath) if (protocol === "http:" || protocol === "https:") { return this.downloadBundle(callback) @@ -48,7 +52,7 @@ export default class PackageConverter { return (downloadUrl += "/archive/master.tar.gz") } - downloadBundle(callback) { + downloadBundle(callback: Function) { const tempPath = temp.mkdirSync("atom-bundle-") const requestOptions = { url: this.getDownloadUrl() } return request.createReadStream(requestOptions, (readStream) => { @@ -69,8 +73,8 @@ export default class PackageConverter { }) } - copyDirectories(sourcePath, callback) { - let packageName + copyDirectories(sourcePath: string, callback: Function) { + let packageName: string sourcePath = path.resolve(sourcePath) try { packageName = JSON.parse(fs.readFileSync(path.join(sourcePath, "package.json")))?.packageName @@ -92,7 +96,13 @@ export default class PackageConverter { return delete object.keyEquivalent } - convertSettings(settings) { + convertSettings(settings: { + shellVariables: { name: any; value: any }[] | {} + increaseIndentPattern: any + decreaseIndentPattern: any + foldingStopMarker: any + completions: any + }) { if (settings.shellVariables) { const shellVariables = {} for (const { name, value } of settings.shellVariables) { @@ -114,7 +124,7 @@ export default class PackageConverter { } } - readFileSync(filePath) { + readFileSync(filePath: string) { if (this.plistExtensions.includes(path.extname(filePath))) { return plist.parseFileSync(filePath) } else if ([".json", ".cson"].includes(path.extname(filePath))) { @@ -122,15 +132,15 @@ export default class PackageConverter { } } - writeFileSync(filePath, object = {}) { + writeFileSync(filePath: string, object = {}) { this.filterObject(object) if (Object.keys(object).length > 0) { return CSON.writeFileSync(filePath, object) } } - convertFile(sourcePath, destinationDir) { - let contents + convertFile(sourcePath: string, destinationDir: string) { + let contents: {} const extension = path.extname(sourcePath) let destinationName = `${path.basename(sourcePath, extension)}.cson` destinationName = destinationName.toLowerCase() @@ -145,7 +155,7 @@ export default class PackageConverter { return this.writeFileSync(destinationPath, contents) } - normalizeFilenames(directoryPath) { + normalizeFilenames(directoryPath: string) { if (!fs.isDirectorySync(directoryPath)) { return } @@ -176,7 +186,7 @@ export default class PackageConverter { })() } - convertSnippets(packageName, source) { + convertSnippets(packageName: string, source: string) { let sourceSnippets = path.join(source, "snippets") if (!fs.isDirectorySync(sourceSnippets)) { sourceSnippets = path.join(source, "Snippets") @@ -233,7 +243,7 @@ export default class PackageConverter { return this.normalizeFilenames(destination) } - convertPreferences(packageName, source) { + convertPreferences(packageName: string, source: string) { let sourcePreferences = path.join(source, "preferences") if (!fs.isDirectorySync(sourcePreferences)) { sourcePreferences = path.join(source, "Preferences") @@ -245,14 +255,14 @@ export default class PackageConverter { const preferencesBySelector = {} const destination = path.join(this.destinationPath, "settings") for (const child of fs.readdirSync(sourcePreferences)) { - let left, properties + let left, properties: { [x: string]: any; editor?: any } const { scope, settings } = (left = this.readFileSync(path.join(sourcePreferences, child))) != null ? left : {} if (!scope || !settings) { continue } if ((properties = this.convertSettings(settings))) { - let selector + let selector: string try { selector = new ScopeSelector(scope).toCssSelector() } catch (e) { @@ -277,7 +287,7 @@ export default class PackageConverter { return this.normalizeFilenames(destination) } - convertGrammars(source) { + convertGrammars(source: string) { let sourceSyntaxes = path.join(source, "syntaxes") if (!fs.isDirectorySync(sourceSyntaxes)) { sourceSyntaxes = path.join(source, "Syntaxes") diff --git a/src/packages.ts b/src/packages.ts index fc96e5c..43a7c79 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -6,6 +6,10 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ import url from "url" +import { PackageMetadata } from "atom/src/package-manager" +export { PackageMetadata } from "atom/src/package-manager" + +export const unkownPackage = { name: "unkown", version: "0.0.0" } // Package helpers // Parse the repository in `name/owner` format from the package metadata. @@ -13,9 +17,9 @@ import url from "url" // pack - The package metadata object. // // Returns a name/owner string or null if not parseable. -export function getRepository(pack = {}) { - let repository - if ((repository = pack.repository?.url != null ? pack.repository?.url : pack.repository)) { +export function getRepository(pack: PackageMetadata = unkownPackage) { + const repository = getUrl(pack) + if (repository) { const repoPath = url.parse(repository.replace(/\.git$/, "")).pathname const [name, owner] = Array.from(repoPath.split("/").slice(-2)) if (name && owner) { @@ -25,10 +29,15 @@ export function getRepository(pack = {}) { return null } -// Determine remote from package metadata. +// Determine remote from package metadata (url) // // pack - The package metadata object. // Returns a the remote or 'origin' if not parseable. -export function getRemote(pack = {}) { - return pack.repository?.url || pack.repository || "origin" +export function getRemote(pack: PackageMetadata = unkownPackage) { + return getUrl(pack) || "origin" +} + +/** Get the repository */ +function getUrl(pack: PackageMetadata = unkownPackage) { + return typeof pack.repository === "object" && "url" in pack.repository ? pack.repository.url : pack.repository } diff --git a/src/publish.ts b/src/publish.ts index 2bab3f5..1b19d5d 100644 --- a/src/publish.ts +++ b/src/publish.ts @@ -12,19 +12,16 @@ import Git from "git-utils" import semver from "semver" import fs from "./fs" import * as config from "./apm" -import Command from "./command" +import Command, { LogCommandResultsArgs } from "./command" import Login from "./login" import * as Packages from "./packages" import * as request from "./request" export default class Publish extends Command { - constructor() { - super() - this.userConfigPath = config.getUserConfigPath() - this.atomNpmPath = require.resolve("npm/bin/npm-cli") - } + userConfigPath = config.getUserConfigPath() + atomNpmPath = require.resolve("npm/bin/npm-cli") - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -59,7 +56,7 @@ have published it.\ // version - The new version or version increment. // callback - The callback function to invoke with an error as the first // argument and a the generated tag string as the second argument. - versionPackage(version, callback) { + versionPackage(version: string, callback) { process.stdout.write("Preparing and tagging a new version ") const versionArgs = ["version", version, "-m", "Prepare v%s release"] return this.fork(this.atomNpmPath, versionArgs, (code, stderr = "", stdout = "") => { @@ -79,11 +76,11 @@ have published it.\ // pack - The package metadata. // callback - The callback function to invoke with an error as the first // argument. - pushVersion(tag, pack, callback) { + pushVersion(tag: string, pack: Packages.PackageMetadata, callback: Function) { process.stdout.write(`Pushing ${tag} tag `) const pushArgs = ["push", Packages.getRemote(pack), "HEAD", tag] - return this.spawn("git", pushArgs, (...args) => { - return this.logCommandResults(callback, ...Array.from(args)) + return this.spawn("git", pushArgs, (...args: LogCommandResultsArgs) => { + return this.logCommandResults(callback, ...args) }) } @@ -97,7 +94,7 @@ have published it.\ // callback - The callback function to invoke when either the tag is available // or the maximum numbers of requests for the tag have been made. // No arguments are passed to the callback when it is invoked. - waitForTagToBeAvailable(pack, tag, callback) { + waitForTagToBeAvailable(pack: Packages.PackageMetadata, tag: string, callback: Function) { let retryCount = 5 const interval = 1000 const requestSettings = { @@ -129,7 +126,7 @@ have published it.\ // packageName - The string package name to check. // callback - The callback function invoke with an error as the first // argument and true/false as the second argument. - packageExists(packageName, callback) { + packageExists(packageName: string, callback: Function) { return Login.getTokenOrLogin(function (error, token) { if (error != null) { return callback(error) @@ -156,7 +153,7 @@ have published it.\ // // pack - The package metadata. // callback - The callback function. - registerPackage(pack, callback) { + registerPackage(pack: Packages.PackageMetadata, callback: Function) { if (!pack.name) { callback("Required name field in package.json not found") return @@ -216,7 +213,7 @@ have published it.\ // tag - The string Git tag of the new version. // callback - The callback function to invoke with an error as the first // argument. - createPackageVersion(packageName, tag, options, callback) { + createPackageVersion(packageName: string, tag: string, options: { rename: boolean }, callback: Function) { return Login.getTokenOrLogin(function (error, token) { if (error != null) { callback(error) @@ -254,7 +251,7 @@ have published it.\ // options - An options Object (optional). // callback - The callback function to invoke when done with an error as the // first argument. - publishPackage(pack, tag, ...remaining) { + publishPackage(pack: Packages.PackageMetadata, tag: string, ...remaining) { let options if (remaining.length >= 2) { options = remaining.shift() @@ -276,7 +273,7 @@ have published it.\ }) } - logFirstTimePublishMessage(pack) { + logFirstTimePublishMessage(pack: Packages.PackageMetadata) { process.stdout.write("Congrats on publishing a new package!".rainbow) // :+1: :package: :tada: when available if (process.platform === "darwin") { @@ -299,7 +296,7 @@ have published it.\ } } - saveMetadata(pack, callback) { + saveMetadata(pack: Packages.PackageMetadata, callback: Function) { const metadataPath = path.resolve("package.json") const metadataJson = JSON.stringify(pack, null, 2) return fs.writeFile(metadataPath, `${metadataJson}\n`, callback) @@ -338,7 +335,7 @@ have published it.\ } // Rename package if necessary - renamePackage(pack, name, callback) { + renamePackage(pack: Packages.PackageMetadata, name: string, callback: Function) { if (name?.length > 0) { if (pack.name === name) { return callback("The new package name must be different than the name in the package.json file") @@ -382,12 +379,12 @@ have published it.\ } } - setPackageName(pack, name, callback) { + setPackageName(pack: Packages.PackageMetadata, name: string, callback: Function) { pack.name = name return this.saveMetadata(pack, callback) } - validateSemverRanges(pack) { + validateSemverRanges(pack: Packages.PackageMetadata) { let packageName, semverRange if (!pack) { return @@ -431,8 +428,8 @@ have published it.\ } // Run the publish command with the given options - run(options, callback) { - let error, pack + run(options, callback: Function) { + let error, pack: Packages.PackageMetadata options = this.parseOptions(options.commandArgs) const { tag } = options.argv let { rename } = options.argv diff --git a/src/rebuild-module-cache.ts b/src/rebuild-module-cache.ts index e7353ef..3e75e81 100644 --- a/src/rebuild-module-cache.ts +++ b/src/rebuild-module-cache.ts @@ -10,14 +10,13 @@ import yargs from "yargs" import Command from "./command" import * as config from "./apm" import fs from "./fs" +import type { CliOptions, RunCallback } from "./apm-cli" export default class RebuildModuleCache extends Command { - constructor() { - super() - this.atomPackagesDirectory = path.join(config.getAtomDirectory(), "packages") - } + atomPackagesDirectory = path.join(config.getAtomDirectory(), "packages") + moduleCache?: any - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -34,7 +33,7 @@ This command skips all linked packages.\ return options.alias("h", "help").describe("help", "Print this usage message") } - getResourcePath(callback) { + getResourcePath(callback: Function) { if (this.resourcePath) { return process.nextTick(() => callback(this.resourcePath)) } else { @@ -45,8 +44,8 @@ This command skips all linked packages.\ } } - rebuild(packageDirectory, callback) { - return this.getResourcePath((resourcePath) => { + rebuild(packageDirectory: string, callback: Function) { + return this.getResourcePath((resourcePath: string) => { try { if (this.moduleCache == null) { this.moduleCache = require(path.join(resourcePath, "src", "module-cache")) @@ -60,7 +59,7 @@ This command skips all linked packages.\ }) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { const commands = [] fs.list(this.atomPackagesDirectory).forEach((packageName) => { const packageDirectory = path.join(this.atomPackagesDirectory, packageName) @@ -71,9 +70,9 @@ This command skips all linked packages.\ return } - return commands.push((callback) => { + return commands.push((callback: Function) => { process.stdout.write(`Rebuilding ${packageName} module cache `) - return this.rebuild(packageDirectory, (error) => { + return this.rebuild(packageDirectory, (error?: Error) => { if (error != null) { this.logFailure() } else { diff --git a/src/rebuild.ts b/src/rebuild.ts index 591a343..778bd2f 100644 --- a/src/rebuild.ts +++ b/src/rebuild.ts @@ -9,16 +9,19 @@ import yargs from "yargs" import * as config from "./apm" import Command from "./command" import fs from "./fs" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Rebuild extends Command { + private atomDirectory = config.getAtomDirectory() + private atomNpmPath = require.resolve("npm/bin/npm-cli") + private atomNodeDirectory: string + constructor() { super() - this.atomDirectory = config.getAtomDirectory() this.atomNodeDirectory = path.join(this.atomDirectory, ".node-gyp") - this.atomNpmPath = require.resolve("npm/bin/npm-cli") } - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -53,7 +56,7 @@ All the modules will be rebuilt if no module names are specified.\ return this.fork(this.atomNpmPath, rebuildArgs, { env }, callback) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) return config.loadNpm((error, npm) => { diff --git a/src/request.ts b/src/request.ts index a2e25a7..0e393c9 100644 --- a/src/request.ts +++ b/src/request.ts @@ -6,10 +6,10 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ import npm from "npm" -import request from "request" +import request, { Options, RequestCallback } from "request" import * as config from "./apm" -function loadNpm(callback) { +function loadNpm(callback: Parameters[1]) { const npmOptions = { userconfig: config.getUserConfigPath(), globalconfig: config.getGlobalConfigPath(), @@ -17,7 +17,7 @@ function loadNpm(callback) { return npm.load(npmOptions, callback) } -function configureRequest(requestOptions, callback) { +function configureRequest(requestOptions: Options, callback: () => void) { return loadNpm(function () { let left if (requestOptions.proxy == null) { @@ -40,9 +40,9 @@ function configureRequest(requestOptions, callback) { }) } -export function get(requestOptions, callback) { +export function get(requestOptions: Options & { retries?: number }, callback: RequestCallback) { return configureRequest(requestOptions, function () { - let retryCount = requestOptions.retries != null ? requestOptions.retries : 0 + let retryCount = "retries" in requestOptions ? requestOptions.retries : 0 let requestsMade = 0 const tryRequest = function () { requestsMade++ @@ -63,19 +63,22 @@ export function get(requestOptions, callback) { }) } -export function del(requestOptions, callback) { +export function del(requestOptions: Options, callback: RequestCallback) { return configureRequest(requestOptions, () => request.del(requestOptions, callback)) } -export function post(requestOptions, callback) { +export function post(requestOptions: Options, callback: RequestCallback) { return configureRequest(requestOptions, () => request.post(requestOptions, callback)) } -export function createReadStream(requestOptions, callback) { +export function createReadStream( + requestOptions: Options, + callback: { (readStream: any): any; (arg0: request.Request): void } +) { return configureRequest(requestOptions, () => callback(request.get(requestOptions))) } -export function getErrorMessage(response, body) { +export function getErrorMessage(response: request.Response, body: {} | { repository?: { url?: string } }) { if (response?.statusCode === 503) { return "atom.io is temporarily unavailable, please try again later." } else { @@ -84,6 +87,6 @@ export function getErrorMessage(response, body) { } } -export function debug(debug) { +export function debug(debug: boolean) { return (request.debug = debug) } diff --git a/src/search.ts b/src/search.ts index 953dc8d..7272b2d 100644 --- a/src/search.ts +++ b/src/search.ts @@ -12,9 +12,10 @@ import * as config from "./apm" import * as request from "./request" import { tree } from "./tree" import { isDeprecatedPackage } from "./deprecated-packages" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Search extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -63,7 +64,7 @@ Search for Atom packages/themes on the atom.io registry.\ }) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) const [query] = Array.from(options.argv._) diff --git a/src/star.ts b/src/star.ts index 4e6e315..b2cfba7 100644 --- a/src/star.ts +++ b/src/star.ts @@ -16,9 +16,10 @@ import fs from "./fs" import Login from "./login" import * as Packages from "./packages" import * as request from "./request" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Star extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -87,7 +88,7 @@ Run \`apm stars\` to see all your starred packages.\ return _.uniq(installedPackages) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { let packageNames options = this.parseOptions(options.commandArgs) diff --git a/src/stars.ts b/src/stars.ts index 9a19286..c775344 100644 --- a/src/stars.ts +++ b/src/stars.ts @@ -12,9 +12,10 @@ import Install from "./install" import Login from "./login" import * as request from "./request" import { tree } from "./tree" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Stars extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -123,7 +124,7 @@ List or install starred Atom packages and themes.\ return callback() } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) const user = options.argv.user?.toString().trim() diff --git a/src/test.ts b/src/test.ts index b1e5809..a1c7d35 100644 --- a/src/test.ts +++ b/src/test.ts @@ -8,9 +8,10 @@ import yargs from "yargs" import temp from "temp" import Command from "./command" import fs from "./fs" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Test extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -24,7 +25,7 @@ to the current working directory).\ return options.alias("p", "path").string("path").describe("path", "Path to atom command") } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { let atomCommand options = this.parseOptions(options.commandArgs) const { env } = process diff --git a/src/text-mate-theme.ts b/src/text-mate-theme.ts index 58f6e92..fa37dc9 100644 --- a/src/text-mate-theme.ts +++ b/src/text-mate-theme.ts @@ -9,7 +9,24 @@ import plist from "@atom/plist" import { ScopeSelector } from "first-mate" +export type RuleSet = { + selector: string + comment?: string + properties: Record +} + +export type ScopeSelectorSettings = { + "font-weight"?: string + "font-style"?: string + "text-decoration"?: string + color?: string + "background-color"?: string +} + export default class TextMateTheme { + contents: string + rulesets: RuleSet[] + syntaxVariables: string constructor(contents) { this.contents = contents this.rulesets = [] @@ -17,11 +34,8 @@ export default class TextMateTheme { } buildRulesets() { - let left, variableSettings - let { settings } = (left = plist.parseStringSync(this.contents)) != null ? left : {} - if (settings == null) { - settings = [] - } + let variableSettings + const settings = plist.parseStringSync(this.contents)?.settings ?? [] for (const setting of settings) { const { scope, name } = setting.settings @@ -188,7 +202,7 @@ atom-text-editor.is-focused .line.cursor-line`, } translateScopeSelectorSettings({ foreground, background, fontStyle }) { - const properties = {} + const properties: ScopeSelectorSettings = {} if (fontStyle) { const fontStyles = fontStyle.split(/\s+/) diff --git a/src/theme-converter.ts b/src/theme-converter.ts index 4c8f9d6..ee341e5 100644 --- a/src/theme-converter.ts +++ b/src/theme-converter.ts @@ -12,7 +12,9 @@ import TextMateTheme from "./text-mate-theme" // Convert a TextMate theme to an Atom theme export default class ThemeConverter { - constructor(sourcePath, destinationPath) { + sourcePath: string + destinationPath: string + constructor(sourcePath: string, destinationPath: string) { this.sourcePath = sourcePath this.destinationPath = path.resolve(destinationPath) } diff --git a/src/types/atom.d.ts b/src/types/atom.d.ts new file mode 100644 index 0000000..2d9f26e --- /dev/null +++ b/src/types/atom.d.ts @@ -0,0 +1,37 @@ +declare module "atom/src/package-manager" { + import { Package, Emitter } from "atom" + + /** The content of a package.json */ + export type PackageMetadata = { + name: string + version: string + repository?: string | { url: string } + engines?: { atom?: string } + dependencies?: { name: string; version: string }[] + devDependencies?: { name: string; version: string }[] + apmInstallSource?: { sha: string; type: string } + } + + export class PackageManager { + readonly initialPackagesActivated: boolean + + getAvailablePackageMetadata(): Array + + activate(): Promise + deactivatePackages(): Promise + deactivatePackage(name: string, suppressSerialization?: boolean): Promise + emitter: Emitter + loadedPackages: { + [packageName: string]: Package + } + loadPackage(name: string): void + loadPackages(): void + serializePackage(pkg: Package): void + // serviceHub: ServiceHub + packageDirPaths: Array + triggerActivationHook(hook: string): void + triggerDeferredActivationHooks(): void + unloadPackage(name: string): void + unloadPackages(): void + } +} diff --git a/src/uninstall.ts b/src/uninstall.ts index 27384e6..2cc7dde 100644 --- a/src/uninstall.ts +++ b/src/uninstall.ts @@ -13,9 +13,10 @@ import Command from "./command" import * as config from "./apm" import fs from "./fs" import * as request from "./request" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Uninstall extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -58,7 +59,7 @@ Delete the installed package(s) from the ~/.atom/packages directory.\ }) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) const packageNames = this.packageNamesFromArgv(options.argv) diff --git a/src/unlink.ts b/src/unlink.ts index e62ac6c..5d1c2ac 100644 --- a/src/unlink.ts +++ b/src/unlink.ts @@ -11,15 +11,13 @@ import yargs from "yargs" import Command from "./command" import * as config from "./apm" import fs from "./fs" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Unlink extends Command { - constructor() { - super() - this.devPackagesPath = path.join(config.getAtomDirectory(), "dev", "packages") - this.packagesPath = path.join(config.getAtomDirectory(), "packages") - } + devPackagesPath = path.join(config.getAtomDirectory(), "dev", "packages") + packagesPath = path.join(config.getAtomDirectory(), "packages") - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -121,7 +119,7 @@ Run \`apm links\` to view all the currently linked packages.\ } } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) if (options.argv.all) { diff --git a/src/unpublish.ts b/src/unpublish.ts index dceb379..c4597e3 100644 --- a/src/unpublish.ts +++ b/src/unpublish.ts @@ -15,9 +15,10 @@ import Command from "./command" import * as config from "./apm" import fs from "./fs" import * as request from "./request" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Unpublish extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -112,7 +113,7 @@ name is specified.\ }) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { let version options = this.parseOptions(options.commandArgs) let [name] = Array.from(options.argv._) diff --git a/src/unstar.ts b/src/unstar.ts index 7493714..4b1f8af 100644 --- a/src/unstar.ts +++ b/src/unstar.ts @@ -11,9 +11,10 @@ import * as config from "./apm" import Command from "./command" import Login from "./login" import * as request from "./request" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Unstar extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -54,7 +55,7 @@ Run \`apm stars\` to see all your starred packages.\ }) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) const packageNames = this.packageNamesFromArgv(options.argv) diff --git a/src/upgrade.ts b/src/upgrade.ts index 2159ba3..6c8701f 100644 --- a/src/upgrade.ts +++ b/src/upgrade.ts @@ -19,15 +19,19 @@ import * as Packages from "./packages" import * as request from "./request" import { tree } from "./tree" import * as git from "./git" +import { PackageMetadata } from "./packages" +import type { CliOptions, RunCallback } from "./apm-cli" export default class Upgrade extends Command { + private atomDirectory = config.getAtomDirectory() + private atomPackagesDirectory: string + constructor() { super() - this.atomDirectory = config.getAtomDirectory() this.atomPackagesDirectory = path.join(this.atomDirectory, "packages") } - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -69,7 +73,7 @@ available updates.\ return packages } - getIntalledPackage(name) { + getIntalledPackage(name: string) { const packageDirectory = path.join(this.atomPackagesDirectory, name) if (fs.isSymbolicLinkSync(packageDirectory)) { return @@ -98,12 +102,12 @@ available updates.\ } } - folderIsRepo(pack) { + folderIsRepo(pack: PackageMetadata) { const repoGitFolderPath = path.join(this.atomPackagesDirectory, pack.name, ".git") return fs.existsSync(repoGitFolderPath) } - getLatestVersion(pack, callback) { + getLatestVersion(pack: PackageMetadata, callback) { const requestSettings = { url: `${config.getAtomPackagesUrl()}/${pack.name}`, json: true, @@ -153,7 +157,7 @@ available updates.\ }) } - getLatestSha(pack, callback) { + getLatestSha(pack: PackageMetadata, callback: Function) { const repoPath = path.join(this.atomPackagesDirectory, pack.name) return config.getSetting("git", (command) => { if (command == null) { @@ -176,12 +180,12 @@ available updates.\ }) } - hasRepo(pack) { + hasRepo(pack: PackageMetadata) { return Packages.getRepository(pack) != null } - getAvailableUpdates(packages, callback) { - const getLatestVersionOrSha = (pack, done) => { + getAvailableUpdates(packages: PackageMetadata[], callback: Function) { + const getLatestVersionOrSha = (pack: PackageMetadata, done) => { if (this.folderIsRepo(pack) && pack.apmInstallSource?.type === "git") { return this.getLatestSha(pack, (err, sha) => done(err, { pack, sha })) } else { @@ -189,16 +193,21 @@ available updates.\ } } - return async.mapLimit(packages, 10, getLatestVersionOrSha, function (error, updates) { - if (error != null) { - return callback(error) - } + return async.mapLimit( + packages, + 10, + getLatestVersionOrSha, + (error, updates: { latestVersion?: string; sha?: string; pack: PackageMetadata }[]) => { + if (error != null) { + return callback(error) + } - updates = updates.filter((update) => update.latestVersion != null || update.sha != null) - updates.sort((updateA, updateB) => updateA.pack.name.localeCompare(updateB.pack.name)) + updates = updates.filter((update) => update.latestVersion != null || update.sha != null) + updates.sort((updateA, updateB) => updateA.pack.name.localeCompare(updateB.pack.name)) - return callback(null, updates) - }) + return callback(null, updates) + } + ) } promptForConfirmation(callback) { @@ -230,7 +239,7 @@ available updates.\ return async.waterfall(installCommands, callback) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { const { command } = options options = this.parseOptions(options.commandArgs) options.command = command diff --git a/src/view.ts b/src/view.ts index e4778cd..47de80e 100644 --- a/src/view.ts +++ b/src/view.ts @@ -13,9 +13,10 @@ import Command from "./command" import * as config from "./apm" import * as request from "./request" import { tree } from "./tree" +import type { CliOptions, RunCallback } from "./apm-cli" export default class View extends Command { - parseOptions(argv) { + parseOptions(argv: string[]) { const options = yargs(argv).wrap(Math.min(100, yargs.terminalWidth())) options.usage(`\ @@ -110,7 +111,7 @@ View information about a package/theme in the atom.io registry.\ }) } - run(options, callback) { + run(options: CliOptions, callback: RunCallback) { options = this.parseOptions(options.commandArgs) const [packageName] = Array.from(options.argv._)