From 99d3c01dc9bbeb1b33957375881fc7973fca730b Mon Sep 17 00:00:00 2001 From: Ramon Brullo Date: Mon, 16 Oct 2023 17:36:12 +0200 Subject: [PATCH] feat: convert to typescript --- bin/openupm | 2 +- bin/openupm-cn | 2 +- lib/{cli.js => cli.ts} | 51 +-- lib/{client.js => client.ts} | 14 +- lib/{cmd-add.js => cmd-add.ts} | 67 ++-- lib/{cmd-deps.js => cmd-deps.ts} | 34 +- lib/{cmd-login.js => cmd-login.ts} | 119 +++++-- lib/{cmd-remove.js => cmd-remove.ts} | 30 +- lib/{cmd-search.js => cmd-search.ts} | 83 +++-- lib/{cmd-view.js => cmd-view.ts} | 25 +- lib/{core.js => core.ts} | 241 ++++++++----- lib/error-handler.js | 13 - lib/error-handler.ts | 15 + lib/logger.js | 8 - lib/logger.ts | 8 + lib/types.ts | 129 +++++++ lib/utils/process.js | 35 -- lib/utils/process.ts | 34 ++ package-lock.json | 512 ++++++++++++++++++++++++++- package.json | 9 +- test/test-cmd-add.js | 193 +++++----- test/test-cmd-deps.js | 76 ++-- test/test-cmd-login.js | 4 +- test/test-cmd-remove.js | 52 +-- test/test-cmd-search.js | 84 +++-- test/test-cmd-view.js | 78 ++-- test/test-core.js | 4 +- tsconfig.json | 2 +- 28 files changed, 1366 insertions(+), 558 deletions(-) rename lib/{cli.js => cli.ts} (76%) rename lib/{client.js => client.ts} (59%) rename lib/{cmd-add.js => cmd-add.ts} (83%) rename lib/{cmd-deps.js => cmd-deps.ts} (51%) rename lib/{cmd-login.js => cmd-login.ts} (70%) rename lib/{cmd-remove.js => cmd-remove.ts} (78%) rename lib/{cmd-search.js => cmd-search.ts} (54%) rename lib/{cmd-view.js => cmd-view.ts} (83%) rename lib/{core.js => core.ts} (71%) delete mode 100644 lib/error-handler.js create mode 100644 lib/error-handler.ts delete mode 100644 lib/logger.js create mode 100644 lib/logger.ts create mode 100644 lib/types.ts delete mode 100644 lib/utils/process.js create mode 100644 lib/utils/process.ts diff --git a/bin/openupm b/bin/openupm index b465f9fa..148b0b2a 100755 --- a/bin/openupm +++ b/bin/openupm @@ -1,3 +1,3 @@ #!/usr/bin/env node -require("../lib/cli"); +require("../build/lib/cli"); diff --git a/bin/openupm-cn b/bin/openupm-cn index 9d08b384..a8f5aef5 100755 --- a/bin/openupm-cn +++ b/bin/openupm-cn @@ -1,4 +1,4 @@ #!/usr/bin/env node if (!process.argv.includes("--cn")) process.argv.push("--cn"); -require("../lib/cli"); +require("../build/lib/cli"); diff --git a/lib/cli.js b/lib/cli.ts similarity index 76% rename from lib/cli.js rename to lib/cli.ts index ab3d0886..87f5db70 100644 --- a/lib/cli.js +++ b/lib/cli.ts @@ -1,16 +1,20 @@ -const program = require("commander"); -const add = require("./cmd-add"); -const remove = require("./cmd-remove"); -const search = require("./cmd-search"); -const view = require("./cmd-view"); -const deps = require("./cmd-deps"); -const { login } = require("./cmd-login"); -const { log } = require("./logger"); -require("pkginfo")(module); +import { program } from "commander"; +import pkginfo from "pkginfo"; +import updateNotifier from "update-notifier"; +import { add } from "./cmd-add"; +import { remove } from "./cmd-remove"; +import { search } from "./cmd-search"; +import { view } from "./cmd-view"; +import { deps } from "./cmd-deps"; +import { login } from "./cmd-login"; + +import log from "./logger"; // update-notifier -const updateNotifier = require("update-notifier"); -const pkg = require("../package.json"); + +import pkg from "../package.json"; + +pkginfo(module); const notifier = updateNotifier({ pkg }); notifier.notify(); @@ -39,7 +43,7 @@ openupm add [otherPkgs...] openupm add @ [otherPkgs...]` ) .action(async function (pkg, otherPkgs, options) { - options._global = program.opts() + options._global = program.opts(); const pkgs = [pkg].concat(otherPkgs); const retCode = await add(pkgs, options); if (retCode) process.exit(retCode); @@ -49,8 +53,8 @@ program .command("remove [otherPkgs...]") .aliases(["rm", "uninstall"]) .description("remove package from manifest json") - .action(async function(pkg, otherPkgs, options) { - options._global = program.opts() + .action(async function (pkg, otherPkgs, options) { + options._global = program.opts(); const pkgs = [pkg].concat(otherPkgs); const retCode = await remove(pkgs, options); if (retCode) process.exit(retCode); @@ -60,8 +64,8 @@ program .command("search ") .aliases(["s", "se", "find"]) .description("Search package by keyword") - .action(async function(keyword, options) { - options._global = program.opts() + .action(async function (keyword, options) { + options._global = program.opts(); const retCode = await search(keyword, options); if (retCode) process.exit(retCode); }); @@ -70,8 +74,8 @@ program .command("view ") .aliases(["v", "info", "show"]) .description("view package information") - .action(async function(pkg, options) { - options._global = program.opts() + .action(async function (pkg, options) { + options._global = program.opts(); const retCode = await view(pkg, options); if (retCode) process.exit(retCode); }); @@ -85,8 +89,8 @@ program openupm deps openupm deps @` ) - .action(async function(pkg, options) { - options._global = program.opts() + .action(async function (pkg, options) { + options._global = program.opts(); const retCode = await deps(pkg, options); if (retCode) process.exit(retCode); }); @@ -104,19 +108,20 @@ program "always auth for tarball hosted on a different domain" ) .description("authenticate with a scoped registry") - .action(async function(options) { - options._global = program.opts() + .action(async function (options) { + options._global = program.opts(); try { const retCode = await login(options); if (retCode) process.exit(retCode); } catch (err) { + // @ts-ignore log.error("", err.message); process.exit(1); } }); // prompt for invalid command -program.on("command:*", function() { +program.on("command:*", function () { log.warn("", `unknown command: ${program.args.join(" ")}`); log.warn("", "see --help for a list of available commands"); process.exit(1); diff --git a/lib/client.js b/lib/client.ts similarity index 59% rename from lib/client.js rename to lib/client.ts index 61bcda47..55a356ea 100644 --- a/lib/client.js +++ b/lib/client.ts @@ -1,12 +1,14 @@ -const { promisify } = require("util"); -const RegClient = require("another-npm-registry-client"); +import {promisify} from "util"; + +// @ts-ignore +import RegClient from "another-npm-registry-client"; +import log from "./logger"; -const { log } = require("./logger"); /** * Return npm client */ -const getNpmClient = function() { +export const getNpmClient = function() { // create client const client = new RegClient({ log }); return { @@ -17,7 +19,3 @@ const getNpmClient = function() { adduser: promisify(client.adduser.bind(client)) }; }; - -module.exports = { - getNpmClient -}; diff --git a/lib/cmd-add.js b/lib/cmd-add.ts similarity index 83% rename from lib/cmd-add.js rename to lib/cmd-add.ts index 272e1ff2..94ab4283 100644 --- a/lib/cmd-add.js +++ b/lib/cmd-add.ts @@ -1,6 +1,6 @@ -const { log } = require("./logger"); -const url = require("url"); -const { +import log from "./logger"; +import url from "url"; +import { compareEditorVersion, env, fetchPackageDependencies, @@ -10,10 +10,20 @@ const { parseEditorVersion, parseEnv, parseName, - saveManifest -} = require("./core"); + saveManifest, +} from "./core"; +import { GlobalOptions, Pkg, PkgName, ScopedRegistry } from "./types"; -const add = async function(pkgs, options) { +export type AddOptions = { + test: boolean; + force: boolean; + _global: GlobalOptions; +}; + +export const add = async function ( + pkgs: Pkg | Pkg[], + options: AddOptions +): Promise { if (!Array.isArray(pkgs)) pkgs = [pkgs]; // parse env const envOk = await parseEnv(options, { checkPath: true }); @@ -25,8 +35,8 @@ const add = async function(pkgs, options) { await _add({ pkg, testables: options.test, force: options.force }) ); const result = { - code: results.filter(x => x.code != 0).length > 0 ? 1 : 0, - dirty: results.filter(x => x.dirty).length > 0 + code: results.filter((x) => x.code != 0).length > 0 ? 1 : 0, + dirty: results.filter((x) => x.dirty).length > 0, }; // print manifest notice if (result.dirty) @@ -34,7 +44,15 @@ const add = async function(pkgs, options) { return result.code; }; -const _add = async function({ pkg, testables, force }) { +const _add = async function ({ + pkg, + testables, + force, +}: { + pkg: Pkg; + testables: boolean; + force: boolean; +}) { // dirty flag let dirty = false; // is upstream package flag @@ -49,7 +67,7 @@ const _add = async function({ pkg, testables, force }) { manifest.dependencies = {}; } // packages that added to scope registry - const pkgsInScope = []; + const pkgsInScope: PkgName[] = []; const isGitOrLocal = version && (version.startsWith("git") || @@ -70,7 +88,7 @@ const _add = async function({ pkg, testables, force }) { const versions = Object.keys(pkgInfo.versions); // eslint-disable-next-line require-atomic-updates if (!version || version == "latest") version = getLatestVersion(pkgInfo); - if (versions.filter(x => x == version).length <= 0) { + if (versions.filter((x) => x == version).length <= 0) { log.warn( "404", `version ${version} is not a valid choice of: ${versions @@ -79,6 +97,7 @@ const _add = async function({ pkg, testables, force }) { ); return { code: 1, dirty }; } + const versionInfo = pkgInfo.versions[version]; // verify editor version if (versionInfo.unity) { @@ -130,16 +149,18 @@ const _add = async function({ pkg, testables, force }) { const [depsValid, depsInvalid] = await fetchPackageDependencies({ name, version, - deep: true + deep: true, }); // add depsValid to pkgsInScope. depsValid - .filter(x => !x.upstream && !x.internal) - .map(x => x.name) - .forEach(name => pkgsInScope.push(name)); + .filter((x) => !x.upstream && !x.internal) + .map((x) => x.name) + .forEach((name) => pkgsInScope.push(name)); // print suggestion for depsInvalid - depsInvalid.forEach(depObj => { + depsInvalid.forEach((depObj) => { if (depObj.reason == "package404" || depObj.reason == "version404") { + // TODO: Do null check on manifest + // @ts-ignore const resolvedVersion = manifest.dependencies[depObj.name]; depObj.resolved = Boolean(resolvedVersion); if (!depObj.resolved) @@ -149,7 +170,7 @@ const _add = async function({ pkg, testables, force }) { ); } }); - if (depsInvalid.filter(x => !x.resolved).length > 0) { + if (depsInvalid.filter((x) => !x.resolved).length > 0) { if (!force) { log.error( "missing dependencies", @@ -162,6 +183,8 @@ const _add = async function({ pkg, testables, force }) { } // add to dependencies const oldVersion = manifest.dependencies[name]; + // TODO: Do undefined check on version + // @ts-ignore manifest.dependencies[name] = version; if (!oldVersion) { // Log the added package @@ -181,16 +204,18 @@ const _add = async function({ pkg, testables, force }) { manifest.scopedRegistries = []; dirty = true; } - const filterEntry = x => { + const filterEntry = (x: ScopedRegistry): boolean => { let addr = x.url || ""; if (addr.endsWith("/")) addr = addr.slice(0, -1); return addr == env.registry; }; if (manifest.scopedRegistries.filter(filterEntry).length <= 0) { manifest.scopedRegistries.push({ + // TODO: Handle null name + // @ts-ignore name: url.parse(env.registry).hostname, url: env.registry, - scopes: [] + scopes: [], }); dirty = true; } @@ -198,7 +223,7 @@ const _add = async function({ pkg, testables, force }) { // apply pkgsInScope let scopesSet = new Set(entry.scopes || []); pkgsInScope.push(env.namespace); - pkgsInScope.forEach(name => { + pkgsInScope.forEach((name) => { if (!scopesSet.has(name)) { scopesSet.add(name); dirty = true; @@ -220,5 +245,3 @@ const _add = async function({ pkg, testables, force }) { } return { code: 0, dirty }; }; - -module.exports = add; diff --git a/lib/cmd-deps.js b/lib/cmd-deps.ts similarity index 51% rename from lib/cmd-deps.js rename to lib/cmd-deps.ts index ff1f4e58..47f39aba 100644 --- a/lib/cmd-deps.js +++ b/lib/cmd-deps.ts @@ -1,7 +1,13 @@ -const { log } = require("./logger"); -const { fetchPackageDependencies, parseEnv, parseName } = require("./core"); +import log from "./logger"; +import { fetchPackageDependencies, parseEnv, parseName } from "./core"; +import { GlobalOptions, Pkg, PkgName, PkgVersionName } from "./types"; -const deps = async function(pkg, options) { +export type DepsOptions = { + deep: boolean; + _global: GlobalOptions; +}; + +export const deps = async function (pkg: Pkg, options: DepsOptions) { // parse env const envOk = await parseEnv(options, { checkPath: false }); if (!envOk) return 1; @@ -12,24 +18,30 @@ const deps = async function(pkg, options) { return 0; }; -const _deps = async function({ name, version, deep }) { +const _deps = async function ({ + name, + version, + deep, +}: { + name: PkgName; + version: PkgVersionName; + deep: boolean; +}) { // eslint-disable-next-line no-unused-vars const [depsValid, depsInvalid] = await fetchPackageDependencies({ name, version, - deep + deep, }); depsValid - .filter(x => !x.self) - .forEach(x => log.notice("dependency", `${x.name}@${x.version}`)); + .filter((x) => !x.self) + .forEach((x) => log.notice("dependency", `${x.name}@${x.version}`)); depsInvalid - .filter(x => !x.self) - .forEach(x => { + .filter((x) => !x.self) + .forEach((x) => { let reason = "unknown"; if (x.reason == "package404") reason = "missing dependency"; else if (x.reason == "version404") reason = "missing dependency version"; log.warn(reason, `${x.name}@${x.version}`); }); }; - -module.exports = deps; diff --git a/lib/cmd-login.js b/lib/cmd-login.ts similarity index 70% rename from lib/cmd-login.js rename to lib/cmd-login.ts index 6b839c32..bdc55db2 100644 --- a/lib/cmd-login.js +++ b/lib/cmd-login.ts @@ -1,19 +1,29 @@ -const fs = require("fs"); -const path = require("path"); +import fs from "fs"; +import path from "path"; +import _ from "lodash"; +import promptly from "promptly"; +import { getNpmClient } from "./client"; -const _ = require("lodash"); -const promptly = require("promptly"); +import log from "./logger"; -const { getNpmClient } = require("./client"); -const { log } = require("./logger"); -const { +import { getUpmConfigDir, loadUpmConfig, + parseEnv, saveUpmConfig, - parseEnv -} = require("./core"); +} from "./core"; +import { GlobalOptions, Registry } from "./types"; -const login = async function(options) { +export type LoginOptions = { + username?: string; + password?: string; + email?: string; + basicAuth?: boolean; + alwaysAuth?: boolean; + _global: GlobalOptions; +}; + +export const login = async function (options: LoginOptions) { // parse env const envOk = await parseEnv(options, { checkPath: false }); if (!envOk) return 1; @@ -24,7 +34,7 @@ const login = async function(options) { if (!options.email) options.email = await promptly.prompt("Email: "); if (!options._global.registry) options._global.registry = await promptly.prompt("Registry: ", { - validator: [validateRegistry] + validator: [validateRegistry], }); let token = null; let _auth = null; @@ -38,7 +48,7 @@ const login = async function(options) { username: options.username, password: options.password, email: options.email, - registry: options._global.registry + registry: options._global.registry, }); if (result.code == 1) return result.code; if (!result.token) { @@ -49,7 +59,7 @@ const login = async function(options) { // write npm token await writeNpmToken({ registry: options._global.registry, - token: result.token + token: result.token, }); } // write unity token @@ -59,7 +69,7 @@ const login = async function(options) { basicAuth: options.basicAuth || false, email: options.email, registry: options._global.registry, - token + token, }); }; @@ -67,15 +77,25 @@ const login = async function(options) { * Return npm login token * @param {*} param0 */ -const npmLogin = async function({ username, password, email, registry }) { +const npmLogin = async function ({ + username, + password, + email, + registry, +}: { + username: string; + password: string; + email: string; + registry: Registry; +}) { const client = getNpmClient(); try { const data = await client.adduser(registry, { auth: { username, password, - email - } + email, + }, }); if (_.isString(data.ok)) log.notice("auth", data.ok); else if (data.ok) @@ -83,10 +103,13 @@ const npmLogin = async function({ username, password, email, registry }) { const token = data.token; return { code: 0, token }; } catch (err) { + // TODO: Type-check error + // @ts-ignore if (err.statusCode == 401 || err.code == "EAUTHUNKNOWN") { log.warn("401", "Incorrect username or password"); return { code: 1 }; } else { + // @ts-ignore log.error(err.statusCode ? err.statusCode.toString() : "", err.message); return { code: 1 }; } @@ -97,7 +120,13 @@ const npmLogin = async function({ username, password, email, registry }) { * Write npm token to .npmrc * @param {*} param0 */ -const writeNpmToken = async function({ registry, token }) { +const writeNpmToken = async function ({ + registry, + token, +}: { + registry: Registry; + token: string; +}) { const configPath = getNpmrcPath(); // read config let content = ""; @@ -114,10 +143,12 @@ const writeNpmToken = async function({ registry, token }) { /** * Return .npmrc config file path */ -const getNpmrcPath = function() { +export const getNpmrcPath = function () { const dirPath = process.env.USERPROFILE ? process.env.USERPROFILE : process.env.HOME; + // TODO: Handle undefined + // @ts-ignore const configPath = path.join(dirPath, ".npmrc"); return configPath; }; @@ -128,29 +159,38 @@ const getNpmrcPath = function() { * @param {*} registry * @param {*} token */ -const generateNpmrcLines = function(content, registry, token) { +export const generateNpmrcLines = function ( + content: string, + registry: Registry, + token: string +) { let lines = content ? content.split("\n") : []; const quotes = /(\?|=)/.test(token) ? '"' : ""; // get the registry url without http protocal + // TODO: Investigate extra quotes + // @ts-ignore let registryUrl = registry.slice(registry.search(/:\/\//, "") + 1); // add trailing slash if (!registryUrl.endsWith("/")) registryUrl = registryUrl + "/"; - const index = _.findIndex(lines, function(element, index, array) { + const index = _.findIndex(lines, function (element, index, array) { if (element.indexOf(registryUrl + ":_authToken=") !== -1) { // If an entry for the auth token is found, replace it + // TODO: Investigate error + // @ts-ignore array[index] = element.replace( /authToken=.*/, "authToken=" + quotes + token + quotes ); return true; } + return false; }); // If no entry for the auth token is found, add one if (index === -1) { lines.push(registryUrl + ":_authToken=" + quotes + token + quotes); } // Remove empty lines - lines = lines.filter(l => l); + lines = lines.filter((l) => l); return lines; }; @@ -158,7 +198,7 @@ const generateNpmrcLines = function(content, registry, token) { * http protocal validator * @param {*} value */ -const validateRegistry = function(value) { +export const validateRegistry = function (value: Registry): Registry { if (!/http(s?):\/\//.test(value)) throw new Error("The registry address should starts with http(s)://"); return value; @@ -168,13 +208,20 @@ const validateRegistry = function(value) { * Write npm token to Unity * @param {*} param0 */ -const writeUnityToken = async function({ +const writeUnityToken = async function ({ _auth, alwaysAuth, basicAuth, email, registry, - token + token, +}: { + _auth: unknown; + alwaysAuth: boolean; + basicAuth: boolean; + email: string; + registry: Registry; + token: string; }) { // Create config dir if necessary const configDir = await getUpmConfigDir(); @@ -183,21 +230,21 @@ const writeUnityToken = async function({ if (!config.npmAuth) config.npmAuth = {}; // Remove ending slash of registry if (registry.endsWith("/")) registry = registry.replace(/\/$/, ""); + + // TODO: Investigate ts warnings // Update config file + // @ts-ignore config["npmAuth"][registry] = { email, - alwaysAuth + alwaysAuth, }; - if (basicAuth) config["npmAuth"][registry]._auth = _auth; - else config["npmAuth"][registry].token = token; + if (basicAuth) { + // @ts-ignore + config["npmAuth"][registry]._auth = _auth; + } else { + // @ts-ignore + config["npmAuth"][registry].token = token; + } // Write config file await saveUpmConfig(config, configDir); }; - -module.exports = { - generateNpmrcLines, - getNpmrcPath, - login, - npmLogin, - validateRegistry -}; diff --git a/lib/cmd-remove.js b/lib/cmd-remove.ts similarity index 78% rename from lib/cmd-remove.js rename to lib/cmd-remove.ts index 451bbebf..ac1372bb 100644 --- a/lib/cmd-remove.js +++ b/lib/cmd-remove.ts @@ -1,13 +1,15 @@ -const { log } = require("./logger"); -const { - env, - loadManifest, - parseEnv, - parseName, - saveManifest -} = require("./core"); +import log from "./logger"; +import { env, loadManifest, parseEnv, parseName, saveManifest } from "./core"; +import { GlobalOptions, Pkg, ScopedRegistry } from "./types"; -const remove = async function(pkgs, options) { +export type RemoveOptions = { + _global: GlobalOptions; +}; + +export const remove = async function ( + pkgs: Pkg[] | Pkg, + options: RemoveOptions +) { if (!Array.isArray(pkgs)) pkgs = [pkgs]; // parse env const envOk = await parseEnv(options, { checkPath: true }); @@ -16,8 +18,8 @@ const remove = async function(pkgs, options) { const results = []; for (const pkg of pkgs) results.push(await _remove(pkg)); const result = { - code: results.filter(x => x.code != 0).length > 0 ? 1 : 0, - dirty: results.filter(x => x.dirty).length > 0 + code: results.filter((x) => x.code != 0).length > 0 ? 1 : 0, + dirty: results.filter((x) => x.dirty).length > 0, }; // print manifest notice if (result.dirty) @@ -25,7 +27,7 @@ const remove = async function(pkgs, options) { return result.code; }; -const _remove = async function(pkg) { +const _remove = async function (pkg: Pkg) { // dirty flag let dirty = false; // parse name @@ -50,7 +52,7 @@ const _remove = async function(pkg) { } // remove from scopedRegistries if (manifest.scopedRegistries) { - const filterEntry = x => { + const filterEntry = (x: ScopedRegistry) => { let url = x.url || ""; if (url.endsWith("/")) url = url.slice(0, -1); return url == env.registry; @@ -78,5 +80,3 @@ const _remove = async function(pkg) { } return { code: 0, dirty }; }; - -module.exports = remove; diff --git a/lib/cmd-search.js b/lib/cmd-search.ts similarity index 54% rename from lib/cmd-search.js rename to lib/cmd-search.ts index 6dde44a9..ec3a09ad 100644 --- a/lib/cmd-search.js +++ b/lib/cmd-search.ts @@ -1,34 +1,58 @@ -const npmSearch = require("libnpmsearch"); -const npmFetch = require("npm-registry-fetch"); -const Table = require("cli-table"); +import npmSearch from "libnpmsearch"; +import npmFetch from "npm-registry-fetch"; +import Table from "cli-table"; +import log from "./logger"; -const { log } = require("./logger"); -const { - env, - getLatestVersion, - getNpmFetchOptions, - parseEnv -} = require("./core"); -const { isConnectionError, is404Error } = require("./error-handler"); +import { env, getLatestVersion, getNpmFetchOptions, parseEnv } from "./core"; -const searchEndpoint = async function (keyword, registry) { +import { is404Error } from "./error-handler"; +import { + GlobalOptions, + PkgInfo, + PkgName, + PkgVersionName, + Registry, +} from "./types"; + +type TableRow = [PkgName, PkgVersionName, string, ""]; + +export type SearchOptions = { + _global: GlobalOptions; +}; + +const searchEndpoint = async function ( + keyword: string, + registry?: Registry +): Promise { if (!registry) registry = env.registry; try { const results = await npmSearch(keyword, getNpmFetchOptions()); + // TODO: This should be converted to a string + // @ts-ignore log.verbose("npmsearch", results); + // TODO: Fix type error + // @ts-ignore return results.map(getTableRow); } catch (err) { - if (!is404Error(err)) log.error("", err.message); + if (!is404Error(err)) { + // TODO: Type check error + // @ts-ignore + log.error("", err.message); + } log.warn("", "fast search endpoint is not available, using old search."); } }; -const searchOld = async function (keyword) { +const searchOld = async function ( + keyword: string +): Promise { // all endpoint try { const results = await npmFetch.json("/-/all", getNpmFetchOptions()); + // TODO: This should be converted to a string + // @ts-ignore log.verbose("endpoint.all", results); - let objects = []; + let objects: PkgInfo[] = []; if (results) { if (Array.isArray(results)) { // results is an array of objects @@ -36,20 +60,26 @@ const searchOld = async function (keyword) { } else { // results is an object if ("_updated" in results) delete results["_updated"]; + // TODO: Do better type checking + // @ts-ignore objects = Object.values(results); } } // prepare rows - const rows = objects.map(pkg => { + const rows = objects.map((pkg) => { return getTableRow(pkg); }); // filter keyword const klc = keyword.toLowerCase(); return rows.filter( - row => row.filter(x => x.toLowerCase().includes(klc)).length > 0 + (row) => row.filter((x) => x.toLowerCase().includes(klc)).length > 0 ); } catch (err) { - if (!is404Error(err)) log.error("", err.message); + if (!is404Error(err)) { + // TODO: Type-check error + // @ts-ignore + log.error("", err.message); + } log.warn("", "/-/all endpoint is not available"); } }; @@ -57,24 +87,23 @@ const searchOld = async function (keyword) { const getTable = function () { var table = new Table({ head: ["Name", "Version", "Date"], - colWidths: [42, 20, 12] + colWidths: [42, 20, 12], }); return table; }; -const getTableRow = function (pkg) { +const getTableRow = function (pkg: PkgInfo): TableRow { const name = pkg.name; const version = getLatestVersion(pkg); let date = ""; if (pkg.time && pkg.time.modified) date = pkg.time.modified.split("T")[0]; if (pkg.date) { - date = pkg.date.toISOString().slice(0, 10) + date = pkg.date.toISOString().slice(0, 10); } - const row = [name, version, date, ""]; - return row -} + return [name, version, date, ""]; +}; -module.exports = async function (keyword, options) { +export async function search(keyword: string, options: SearchOptions) { // parse env const envOk = await parseEnv(options, { checkPath: false }); if (!envOk) return 1; @@ -92,8 +121,8 @@ module.exports = async function (keyword, options) { // results.push(...upstreamResults); // } if (results && results.length) { - results.forEach(x => table.push(x.slice(0, -1))); + results.forEach((x) => table.push(x.slice(0, -1))); console.log(table.toString()); } else log.notice("", `No matches found for "${keyword}"`); return 0; -}; +} diff --git a/lib/cmd-view.js b/lib/cmd-view.ts similarity index 83% rename from lib/cmd-view.js rename to lib/cmd-view.ts index bb0a191b..80c98ef7 100644 --- a/lib/cmd-view.js +++ b/lib/cmd-view.ts @@ -1,15 +1,20 @@ -const chalk = require("chalk"); +import chalk from "chalk"; +import log from "./logger"; -const { log } = require("./logger"); -const { +import { env, fetchPackageInfo, getLatestVersion, parseEnv, - parseName -} = require("./core"); + parseName, +} from "./core"; +import { GlobalOptions, Pkg, PkgInfo } from "./types"; -const view = async function(pkg, options) { +export type ViewOptions = { + _global: GlobalOptions; +}; + +export const view = async function (pkg: Pkg, options: ViewOptions) { // parse env const envOk = await parseEnv(options, { checkPath: false }); if (!envOk) return 1; @@ -32,7 +37,7 @@ const view = async function(pkg, options) { return 0; }; -const printInfo = function(pkg) { +const printInfo = function (pkg: PkgInfo) { const versionCount = Object.keys(pkg.versions).length; const ver = getLatestVersion(pkg); const verInfo = pkg.versions[ver]; @@ -45,7 +50,7 @@ const printInfo = function(pkg) { const dependencies = verInfo.dependencies; const latest = pkg["dist-tags"].latest; let time = pkg.time.modified; - if (!time && latest in pkg.time) time = pkg.time[latest]; + if (!time && latest && latest in pkg.time) time = pkg.time[latest]; console.log(); console.log( @@ -78,7 +83,7 @@ const printInfo = function(pkg) { console.log("dependencies"); Object.keys(dependencies) .sort() - .forEach(n => console.log(chalk.yellow(n) + ` ${dependencies[n]}`)); + .forEach((n) => console.log(chalk.yellow(n) + ` ${dependencies[n]}`)); } console.log(); @@ -93,5 +98,3 @@ const printInfo = function(pkg) { console.log(" " + chalk.greenBright(version)); } }; - -module.exports = view; diff --git a/lib/core.js b/lib/core.ts similarity index 71% rename from lib/core.js rename to lib/core.ts index 71861077..79159fbc 100644 --- a/lib/core.js +++ b/lib/core.ts @@ -1,24 +1,41 @@ -const fs = require("fs"); -const os = require("os"); -const path = require("path"); -const url = require("url"); +import fs from "fs"; +import path from "path"; +import url from "url"; +import _ from "lodash"; +import chalk from "chalk"; +// @ts-ignore +import mkdirp from "mkdirp"; +import net from "node:net"; +import isWsl from "is-wsl"; +import TOML from "@iarna/toml"; +import yaml from "yaml"; +import execute from "./utils/process"; +import { getNpmClient } from "./client"; +import log from "./logger"; +import { + Dependency, + Env, + GlobalOptions, + NameVersionPair, + NpmFetchOptions, + Pkg, + PkgInfo, + PkgManifest, + PkgName, + PkgVersionName, + Registry, + SemanticVersion, + UPMConfig, +} from "./types"; -const _ = require("lodash"); -const chalk = require("chalk"); -const mkdirp = require("mkdirp"); -const net = require('node:net'); -const isWsl = require("is-wsl"); -const TOML = require("@iarna/toml"); -const yaml = require("yaml"); - -const { execute } = require("./utils/process"); -const { getNpmClient } = require("./client"); -const { log } = require("./logger"); - -const env = {}; +// @ts-ignore +export const env: Env = {}; // Parse env -const parseEnv = async function(options, { checkPath }) { +export const parseEnv = async function ( + options: { _global: GlobalOptions } & Record, + { checkPath }: { checkPath: unknown } +) { // set defaults env.registry = "https://package.openupm.com"; env.namespace = "com.openupm"; @@ -60,14 +77,10 @@ const parseEnv = async function(options, { checkPath }) { registry = "http://" + registry; if (registry.endsWith("/")) registry = registry.slice(0, -1); env.registry = registry; - const hostname = url.parse(registry).hostname; + // TODO: Check hostname for null + const hostname = url.parse(registry).hostname as string; if (net.isIP(hostname)) env.namespace = hostname; - else - env.namespace = hostname - .split(".") - .reverse() - .slice(0, 2) - .join("."); + else env.namespace = hostname.split(".").reverse().slice(0, 2).join("."); } // auth if (options._global.systemUser) env.systemUser = true; @@ -78,12 +91,14 @@ const parseEnv = async function(options, { checkPath }) { if (env.npmAuth) { for (const reg in env.npmAuth) { const regAuth = env.npmAuth[reg]; - if (regAuth.token) { + if ("token" in regAuth) { env.auth[reg] = { token: regAuth.token, - alwaysAuth: regAuth.alwaysAuth || false + alwaysAuth: regAuth.alwaysAuth || false, }; - } else if (regAuth._auth) { + } else if ("_auth" in regAuth) { + // NOTE: We can rule out undefined because of the if + // @ts-ignore const buf = Buffer.from(regAuth._auth, "base64"); const text = buf.toString("utf-8"); const [username, password] = text.split(":", 2); @@ -91,13 +106,15 @@ const parseEnv = async function(options, { checkPath }) { username, password: Buffer.from(password).toString("base64"), email: regAuth.email, - alwaysAuth: regAuth.alwaysAuth || false + alwaysAuth: regAuth.alwaysAuth || false, }; } else { log.warn( "env.auth", `failed to parse auth info for ${reg} in .upmconfig.toml: missing token or _auth fields` ); + // TODO: Convert to string + // @ts-ignore log.warn("env.auth", regAuth); } } @@ -145,19 +162,24 @@ const parseEnv = async function(options, { checkPath }) { }; // Parse name to {name, version} -const parseName = function(pkg) { +export const parseName = function (pkg: Pkg): { + name: PkgName; + version: PkgVersionName; +} { const segs = pkg.split("@"); const name = segs[0]; const version = segs.length > 1 ? segs.slice(1, segs.length).join("@") : undefined; + // TODO: Handle version undefined + // @ts-ignore return { name, version }; }; // Get npm fetch options -const getNpmFetchOptions = function() { - const opts = { +export const getNpmFetchOptions = function (): NpmFetchOptions { + const opts: NpmFetchOptions = { log, - registry: env.registry + registry: env.registry, }; const auth = env.auth[env.registry]; if (auth) { @@ -171,7 +193,10 @@ const getNpmFetchOptions = function() { }; // Fetch package info json from registry -const fetchPackageInfo = async function(name, registry) { +export const fetchPackageInfo = async function ( + name: PkgName, + registry?: Registry +): Promise { if (!registry) registry = env.registry; const pkgPath = `${registry}/${name}`; const client = getNpmClient(); @@ -193,10 +218,18 @@ const fetchPackageInfo = async function(name, registry) { }, ... ] */ -const fetchPackageDependencies = async function({ name, version, deep }) { +export const fetchPackageDependencies = async function ({ + name, + version, + deep, +}: { + name: PkgName; + version: PkgVersionName; + deep: boolean; +}): Promise<[Dependency[], Dependency[]]> { log.verbose("dependency", `fetch: ${name}@${version} deep=${deep}`); // a list of pending dependency {name, version} - const pendingList = [{ name, version }]; + const pendingList: NameVersionPair[] = [{ name, version }]; // a list of processed dependency {name, version} const processedList = []; // a list of dependency entry exists on the registry @@ -204,32 +237,36 @@ const fetchPackageDependencies = async function({ name, version, deep }) { // a list of dependency entry doesn't exist on the registry const depsInvalid = []; // cached dict: {pkg-name: pkgInfo} - const cachedPacakgeInfoDict = {}; + const cachedPacakgeInfoDict: Record< + PkgVersionName, + { pkgInfo: PkgInfo; upstream: boolean } + > = {}; while (pendingList.length > 0) { - const entry = pendingList.shift(); - if (processedList.find(x => _.isEqual(x, entry)) === undefined) { + // NOTE: Guaranteed defined because of while loop logic + const entry = pendingList.shift() as NameVersionPair; + if (processedList.find((x) => _.isEqual(x, entry)) === undefined) { // add entry to processed list processedList.push(entry); // create valid depedenency structure - const depObj = { + const depObj: Dependency = { ...entry, internal: isInternalPackage(entry.name), upstream: false, self: entry.name == name, - reason: null + reason: null, }; if (!depObj.internal) { // try fetching package info from cache let { pkgInfo, upstream } = _.get(cachedPacakgeInfoDict, entry.name, { pkgInfo: null, - upstream: false + upstream: false, }); - if (pkgInfo) { + if (pkgInfo !== null) { depObj.upstream = upstream; } // try fetching package info from the default registry - if (!pkgInfo) { - pkgInfo = await fetchPackageInfo(entry.name); + if (pkgInfo === null) { + pkgInfo = (await fetchPackageInfo(entry.name)) ?? null; if (pkgInfo) { depObj.upstream = false; cachedPacakgeInfoDict[entry.name] = { pkgInfo, upstream: false }; @@ -237,7 +274,8 @@ const fetchPackageDependencies = async function({ name, version, deep }) { } // try fetching package info from the upstream registry if (!pkgInfo) { - pkgInfo = await fetchPackageInfo(entry.name, env.upstreamRegistry); + pkgInfo = + (await fetchPackageInfo(entry.name, env.upstreamRegistry)) ?? null; if (pkgInfo) { depObj.upstream = true; cachedPacakgeInfoDict[entry.name] = { pkgInfo, upstream: true }; @@ -257,7 +295,7 @@ const fetchPackageDependencies = async function({ name, version, deep }) { depObj.version = entry.version = getLatestVersion(pkgInfo); } // handle version not exist - if (!versions.find(x => x == entry.version)) { + if (!versions.find((x) => x == entry.version)) { log.warn( "404", `package ${entry.name}@${ @@ -273,12 +311,12 @@ const fetchPackageDependencies = async function({ name, version, deep }) { } // add dependencies to pending list if (depObj.self || deep) { - const deps = _.toPairs( + const deps: NameVersionPair[] = _.toPairs( pkgInfo.versions[entry.version]["dependencies"] - ).map(x => { + ).map((x: [PkgName, PkgVersionName]): NameVersionPair => { return { name: x[0], version: x[1] }; }); - deps.forEach(x => pendingList.push(x)); + deps.forEach((x) => pendingList.push(x)); } } depsValid.push(depObj); @@ -294,23 +332,30 @@ const fetchPackageDependencies = async function({ name, version, deep }) { }; // Get latest version from package info -const getLatestVersion = function(pkgInfo) { +// @ts-ignore +export const getLatestVersion = function (pkgInfo: PkgInfo): PkgVersionName { if (pkgInfo["dist-tags"] && pkgInfo["dist-tags"]["latest"]) return pkgInfo["dist-tags"]["latest"]; - else if (pkgInfo.versions) + else if (pkgInfo.versions) { + // @ts-ignore + // TODO: Handle undefined return Object.keys(pkgInfo.versions).find( - key => pkgInfo.versions[key] == "latest" + // TODO: Something is wrong here + // @ts-ignore + (key) => pkgInfo.versions[key] == "latest" ); - else if (pkgInfo.version) - return pkgInfo.version + } else if (pkgInfo.version) return pkgInfo.version; + // TODO: Not handling undefined case }; // Load manifest json file -const loadManifest = function() { +export const loadManifest = function (): PkgManifest | null { try { let text = fs.readFileSync(env.manifestPath, { encoding: "utf8" }); return JSON.parse(text); } catch (err) { + // TODO: Type error + // @ts-ignore if (err.code == "ENOENT") log.error("manifest", "file Packages/manifest.json does not exist"); else { @@ -318,6 +363,7 @@ const loadManifest = function() { "manifest", `failed to parse Packages/manifest.json at ${env.manifestPath}` ); + // @ts-ignore log.error("manifest", err.message); } return null; @@ -325,20 +371,22 @@ const loadManifest = function() { }; // Save manifest json file -const saveManifest = function(data) { +export const saveManifest = function (data: PkgManifest) { let json = JSON.stringify(data, null, 2); try { fs.writeFileSync(env.manifestPath, json); return true; } catch (err) { log.error("manifest", "can not write manifest json file"); + // @ts-ignore + // TODO: Type-check error log.error("manifest", err.message); return false; } }; // Get .upmconfig.toml directory -const getUpmConfigDir = async function() { +export const getUpmConfigDir = async function (): Promise { let dirPath = ""; const systemUserSubPath = "Unity/config/ServiceAccounts"; if (env.wsl) { @@ -353,10 +401,12 @@ const getUpmConfigDir = async function() { dirPath = path.join(allUserProfilePath, systemUserSubPath); } else { dirPath = await execute('wslpath "$(wslvar USERPROFILE)"', { - trim: true + trim: true, }); } } else { + // TODO: Handle undefined + // @ts-ignore dirPath = process.env.USERPROFILE ? process.env.USERPROFILE : process.env.HOME; @@ -371,18 +421,25 @@ const getUpmConfigDir = async function() { }; // Load .upmconfig.toml -const loadUpmConfig = async function(configDir) { +export const loadUpmConfig = async function ( + configDir?: string +): Promise { if (configDir === undefined) configDir = await getUpmConfigDir(); const configPath = path.join(configDir, ".upmconfig.toml"); if (fs.existsSync(configPath)) { const content = fs.readFileSync(configPath, "utf8"); const config = TOML.parse(content); - return config; + + // NOTE: We assume correct format + return config as UPMConfig; } }; // Save .upmconfig.toml -const saveUpmConfig = async function(config, configDir) { +export const saveUpmConfig = async function ( + config: UPMConfig, + configDir: string +) { if (configDir === undefined) configDir = await getUpmConfigDir(); mkdirp.sync(configDir); const configPath = path.join(configDir, ".upmconfig.toml"); @@ -392,19 +449,22 @@ const saveUpmConfig = async function(config, configDir) { }; // Compare unity editor version and return -1, 0, or 1. -const compareEditorVersion = function(a, b) { +export const compareEditorVersion = function (a: string, b: string) { const verA = parseEditorVersion(a); const verB = parseEditorVersion(b); - const editorVersionToArray = ver => [ + const editorVersionToArray = (ver: SemanticVersion) => [ ver.major, ver.minor, ver.patch || 0, ver.flagValue || 0, ver.build || 0, ver.locValue || 0, - ver.locBuild || 0 + ver.locBuild || 0, ]; + // TODO: Handle null + // @ts-ignore const arrA = editorVersionToArray(verA); + // @ts-ignore const arrB = editorVersionToArray(verB); for (let i = 0; i < arrA.length; i++) { const valA = arrA[i]; @@ -429,58 +489,61 @@ const compareEditorVersion = function(a, b) { * locValue: 1 * locBuild: 4 */ -const parseEditorVersion = function(version) { +export const parseEditorVersion = function ( + version: string +): SemanticVersion | null { if (!version) return null; - const regex = /^(?\d+)\.(?\d+)(\.(?\d+)((?a|b|f|c)(?\d+)((?c)(?\d+))?)?)?/; + const regex = + /^(?\d+)\.(?\d+)(\.(?\d+)((?a|b|f|c)(?\d+)((?c)(?\d+))?)?)?/; const match = regex.exec(version); if (!match) return null; const groups = match.groups; - const result = { + const result: SemanticVersion = { + // TODO: Check undefined + // @ts-ignore major: parseInt(groups.major), - minor: parseInt(groups.minor) + // @ts-ignore + minor: parseInt(groups.minor), }; + // TODO: Check undefined + // @ts-ignore if (groups.patch) result.patch = parseInt(groups.patch); + // TODO: Check undefined + // @ts-ignore if (groups.flag) { + // TODO: Do type checking + // @ts-ignore result.flag = groups.flag.toLowerCase(); if (result.flag == "a") result.flagValue = 0; if (result.flag == "b") result.flagValue = 1; if (result.flag == "f") result.flagValue = 2; + // TODO: Handle undefined + // @ts-ignore if (groups.build) result.build = parseInt(groups.build); } + + // TODO: Handle undefined + // @ts-ignore if (groups.loc) { + // TODO: Handle undefined + // @ts-ignore result.loc = groups.loc.toLowerCase(); if (result.loc == "c") result.locValue = 1; + // TODO: Handle undefined + // @ts-ignore if (groups.locBuild) result.locBuild = parseInt(groups.locBuild); } return result; }; // Detect if the given package name is an internal package -const isInternalPackage = function(name) { +export const isInternalPackage = function (name: PkgName): boolean { const internals = [ "com.unity.ugui", "com.unity.2d.sprite", "com.unity.2d.tilemap", "com.unity.package-manager-ui", - "com.unity.ugui" + "com.unity.ugui", ]; return /com.unity.modules/i.test(name) || internals.includes(name); }; - -module.exports = { - compareEditorVersion, - env, - fetchPackageDependencies, - fetchPackageInfo, - getLatestVersion, - getNpmFetchOptions, - getUpmConfigDir, - isInternalPackage, - loadManifest, - loadUpmConfig, - parseEnv, - parseName, - parseEditorVersion, - saveManifest, - saveUpmConfig -}; diff --git a/lib/error-handler.js b/lib/error-handler.js deleted file mode 100644 index ae24c716..00000000 --- a/lib/error-handler.js +++ /dev/null @@ -1,13 +0,0 @@ -const isConnectionError = function(err) { - return err.code == "ENOTFOUND"; -}; - -const is404Error = function(err) { - return (err.response && err.response.notFound) || err.message.includes("404"); -}; - -const is503Error = function(err) { - return err.response && err.status == 503; -}; - -module.exports = { isConnectionError, is404Error, is503Error }; diff --git a/lib/error-handler.ts b/lib/error-handler.ts new file mode 100644 index 00000000..e1476d02 --- /dev/null +++ b/lib/error-handler.ts @@ -0,0 +1,15 @@ +// TODO: Use better error types + +export const isConnectionError = function(err: any) { + return err.code == "ENOTFOUND"; +}; + +export const is404Error = function(err: any) { + return (err.response && err.response.notFound) || err.message.includes("404"); +}; + +const is503Error = function(err: any) { + return err.response && err.status == 503; +}; + +export default { isConnectionError, is404Error, is503Error }; diff --git a/lib/logger.js b/lib/logger.js deleted file mode 100644 index 1309641b..00000000 --- a/lib/logger.js +++ /dev/null @@ -1,8 +0,0 @@ -const npmlog = require("npmlog"); - -if (process.env.NODE_ENV == "test") { - npmlog.stream = process.stdout; - npmlog.disableColor(); -} - -module.exports = { log: npmlog }; diff --git a/lib/logger.ts b/lib/logger.ts new file mode 100644 index 00000000..92a13e8e --- /dev/null +++ b/lib/logger.ts @@ -0,0 +1,8 @@ +import npmlog from "npmlog"; + +if (process.env.NODE_ENV == "test") { + npmlog.stream = process.stdout; + npmlog.disableColor(); +} + +export default npmlog; diff --git a/lib/types.ts b/lib/types.ts new file mode 100644 index 00000000..c7624acf --- /dev/null +++ b/lib/types.ts @@ -0,0 +1,129 @@ +import { Logger } from "npmlog"; + +export type PkgName = string; + +export type PkgVersionName = string; + +export type Pkg = `${PkgName}@${PkgVersionName}`; + +export type Region = "us" | "cn"; + +export type Registry = string; + +export type SemanticVersion = { + major: number; + minor: number; + patch?: number; + flag?: "a" | "b" | "f"; + flagValue?: 0 | 1 | 2; + build?: number; + loc?: string; + locValue?: number; + locBuild?: number; +}; + +export type Auth = { + alwaysAuth?: boolean; + _auth?: string; + username?: string; + password?: string; + email?: string; + token?: string; +}; + +export type Env = { + cwd: string; + color: boolean; + systemUser: boolean; + wsl: boolean; + npmAuth?: Record; + auth: Record; + upstream: boolean; + upstreamRegistry: string; + registry: string; + namespace: string; + editorVersion: string | null; + region: Region; + manifestPath: string; +}; + +export type Dist = { + tarball: string; + shasum: string; + integrity: string; +}; + +export type PkgVersion = { + unity: string; + unityRelease: string; + dependencies: Record; + license?: string; + displayName: string; + description?: string; + keywords?: string[]; + homepage: string; + dist?: Dist; +}; + +export type PkgInfo = { + name: PkgName; + versions: Record; + "dist-tags": { latest?: PkgVersionName }; + version?: PkgVersionName; + description?: string; + keywords?: string[]; + time: Record<"created" | "modified" | PkgVersionName, string>; + date?: Date; +}; + +export type NameVersionPair = { + name: PkgName; + version: PkgVersionName; +}; + +export type Dependency = { + name: PkgName; + version: PkgVersionName; + upstream: boolean; + self: boolean; + internal: boolean; + reason: string | null; + resolved?: boolean; +}; + +export type ScopedRegistry = { + name: string; + url: string; + scopes: PkgName[]; +}; + +export type PkgManifest = { + dependencies: Record; + scopedRegistries: ScopedRegistry[]; + testables: string[]; +}; + +export type GlobalOptions = { + registry?: Registry; + verbose: boolean; + color: boolean; + upstream: boolean; + cn: boolean; + systemUser: boolean; + wsl: boolean; + chdir: string; +}; + +export type UPMConfig = { + npmAuth?: Record; +}; + +export type NpmFetchOptions = { + log: Logger; + registry: Registry; + alwaysAuth?: boolean; + email?: string; + password?: string; + token?: string; + username?: string; +}; diff --git a/lib/utils/process.js b/lib/utils/process.js deleted file mode 100644 index f1e91c1c..00000000 --- a/lib/utils/process.js +++ /dev/null @@ -1,35 +0,0 @@ -const childProcess = require("child_process"); - -/** - * @param {string} command A shell command to execute - * @return {Promise} A promise that resolve to the output of the shell command, or an error - * @example const output = await execute("ls -alh"); - */ -function execute(command, { trim }) { - /** - * @param {Function} resolve A function that resolves the promise - * @param {Function} reject A function that fails the promise - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise - */ - return new Promise(function(resolve, reject) { - /** - * @param {Error} error An error triggered during the execution of the childProcess.exec command - * @param {string|Buffer} stdout The result of the shell command execution - * @param {string|Buffer} stderr The error resulting of the shell command execution - * @see https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback - */ - childProcess.exec(command, function(error, stdout, stderr) { - if (error) { - reject(); - return; - } - if (stderr) { - reject(stderr); - return; - } - resolve(trim ? stdout.trim() : stdout); - }); - }); -} - -module.exports = { execute }; diff --git a/lib/utils/process.ts b/lib/utils/process.ts new file mode 100644 index 00000000..c6212f07 --- /dev/null +++ b/lib/utils/process.ts @@ -0,0 +1,34 @@ +import childProcess from "child_process"; + +/** + * @param command A shell command to execute + * @return A promise that resolve to the output of the shell command, or an error + * @example const output = await execute("ls -alh"); + */ +export default function execute(command: string, {trim}: { trim: boolean }): Promise { + /** + * @param {Function} resolve A function that resolves the promise + * @param {Function} reject A function that fails the promise + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise + */ + return new Promise(function (resolve, reject) { + /** + * @param {Error} error An error triggered during the execution of the childProcess.exec command + * @param {string|Buffer} stdout The result of the shell command execution + * @param {string|Buffer} stderr The error resulting of the shell command execution + * @see https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback + */ + childProcess.exec(command, function (error, stdout, stderr) { + if (error) { + reject(); + return; + } + if (stderr) { + reject(stderr); + return; + } + resolve(trim ? stdout.trim() : stdout); + }); + }); +} + diff --git a/package-lock.json b/package-lock.json index 8e0a9d41..73052625 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,14 @@ "@babel/eslint-parser": "^7.17.0", "@semantic-release/changelog": "^6.0.1", "@semantic-release/git": "^10.0.1", + "@types/cli-table": "^0.3.2", + "@types/libnpmsearch": "^2.0.4", + "@types/lodash": "^4.14.199", "@types/node": "^20.8.6", + "@types/npmlog": "^4.1.4", + "@types/pkginfo": "^0.4.1", + "@types/promptly": "^3.0.3", + "@types/update-notifier": "^6.0.5", "cross-env": "^7.0.3", "eslint": "^8.15.0", "eslint-config-prettier": "^8.5.0", @@ -45,7 +52,7 @@ "mocha": "^10.0.0", "nock": "^13.2.4", "prettier": "^2.6.2", - "semantic-release": "^19.0.2", + "semantic-release": "^19.0.3", "should": "^13.2.3", "test-console": "^2.0.0", "typescript": "^5.2.2" @@ -1024,6 +1031,34 @@ "node": ">= 10" } }, + "node_modules/@types/cli-table": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@types/cli-table/-/cli-table-0.3.2.tgz", + "integrity": "sha512-yEwKAYmZsgb59xHtNRXaQAloxrm5xr8CQcrYerYlPK+3nwhPk1VC3QFwuiCd/jVWFu2hm4uFiiWDCJQSKhkROQ==", + "dev": true + }, + "node_modules/@types/configstore": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-GUvNiia85zTDDIx0iPrtF3pI8dwrQkfuokEqxqPDE55qxH0U5SZz4awVZjiJLWN2ZZRkXCUqgsMUbygXY+kytA==", + "dev": true + }, + "node_modules/@types/libnpmsearch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/libnpmsearch/-/libnpmsearch-2.0.4.tgz", + "integrity": "sha512-2qlwrkVckDG+0AcMxr41hURNNZCJUhJ74/hkMjaW4/z5eT2zRYlTaSdUIjPnQYH2YTM0SSa1qKTcpO9g+zzlgw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/npm-registry-fetch": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.14.199", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.199.tgz", + "integrity": "sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==", + "dev": true + }, "node_modules/@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", @@ -1039,24 +1074,274 @@ "undici-types": "~5.25.1" } }, + "node_modules/@types/node-fetch": { + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.6.tgz", + "integrity": "sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, + "node_modules/@types/npm-package-arg": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@types/npm-package-arg/-/npm-package-arg-6.1.2.tgz", + "integrity": "sha512-K7TdZq7dTZKKgxaFGLR6VPAeNMDM7GwTELlVNyzQ0KKc6Du3+SYYRXFNEDrsCptpEpMjMNKVlb/5/ZNS/MeHjw==", + "dev": true + }, + "node_modules/@types/npm-registry-fetch": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@types/npm-registry-fetch/-/npm-registry-fetch-8.0.5.tgz", + "integrity": "sha512-mAyQmKTF/4dhXTeSicltEtMO+Vj/LEUoBkMgDn9tS2fGp8IsrZPkYv2GH0KKBcbFLXUq67wuzYwl0DCZGeRcpw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/node-fetch": "*", + "@types/npm-package-arg": "*", + "@types/npmlog": "*", + "@types/ssri": "*" + } + }, + "node_modules/@types/npmlog": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.4.tgz", + "integrity": "sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==", + "dev": true + }, "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "node_modules/@types/pkginfo": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/pkginfo/-/pkginfo-0.4.1.tgz", + "integrity": "sha512-zdrklc4j/o5Nlp/O2JMn2t2lzVaPHeDUV4XD27PAJFqOnEP9dhWGEbsOucp9i4W02p4OtrzL7Up5fZ+ZzyKuKg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/promptly": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/promptly/-/promptly-3.0.3.tgz", + "integrity": "sha512-eM4RvsPy0cT37wJHTcOWvemIyPzBoSKEATp2OO4ptKeSrcNjMwGpDsUSBuBHuleC/datJW7A6NUlBAZsZGJmpA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "node_modules/@types/ssri": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@types/ssri/-/ssri-7.1.2.tgz", + "integrity": "sha512-Mbo/NaBiZlXNlOFTLK+PXeVEzKFxi+ZVELuzmk4VxdRz6aqKpmP9bhcNqsIB2c/s78355WBHwUCGYhQDydcfEg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/update-notifier": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/@types/update-notifier/-/update-notifier-6.0.5.tgz", + "integrity": "sha512-uUOhxsJ3edPHu06r3k4I2yJ4eoyqBt+53ra9+caXEx0ruoPwqNHTlkq75CUvI4yWsrCA5+31tih+opunLCYnXw==", + "dev": true, + "dependencies": { + "@types/configstore": "*", + "boxen": "^7.0.0" + } + }, + "node_modules/@types/update-notifier/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@types/update-notifier/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@types/update-notifier/node_modules/boxen": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", + "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^7.0.1", + "chalk": "^5.2.0", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/update-notifier/node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/update-notifier/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@types/update-notifier/node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/update-notifier/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@types/update-notifier/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/update-notifier/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@types/update-notifier/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/update-notifier/node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dev": true, + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/update-notifier/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -2406,6 +2691,12 @@ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==" }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -10534,6 +10825,34 @@ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" }, + "@types/cli-table": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@types/cli-table/-/cli-table-0.3.2.tgz", + "integrity": "sha512-yEwKAYmZsgb59xHtNRXaQAloxrm5xr8CQcrYerYlPK+3nwhPk1VC3QFwuiCd/jVWFu2hm4uFiiWDCJQSKhkROQ==", + "dev": true + }, + "@types/configstore": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-GUvNiia85zTDDIx0iPrtF3pI8dwrQkfuokEqxqPDE55qxH0U5SZz4awVZjiJLWN2ZZRkXCUqgsMUbygXY+kytA==", + "dev": true + }, + "@types/libnpmsearch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/libnpmsearch/-/libnpmsearch-2.0.4.tgz", + "integrity": "sha512-2qlwrkVckDG+0AcMxr41hURNNZCJUhJ74/hkMjaW4/z5eT2zRYlTaSdUIjPnQYH2YTM0SSa1qKTcpO9g+zzlgw==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/npm-registry-fetch": "*" + } + }, + "@types/lodash": { + "version": "4.14.199", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.199.tgz", + "integrity": "sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==", + "dev": true + }, "@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", @@ -10549,24 +10868,209 @@ "undici-types": "~5.25.1" } }, + "@types/node-fetch": { + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.6.tgz", + "integrity": "sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^4.0.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, + "@types/npm-package-arg": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@types/npm-package-arg/-/npm-package-arg-6.1.2.tgz", + "integrity": "sha512-K7TdZq7dTZKKgxaFGLR6VPAeNMDM7GwTELlVNyzQ0KKc6Du3+SYYRXFNEDrsCptpEpMjMNKVlb/5/ZNS/MeHjw==", + "dev": true + }, + "@types/npm-registry-fetch": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@types/npm-registry-fetch/-/npm-registry-fetch-8.0.5.tgz", + "integrity": "sha512-mAyQmKTF/4dhXTeSicltEtMO+Vj/LEUoBkMgDn9tS2fGp8IsrZPkYv2GH0KKBcbFLXUq67wuzYwl0DCZGeRcpw==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/node-fetch": "*", + "@types/npm-package-arg": "*", + "@types/npmlog": "*", + "@types/ssri": "*" + } + }, + "@types/npmlog": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.4.tgz", + "integrity": "sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==", + "dev": true + }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "@types/pkginfo": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/pkginfo/-/pkginfo-0.4.1.tgz", + "integrity": "sha512-zdrklc4j/o5Nlp/O2JMn2t2lzVaPHeDUV4XD27PAJFqOnEP9dhWGEbsOucp9i4W02p4OtrzL7Up5fZ+ZzyKuKg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/promptly": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/promptly/-/promptly-3.0.3.tgz", + "integrity": "sha512-eM4RvsPy0cT37wJHTcOWvemIyPzBoSKEATp2OO4ptKeSrcNjMwGpDsUSBuBHuleC/datJW7A6NUlBAZsZGJmpA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "@types/ssri": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@types/ssri/-/ssri-7.1.2.tgz", + "integrity": "sha512-Mbo/NaBiZlXNlOFTLK+PXeVEzKFxi+ZVELuzmk4VxdRz6aqKpmP9bhcNqsIB2c/s78355WBHwUCGYhQDydcfEg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/update-notifier": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/@types/update-notifier/-/update-notifier-6.0.5.tgz", + "integrity": "sha512-uUOhxsJ3edPHu06r3k4I2yJ4eoyqBt+53ra9+caXEx0ruoPwqNHTlkq75CUvI4yWsrCA5+31tih+opunLCYnXw==", + "dev": true, + "requires": { + "@types/configstore": "*", + "boxen": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "boxen": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", + "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", + "dev": true, + "requires": { + "ansi-align": "^3.0.1", + "camelcase": "^7.0.1", + "chalk": "^5.2.0", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.1.0" + } + }, + "camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "dev": true + }, + "chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true + }, + "cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true + }, + "widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dev": true, + "requires": { + "string-width": "^5.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -11591,6 +12095,12 @@ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==" }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", diff --git a/package.json b/package.json index 4399afa0..83471633 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "main": "index.js", "scripts": { - "test": "cross-env NODE_ENV=test mocha", + "test": "tsc && cross-env NODE_ENV=test mocha", "semantic-release": "semantic-release" }, "bin": { @@ -35,7 +35,14 @@ "@babel/eslint-parser": "^7.17.0", "@semantic-release/changelog": "^6.0.1", "@semantic-release/git": "^10.0.1", + "@types/cli-table": "^0.3.2", + "@types/libnpmsearch": "^2.0.4", + "@types/lodash": "^4.14.199", "@types/node": "^20.8.6", + "@types/npmlog": "^4.1.4", + "@types/pkginfo": "^0.4.1", + "@types/promptly": "^3.0.3", + "@types/update-notifier": "^6.0.5", "cross-env": "^7.0.3", "eslint": "^8.15.0", "eslint-config-prettier": "^8.5.0", diff --git a/test/test-cmd-add.js b/test/test-cmd-add.js index b0f14844..1f2e0267 100644 --- a/test/test-cmd-add.js +++ b/test/test-cmd-add.js @@ -4,8 +4,8 @@ const assert = require("assert"); const nock = require("nock"); const should = require("should"); -const { parseEnv, loadManifest } = require("../lib/core"); -const add = require("../lib/cmd-add"); +const { parseEnv, loadManifest } = require("../build/lib/core"); +const { add } = require("../build/lib/cmd-add"); const { getWorkDir, createWorkDir, @@ -13,41 +13,41 @@ const { getInspects, getOutputs, nockUp, - nockDown + nockDown, } = require("./utils"); -describe("cmd-add.js", function() { +describe("cmd-add.ts", function () { const options = { _global: { registry: "http://example.com", upstream: false, - chdir: getWorkDir("test-openupm-cli") - } + chdir: getWorkDir("test-openupm-cli"), + }, }; const upstreamOptions = { _global: { registry: "http://example.com", upstream: true, - chdir: getWorkDir("test-openupm-cli") - } + chdir: getWorkDir("test-openupm-cli"), + }, }; const testableOptions = { _global: { registry: "http://example.com", upstream: false, - chdir: getWorkDir("test-openupm-cli") + chdir: getWorkDir("test-openupm-cli"), }, - test: true + test: true, }; const forceOptions = { _global: { registry: "http://example.com", upstream: false, - chdir: getWorkDir("test-openupm-cli") + chdir: getWorkDir("test-openupm-cli"), }, - force: true + force: true, }; - describe("add", function() { + describe("add", function () { let stdoutInspect = null; let stderrInspect = null; const remotePkgInfoA = { @@ -56,17 +56,17 @@ describe("cmd-add.js", function() { "0.1.0": { name: "com.base.package-a", version: "0.1.0", - dependencies: {} + dependencies: {}, }, "1.0.0": { name: "com.base.package-a", version: "1.0.0", - dependencies: {} - } + dependencies: {}, + }, }, "dist-tags": { - latest: "1.0.0" - } + latest: "1.0.0", + }, }; const remotePkgInfoB = { name: "com.base.package-b", @@ -74,12 +74,12 @@ describe("cmd-add.js", function() { "1.0.0": { name: "com.base.package-b", version: "1.0.0", - dependencies: {} - } + dependencies: {}, + }, }, "dist-tags": { - latest: "1.0.0" - } + latest: "1.0.0", + }, }; const remotePkgInfoC = { name: "com.base.package-c", @@ -89,13 +89,13 @@ describe("cmd-add.js", function() { version: "1.0.0", dependencies: { "com.base.package-d": "1.0.0", - "com.unity.modules.x": "1.0.0" - } - } + "com.unity.modules.x": "1.0.0", + }, + }, }, "dist-tags": { - latest: "1.0.0" - } + latest: "1.0.0", + }, }; const remotePkgInfoD = { name: "com.base.package-d", @@ -104,13 +104,13 @@ describe("cmd-add.js", function() { name: "com.base.package-d", version: "1.0.0", dependencies: { - "com.upstream.package-up": "1.0.0" - } - } + "com.upstream.package-up": "1.0.0", + }, + }, }, "dist-tags": { - latest: "1.0.0" - } + latest: "1.0.0", + }, }; const remotePkgInfoWithLowerEditorVersion = { name: "com.base.package-with-lower-editor-version", @@ -119,12 +119,12 @@ describe("cmd-add.js", function() { name: "com.base.package-with-lower-editor-version", version: "1.0.0", unity: "2019.1", - unityRelease: "0b1" - } + unityRelease: "0b1", + }, }, "dist-tags": { - latest: "1.0.0" - } + latest: "1.0.0", + }, }; const remotePkgInfoWithHigherEditorVersion = { name: "com.base.package-with-higher-editor-version", @@ -132,12 +132,12 @@ describe("cmd-add.js", function() { "1.0.0": { name: "com.base.package-with-higher-editor-version", version: "1.0.0", - unity: "2020.2" - } + unity: "2020.2", + }, }, "dist-tags": { - latest: "1.0.0" - } + latest: "1.0.0", + }, }; const remotePkgInfoWithWrongEditorVersion = { name: "com.base.package-with-wrong-editor-version", @@ -145,12 +145,12 @@ describe("cmd-add.js", function() { "1.0.0": { name: "com.base.package-with-wrong-editor-version", version: "1.0.0", - unity: "2020" - } + unity: "2020", + }, }, "dist-tags": { - latest: "1.0.0" - } + latest: "1.0.0", + }, }; const remotePkgInfoUp = { name: "com.upstream.package-up", @@ -158,76 +158,76 @@ describe("cmd-add.js", function() { "1.0.0": { name: "com.upstream.package-up", version: "1.0.0", - dependencies: {} - } + dependencies: {}, + }, }, "dist-tags": { - latest: "1.0.0" - } + latest: "1.0.0", + }, }; const defaultManifest = { - dependencies: {} + dependencies: {}, }; const expectedManifestA = { dependencies: { - "com.base.package-a": "1.0.0" + "com.base.package-a": "1.0.0", }, scopedRegistries: [ { name: "example.com", scopes: ["com.base.package-a", "com.example"], - url: "http://example.com" - } - ] + url: "http://example.com", + }, + ], }; const expectedManifestAB = { dependencies: { "com.base.package-a": "1.0.0", - "com.base.package-b": "1.0.0" + "com.base.package-b": "1.0.0", }, scopedRegistries: [ { name: "example.com", scopes: ["com.base.package-a", "com.base.package-b", "com.example"], - url: "http://example.com" - } - ] + url: "http://example.com", + }, + ], }; const expectedManifestC = { dependencies: { - "com.base.package-c": "1.0.0" + "com.base.package-c": "1.0.0", }, scopedRegistries: [ { name: "example.com", scopes: ["com.base.package-c", "com.base.package-d", "com.example"], - url: "http://example.com" - } - ] + url: "http://example.com", + }, + ], }; const expectedManifestUpstream = { dependencies: { - "com.upstream.package-up": "1.0.0" - } + "com.upstream.package-up": "1.0.0", + }, }; const expectedManifestTestable = { dependencies: { - "com.base.package-a": "1.0.0" + "com.base.package-a": "1.0.0", }, scopedRegistries: [ { name: "example.com", scopes: ["com.base.package-a", "com.example"], - url: "http://example.com" - } + url: "http://example.com", + }, ], - testables: ["com.base.package-a"] + testables: ["com.base.package-a"], }; - beforeEach(function() { + beforeEach(function () { removeWorkDir("test-openupm-cli"); createWorkDir("test-openupm-cli", { manifest: true, - editorVersion: "2019.2.13f1" + editorVersion: "2019.2.13f1", }); nockUp(); nock("http://example.com") @@ -250,24 +250,21 @@ describe("cmd-add.js", function() { .persist() .get("/com.base.package-with-lower-editor-version") .reply(200, remotePkgInfoWithLowerEditorVersion, { - "Content-Type": "application/json" + "Content-Type": "application/json", }); nock("http://example.com") .persist() .get("/com.base.package-with-higher-editor-version") .reply(200, remotePkgInfoWithHigherEditorVersion, { - "Content-Type": "application/json" + "Content-Type": "application/json", }); nock("http://example.com") .persist() .get("/com.base.package-with-wrong-editor-version") .reply(200, remotePkgInfoWithWrongEditorVersion, { - "Content-Type": "application/json" + "Content-Type": "application/json", }); - nock("http://example.com") - .persist() - .get("/pkg-not-exist") - .reply(404); + nock("http://example.com").persist().get("/pkg-not-exist").reply(404); nock("http://example.com") .persist() .get("/com.upstream.package-up") @@ -276,7 +273,7 @@ describe("cmd-add.js", function() { .persist() .get("/com.upstream.package-up") .reply(200, remotePkgInfoUp, { - "Content-Type": "application/json" + "Content-Type": "application/json", }); nock("https://packages.unity.com") .persist() @@ -284,13 +281,13 @@ describe("cmd-add.js", function() { .reply(404); [stdoutInspect, stderrInspect] = getInspects(); }); - afterEach(function() { + afterEach(function () { removeWorkDir("test-openupm-cli"); nockDown(); stdoutInspect.restore(); stderrInspect.restore(); }); - it("add pkg", async function() { + it("add pkg", async function () { const retCode = await add("com.base.package-a", options); retCode.should.equal(0); const manifest = await loadManifest(); @@ -299,7 +296,7 @@ describe("cmd-add.js", function() { stdout.includes("added").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg@1.0.0", async function() { + it("add pkg@1.0.0", async function () { const retCode = await add("com.base.package-a@1.0.0", options); retCode.should.equal(0); const manifest = await loadManifest(); @@ -308,7 +305,7 @@ describe("cmd-add.js", function() { stdout.includes("added").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg@latest", async function() { + it("add pkg@latest", async function () { const retCode = await add("com.base.package-a@latest", options); retCode.should.equal(0); const manifest = await loadManifest(); @@ -317,7 +314,7 @@ describe("cmd-add.js", function() { stdout.includes("added").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg@0.1.0 then pkg@1.0.0", async function() { + it("add pkg@0.1.0 then pkg@1.0.0", async function () { const retCode1 = await add("com.base.package-a@0.1.0", options); retCode1.should.equal(0); const retCode2 = await add("com.base.package-a@1.0.0", options); @@ -328,7 +325,7 @@ describe("cmd-add.js", function() { stdout.includes("modified ").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add exited pkg version", async function() { + it("add exited pkg version", async function () { const retCode1 = await add("com.base.package-a@1.0.0", options); retCode1.should.equal(0); const retCode2 = await add("com.base.package-a@1.0.0", options); @@ -339,7 +336,7 @@ describe("cmd-add.js", function() { stdout.includes("existed ").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg@not-exist-version", async function() { + it("add pkg@not-exist-version", async function () { const retCode = await add("com.base.package-a@2.0.0", options); retCode.should.equal(1); const manifest = await loadManifest(); @@ -348,7 +345,7 @@ describe("cmd-add.js", function() { stdout.includes("version 2.0.0 is not a valid choice").should.be.ok(); stdout.includes("1.0.0").should.be.ok(); }); - it("add pkg@http", async function() { + it("add pkg@http", async function () { const gitUrl = "https://github.com/yo/com.base.package-a"; const retCode = await add("com.base.package-a@" + gitUrl, options); retCode.should.equal(0); @@ -358,7 +355,7 @@ describe("cmd-add.js", function() { stdout.includes("added").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg@git", async function() { + it("add pkg@git", async function () { const gitUrl = "git@github.com:yo/com.base.package-a"; const retCode = await add("com.base.package-a@" + gitUrl, options); retCode.should.equal(0); @@ -368,7 +365,7 @@ describe("cmd-add.js", function() { stdout.includes("added").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg@file", async function() { + it("add pkg@file", async function () { const fileUrl = "file../yo/com.base.package-a"; const retCode = await add("com.base.package-a@" + fileUrl, options); retCode.should.equal(0); @@ -378,7 +375,7 @@ describe("cmd-add.js", function() { stdout.includes("added").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg-not-exist", async function() { + it("add pkg-not-exist", async function () { const retCode = await add("pkg-not-exist", options); retCode.should.equal(1); const manifest = await loadManifest(); @@ -386,7 +383,7 @@ describe("cmd-add.js", function() { const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("package not found").should.be.ok(); }); - it("add more than one pkgs", async function() { + it("add more than one pkgs", async function () { const retCode = await add( ["com.base.package-a", "com.base.package-b"], options @@ -399,7 +396,7 @@ describe("cmd-add.js", function() { stdout.includes("added com.base.package-b").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg from upstream", async function() { + it("add pkg from upstream", async function () { const retCode = await add("com.upstream.package-up", upstreamOptions); retCode.should.equal(0); const manifest = await loadManifest(); @@ -408,7 +405,7 @@ describe("cmd-add.js", function() { stdout.includes("added com.upstream.package-up").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg-not-exist from upstream", async function() { + it("add pkg-not-exist from upstream", async function () { const retCode = await add("pkg-not-exist", upstreamOptions); retCode.should.equal(1); const manifest = await loadManifest(); @@ -416,7 +413,7 @@ describe("cmd-add.js", function() { const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("package not found").should.be.ok(); }); - it("add pkg with nested dependencies", async function() { + it("add pkg with nested dependencies", async function () { const retCode = await add("com.base.package-c@latest", upstreamOptions); retCode.should.equal(0); const manifest = await loadManifest(); @@ -425,7 +422,7 @@ describe("cmd-add.js", function() { stdout.includes("added").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg with tests", async function() { + it("add pkg with tests", async function () { const retCode = await add("com.base.package-a", testableOptions); retCode.should.equal(0); const manifest = await loadManifest(); @@ -434,7 +431,7 @@ describe("cmd-add.js", function() { stdout.includes("added").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg with lower editor version", async function() { + it("add pkg with lower editor version", async function () { const retCode = await add( "com.base.package-with-lower-editor-version", testableOptions @@ -444,7 +441,7 @@ describe("cmd-add.js", function() { stdout.includes("added").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("add pkg with higher editor version", async function() { + it("add pkg with higher editor version", async function () { const retCode = await add( "com.base.package-with-higher-editor-version", testableOptions @@ -453,7 +450,7 @@ describe("cmd-add.js", function() { const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("requires 2020.2 but found 2019.2.13f1").should.be.ok(); }); - it("force add pkg with higher editor version", async function() { + it("force add pkg with higher editor version", async function () { const retCode = await add( "com.base.package-with-higher-editor-version", forceOptions @@ -462,7 +459,7 @@ describe("cmd-add.js", function() { const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("requires 2020.2 but found 2019.2.13f1").should.be.ok(); }); - it("add pkg with wrong editor version", async function() { + it("add pkg with wrong editor version", async function () { const retCode = await add( "com.base.package-with-wrong-editor-version", testableOptions @@ -472,7 +469,7 @@ describe("cmd-add.js", function() { stdout.includes("2020 is not valid").should.be.ok(); console.log(stdout); }); - it("force add pkg with wrong editor version", async function() { + it("force add pkg with wrong editor version", async function () { const retCode = await add( "com.base.package-with-wrong-editor-version", forceOptions diff --git a/test/test-cmd-deps.js b/test/test-cmd-deps.js index 95dd3566..68d1cd0f 100644 --- a/test/test-cmd-deps.js +++ b/test/test-cmd-deps.js @@ -4,8 +4,8 @@ const assert = require("assert"); const nock = require("nock"); const should = require("should"); -const { parseEnv, loadManifest } = require("../lib/core"); -const deps = require("../lib/cmd-deps"); +const { parseEnv, loadManifest } = require("../build/lib/core"); +const { deps } = require("../build/lib/cmd-deps"); const { getWorkDir, createWorkDir, @@ -13,17 +13,17 @@ const { getInspects, getOutputs, nockUp, - nockDown + nockDown, } = require("./utils"); -describe("cmd-deps.js", function() { +describe("cmd-deps.ts", function () { const options = { _global: { registry: "http://example.com", - chdir: getWorkDir("test-openupm-cli") - } + chdir: getWorkDir("test-openupm-cli"), + }, }; - describe("deps", function() { + describe("deps", function () { let stdoutInspect = null; let stderrInspect = null; const remotePkgInfoA = { @@ -33,13 +33,13 @@ describe("cmd-deps.js", function() { name: "com.example.package-a", version: "1.0.0", dependencies: { - "com.example.package-b": "1.0.0" - } - } + "com.example.package-b": "1.0.0", + }, + }, }, "dist-tags": { - latest: "1.0.0" - } + latest: "1.0.0", + }, }; const remotePkgInfoB = { name: "com.example.package-b", @@ -48,13 +48,13 @@ describe("cmd-deps.js", function() { name: "com.example.package-b", version: "1.0.0", dependencies: { - "com.example.package-up": "1.0.0" - } - } + "com.example.package-up": "1.0.0", + }, + }, }, "dist-tags": { - latest: "1.0.0" - } + latest: "1.0.0", + }, }; const remotePkgInfoUp = { name: "com.example.package-up", @@ -62,14 +62,14 @@ describe("cmd-deps.js", function() { "1.0.0": { name: "com.example.package-up", version: "1.0.0", - dependencies: {} - } + dependencies: {}, + }, }, "dist-tags": { - latest: "1.0.0" - } + latest: "1.0.0", + }, }; - beforeEach(function() { + beforeEach(function () { removeWorkDir("test-openupm-cli"); createWorkDir("test-openupm-cli", { manifest: true }); nockUp(); @@ -79,69 +79,63 @@ describe("cmd-deps.js", function() { nock("http://example.com") .get("/com.example.package-b") .reply(200, remotePkgInfoB, { "Content-Type": "application/json" }); - nock("http://example.com") - .get("/pkg-not-exist") - .reply(404); - nock("http://example.com") - .get("/com.example.package-up") - .reply(404); + nock("http://example.com").get("/pkg-not-exist").reply(404); + nock("http://example.com").get("/com.example.package-up").reply(404); nock("https://packages.unity.com") .get("/com.example.package-up") .reply(200, remotePkgInfoUp, { - "Content-Type": "application/json" + "Content-Type": "application/json", }); - nock("https://packages.unity.com") - .get("/pkg-not-exist") - .reply(404); + nock("https://packages.unity.com").get("/pkg-not-exist").reply(404); [stdoutInspect, stderrInspect] = getInspects(); }); - afterEach(function() { + afterEach(function () { removeWorkDir("test-openupm-cli"); nockDown(); stdoutInspect.restore(); stderrInspect.restore(); }); - it("deps pkg", async function() { + it("deps pkg", async function () { const retCode = await deps("com.example.package-a", options); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("com.example.package-b").should.be.ok(); }); - it("deps pkg --deep", async function() { + it("deps pkg --deep", async function () { const retCode = await deps("com.example.package-a", { ...options, - deep: true + deep: true, }); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("com.example.package-b").should.be.ok(); stdout.includes("com.example.package-up").should.be.ok(); }); - it("deps pkg@latest", async function() { + it("deps pkg@latest", async function () { const retCode = await deps("com.example.package-a@latest", options); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("com.example.package-b").should.be.ok(); }); - it("deps pkg@1.0.0", async function() { + it("deps pkg@1.0.0", async function () { const retCode = await deps("com.example.package-a@1.0.0", options); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("com.example.package-b").should.be.ok(); }); - it("deps pkg@not-exist-version", async function() { + it("deps pkg@not-exist-version", async function () { const retCode = await deps("com.example.package-a@2.0.0", options); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("is not a valid choice").should.be.ok(); }); - it("deps pkg-not-exist", async function() { + it("deps pkg-not-exist", async function () { const retCode = await deps("pkg-not-exist", options); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("not found").should.be.ok(); }); - it("deps pkg upstream", async function() { + it("deps pkg upstream", async function () { const retCode = await deps("com.example.package-up", options); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); diff --git a/test/test-cmd-login.js b/test/test-cmd-login.js index b5edab71..bf0d55ac 100644 --- a/test/test-cmd-login.js +++ b/test/test-cmd-login.js @@ -7,9 +7,9 @@ const { validateRegistry, generateNpmrcLines, getNpmrcPath -} = require("../lib/cmd-login"); +} = require("../build/lib/cmd-login"); -describe("cmd-login.js", function() { +describe("cmd-login.ts", function() { describe("validateRegistry", function() { it("should validate http", async function() { validateRegistry("http://registry.npmjs.org/").should.be.ok(); diff --git a/test/test-cmd-remove.js b/test/test-cmd-remove.js index 398b42ec..9f66e7d6 100644 --- a/test/test-cmd-remove.js +++ b/test/test-cmd-remove.js @@ -3,24 +3,24 @@ const assert = require("assert"); const should = require("should"); -const { parseEnv, loadManifest } = require("../lib/core"); -const remove = require("../lib/cmd-remove"); +const { parseEnv, loadManifest } = require("../build/lib/core"); +const { remove } = require("../build/lib/cmd-remove"); const { getInspects, getOutputs, getWorkDir, createWorkDir, - removeWorkDir + removeWorkDir, } = require("./utils"); -describe("cmd-remove.js", function() { - describe("remove", function() { +describe("cmd-remove.ts", function () { + describe("remove", function () { let stdoutInspect = null; let stderrInspect = null; const defaultManifest = { dependencies: { "com.example.package-a": "1.0.0", - "com.example.package-b": "1.0.0" + "com.example.package-b": "1.0.0", }, scopedRegistries: [ { @@ -28,30 +28,30 @@ describe("cmd-remove.js", function() { scopes: [ "com.example", "com.example.package-a", - "com.example.package-b" + "com.example.package-b", ], - url: "http://example.com" - } - ] + url: "http://example.com", + }, + ], }; - beforeEach(function() { + beforeEach(function () { removeWorkDir("test-openupm-cli"); createWorkDir("test-openupm-cli", { - manifest: defaultManifest + manifest: defaultManifest, }); [stdoutInspect, stderrInspect] = getInspects(); }); - afterEach(function() { + afterEach(function () { removeWorkDir("test-openupm-cli"); stdoutInspect.restore(); stderrInspect.restore(); }); - it("remove pkg", async function() { + it("remove pkg", async function () { const options = { _global: { registry: "http://example.com", - chdir: getWorkDir("test-openupm-cli") - } + chdir: getWorkDir("test-openupm-cli"), + }, }; const retCode = await remove("com.example.package-a", options); retCode.should.equal(0); @@ -61,18 +61,18 @@ describe("cmd-remove.js", function() { ).should.be.ok(); manifest.scopedRegistries[0].scopes.should.be.deepEqual([ "com.example", - "com.example.package-b" + "com.example.package-b", ]); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("removed ").should.be.ok(); stdout.includes("open Unity").should.be.ok(); }); - it("remove pkg@1.0.0", async function() { + it("remove pkg@1.0.0", async function () { const options = { _global: { registry: "http://example.com", - chdir: getWorkDir("test-openupm-cli") - } + chdir: getWorkDir("test-openupm-cli"), + }, }; const retCode = await remove("com.example.package-a@1.0.0", options); retCode.should.equal(1); @@ -81,12 +81,12 @@ describe("cmd-remove.js", function() { const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("please replace").should.be.ok(); }); - it("remove pkg-not-exist", async function() { + it("remove pkg-not-exist", async function () { const options = { _global: { registry: "http://example.com", - chdir: getWorkDir("test-openupm-cli") - } + chdir: getWorkDir("test-openupm-cli"), + }, }; const retCode = await remove("pkg-not-exist", options); retCode.should.equal(1); @@ -95,12 +95,12 @@ describe("cmd-remove.js", function() { const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("package not found").should.be.ok(); }); - it("remove more than one pkgs", async function() { + it("remove more than one pkgs", async function () { const options = { _global: { registry: "http://example.com", - chdir: getWorkDir("test-openupm-cli") - } + chdir: getWorkDir("test-openupm-cli"), + }, }; const retCode = await remove( ["com.example.package-a", "com.example.package-b"], diff --git a/test/test-cmd-search.js b/test/test-cmd-search.js index dc7622e0..d9060ded 100644 --- a/test/test-cmd-search.js +++ b/test/test-cmd-search.js @@ -4,7 +4,7 @@ const assert = require("assert"); const nock = require("nock"); const should = require("should"); -const search = require("../lib/cmd-search"); +const { search } = require("../build/lib/cmd-search"); const { getWorkDir, createWorkDir, @@ -12,38 +12,38 @@ const { getInspects, getOutputs, nockUp, - nockDown + nockDown, } = require("./utils"); -describe("cmd-search.js", function() { +describe("cmd-search.ts", function () { let stdoutInspect = null; let stderrInspect = null; const options = { _global: { registry: "http://example.com", upstream: false, - chdir: getWorkDir("test-openupm-cli") - } + chdir: getWorkDir("test-openupm-cli"), + }, }; const upstreamOptions = { _global: { registry: "http://example.com", - chdir: getWorkDir("test-openupm-cli") - } + chdir: getWorkDir("test-openupm-cli"), + }, }; - beforeEach(function() { + beforeEach(function () { removeWorkDir("test-openupm-cli"); createWorkDir("test-openupm-cli", { manifest: true }); removeWorkDir("test-openupm-cli"); createWorkDir("test-openupm-cli", { manifest: true }); [stdoutInspect, stderrInspect] = getInspects(); }); - afterEach(function() { + afterEach(function () { removeWorkDir("test-openupm-cli"); stdoutInspect.restore(); stderrInspect.restore(); }); - describe("search endpoint", function() { + describe("search endpoint", function () { const searchEndpointResult = { objects: [ { @@ -52,16 +52,16 @@ describe("cmd-search.js", function() { scope: "unscoped", "dist-tags": { latest: "1.0.0" }, versions: { - "1.0.0": "latest" + "1.0.0": "latest", }, description: "A demo package", time: { - modified: "2019-10-02T04:02:38.335Z" + modified: "2019-10-02T04:02:38.335Z", }, links: {}, author: { name: "yo", url: "https://github.com/yo" }, publisher: { username: "yo", email: "yo@example.com" }, - maintainers: [{ username: "yo", email: "yo@example.com" }] + maintainers: [{ username: "yo", email: "yo@example.com" }], }, flags: { unstable: true }, score: { @@ -69,37 +69,37 @@ describe("cmd-search.js", function() { detail: { quality: 0.64303646684878, popularity: 0.0034858628087645178, - maintenance: 0.3329285640997383 - } + maintenance: 0.3329285640997383, + }, }, - searchScore: 0.000005798558 - } + searchScore: 0.000005798558, + }, ], total: 1, - time: "Sat Dec 07 2019 04:57:11 GMT+0000 (UTC)" + time: "Sat Dec 07 2019 04:57:11 GMT+0000 (UTC)", }; const searchEndpointEmptyResult = { objects: [], total: 0, - time: "Sat Dec 07 2019 05:07:42 GMT+0000 (UTC)" + time: "Sat Dec 07 2019 05:07:42 GMT+0000 (UTC)", }; - beforeEach(function() { + beforeEach(function () { nockUp(); nock("http://example.com") .get(/-\/v1\/search\?text=package-a/) .reply(200, searchEndpointResult, { - "Content-Type": "application/json" + "Content-Type": "application/json", }); nock("http://example.com") .get(/-\/v1\/search\?text=pkg-not-exist/) .reply(200, searchEndpointEmptyResult, { - "Content-Type": "application/json" + "Content-Type": "application/json", }); }); - afterEach(function() { + afterEach(function () { nockDown(); }); - it("simple", async function() { + it("simple", async function () { const retCode = await search("package-a", options); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); @@ -107,7 +107,7 @@ describe("cmd-search.js", function() { stdout.includes("1.0.0").should.be.ok(); stdout.includes("2019-10-02").should.be.ok(); }); - it("pkg not exist", async function() { + it("pkg not exist", async function () { const retCode = await search("pkg-not-exist", options); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); @@ -115,7 +115,7 @@ describe("cmd-search.js", function() { }); }); - describe("old search", function() { + describe("old search", function () { const allResult = { _updated: 99999, "com.example.package-a": { @@ -126,34 +126,32 @@ describe("cmd-search.js", function() { author: { name: "yo", url: "https://github.com/yo" }, repository: { type: "git", - url: "git+https://github.com/yo/com.example.package-a.git" + url: "git+https://github.com/yo/com.example.package-a.git", }, readmeFilename: "README.md", homepage: "https://github.com/yo/com.example.package-a#readme", bugs: { - url: "https://github.com/yo/com.example.package-a/issues" + url: "https://github.com/yo/com.example.package-a/issues", }, license: "MIT", time: { modified: "2019-10-02T18:22:51.000Z" }, - versions: { "1.0.0": "latest" } - } + versions: { "1.0.0": "latest" }, + }, }; - beforeEach(function() { + beforeEach(function () { nockUp(); nock("http://example.com") .persist() .get(/-\/v1\/search\?text=/) .reply(404); }); - afterEach(function() { + afterEach(function () { nockDown(); }); - it("from remote", async function() { - nock("http://example.com") - .get("/-/all") - .reply(200, allResult, { - "Content-Type": "application/json" - }); + it("from remote", async function () { + nock("http://example.com").get("/-/all").reply(200, allResult, { + "Content-Type": "application/json", + }); const retCode = await search("package-a", options); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); @@ -162,12 +160,10 @@ describe("cmd-search.js", function() { stdout.includes("1.0.0").should.be.ok(); stdout.includes("2019-10-02").should.be.ok(); }); - it("pkg not exist", async function() { - nock("http://example.com") - .get("/-/all") - .reply(200, allResult, { - "Content-Type": "application/json" - }); + it("pkg not exist", async function () { + nock("http://example.com").get("/-/all").reply(200, allResult, { + "Content-Type": "application/json", + }); const retCode = await search("pkg-not-exist", options); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); diff --git a/test/test-cmd-view.js b/test/test-cmd-view.js index 94a463ba..c2bda8e3 100644 --- a/test/test-cmd-view.js +++ b/test/test-cmd-view.js @@ -3,8 +3,8 @@ const assert = require("assert"); const nock = require("nock"); const should = require("should"); -const { parseEnv, loadManifest } = require("../lib/core"); -const view = require("../lib/cmd-view"); +const { parseEnv, loadManifest } = require("../build/lib/core"); +const { view } = require("../build/lib/cmd-view"); const { getWorkDir, createWorkDir, @@ -12,24 +12,24 @@ const { getInspects, getOutputs, nockUp, - nockDown + nockDown, } = require("./utils"); -describe("cmd-view.js", function() { +describe("cmd-view.ts", function () { const options = { _global: { registry: "http://example.com", upstream: false, - chdir: getWorkDir("test-openupm-cli") - } + chdir: getWorkDir("test-openupm-cli"), + }, }; const upstreamOptions = { _global: { registry: "http://example.com", - chdir: getWorkDir("test-openupm-cli") - } + chdir: getWorkDir("test-openupm-cli"), + }, }; - describe("view", function() { + describe("view", function () { let stdoutInspect = null; let stderrInspect = null; const remotePkgInfoA = { @@ -39,7 +39,7 @@ describe("cmd-view.js", function() { name: "com.example.package-a", displayName: "Package A", author: { - name: "batman" + name: "batman", }, version: "1.0.0", unity: "2018.4", @@ -47,7 +47,7 @@ describe("cmd-view.js", function() { keywords: [""], category: "Unity", dependencies: { - "com.example.package-a": "^1.0.0" + "com.example.package-a": "^1.0.0", }, gitHead: "5c141ecfac59c389090a07540f44c8ac5d07a729", readmeFilename: "README.md", @@ -59,24 +59,24 @@ describe("cmd-view.js", function() { "sha512-MAh44bur7HGyfbCXH9WKfaUNS67aRMfO0VAbLkr+jwseb1hJue/I1pKsC7PKksuBYh4oqoo9Jov1cBcvjVgjmA==", shasum: "516957cac4249f95cafab0290335def7d9703db7", tarball: - "https://cdn.example.com/com.example.package-a/com.example.package-a-1.0.0.tgz" + "https://cdn.example.com/com.example.package-a/com.example.package-a-1.0.0.tgz", }, - contributors: [] - } + contributors: [], + }, }, time: { modified: "2019-11-28T18:51:58.123Z", created: "2019-11-28T18:51:58.123Z", - "1.0.0": "2019-11-28T18:51:58.123Z" + "1.0.0": "2019-11-28T18:51:58.123Z", }, users: {}, "dist-tags": { - latest: "1.0.0" + latest: "1.0.0", }, _rev: "3-418f950115c32bd0", _id: "com.example.package-a", readme: "A demo package", - _attachments: {} + _attachments: {}, }; const remotePkgInfoUp = { name: "com.example.package-up", @@ -85,7 +85,7 @@ describe("cmd-view.js", function() { name: "com.example.package-up", displayName: "Package A", author: { - name: "batman" + name: "batman", }, version: "1.0.0", unity: "2018.4", @@ -93,7 +93,7 @@ describe("cmd-view.js", function() { keywords: [""], category: "Unity", dependencies: { - "com.example.package-up": "^1.0.0" + "com.example.package-up": "^1.0.0", }, gitHead: "5c141ecfac59c389090a07540f44c8ac5d07a729", readmeFilename: "README.md", @@ -105,79 +105,73 @@ describe("cmd-view.js", function() { "sha512-MAh44bur7HGyfbCXH9WKfaUNS67aRMfO0VAbLkr+jwseb1hJue/I1pKsC7PKksuBYh4oqoo9Jov1cBcvjVgjmA==", shasum: "516957cac4249f95cafab0290335def7d9703db7", tarball: - "https://cdn.example.com/com.example.package-up/com.example.package-up-1.0.0.tgz" + "https://cdn.example.com/com.example.package-up/com.example.package-up-1.0.0.tgz", }, - contributors: [] - } + contributors: [], + }, }, time: { modified: "2019-11-28T18:51:58.123Z", created: "2019-11-28T18:51:58.123Z", - "1.0.0": "2019-11-28T18:51:58.123Z" + "1.0.0": "2019-11-28T18:51:58.123Z", }, users: {}, "dist-tags": { - latest: "1.0.0" + latest: "1.0.0", }, _rev: "3-418f950115c32bd0", _id: "com.example.package-up", readme: "A demo package", - _attachments: {} + _attachments: {}, }; - beforeEach(function() { + beforeEach(function () { removeWorkDir("test-openupm-cli"); createWorkDir("test-openupm-cli", { manifest: true }); nockUp(); nock("http://example.com") .get("/com.example.package-a") .reply(200, remotePkgInfoA, { "Content-Type": "application/json" }); - nock("http://example.com") - .get("/pkg-not-exist") - .reply(404); - nock("http://example.com") - .get("/com.example.package-up") - .reply(404); + nock("http://example.com").get("/pkg-not-exist").reply(404); + nock("http://example.com").get("/com.example.package-up").reply(404); nock("https://packages.unity.com") .get("/com.example.package-up") .reply(200, remotePkgInfoUp, { - "Content-Type": "application/json" + "Content-Type": "application/json", }); - nock("https://packages.unity.com") - .get("/pkg-not-exist") - .reply(404); + nock("https://packages.unity.com").get("/pkg-not-exist").reply(404); [stdoutInspect, stderrInspect] = getInspects(); }); - afterEach(function() { + afterEach(function () { removeWorkDir("test-openupm-cli"); nockDown(); stdoutInspect.restore(); stderrInspect.restore(); }); - it("view pkg", async function() { + it("view pkg", async function () { const retCode = await view("com.example.package-a", options); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("com.example.package-a@1.0.0").should.be.ok(); }); - it("view pkg@1.0.0", async function() { + it("view pkg@1.0.0", async function () { const retCode = await view("com.example.package-a@1.0.0", options); retCode.should.equal(1); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("please replace").should.be.ok(); }); - it("view pkg-not-exist", async function() { + it("view pkg-not-exist", async function () { const retCode = await view("pkg-not-exist", options); retCode.should.equal(1); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("package not found").should.be.ok(); }); - it("view pkg from upstream", async function() { + it("view pkg from upstream", async function () { const retCode = await view("com.example.package-up", upstreamOptions); retCode.should.equal(0); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); stdout.includes("com.example.package-up@1.0.0").should.be.ok(); }); - it("view pkg-not-exist from upstream", async function() { + it("view pkg-not-exist from upstream", async function () { const retCode = await view("pkg-not-exist", upstreamOptions); retCode.should.equal(1); const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect); diff --git a/test/test-core.js b/test/test-core.js index 0a07393c..bc1fe13b 100644 --- a/test/test-core.js +++ b/test/test-core.js @@ -16,7 +16,7 @@ const { parseName, saveManifest, isInternalPackage -} = require("../lib/core"); +} = require("../build/lib/core"); const { getWorkDir, createWorkDir, @@ -27,7 +27,7 @@ const { nockDown } = require("./utils"); -describe("cmd-core.js", function() { +describe("cmd-core.ts", function() { describe("parseName", function() { it("pkg@version", function() { parseName("pkg@1.0.0").should.deepEqual({ diff --git a/tsconfig.json b/tsconfig.json index 17b19bf6..4f54999c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -41,7 +41,7 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ + "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */