diff --git a/src/cmd-add.ts b/src/cmd-add.ts index 24cf4119..3c2a750f 100644 --- a/src/cmd-add.ts +++ b/src/cmd-add.ts @@ -3,7 +3,7 @@ import url from "url"; import { isPackageUrl } from "./types/package-url"; import { tryGetLatestVersion } from "./types/pkg-info"; import { loadManifest, saveManifest } from "./utils/pkg-manifest-io"; -import { env, parseEnv } from "./utils/env"; +import { parseEnv } from "./utils/env"; import { compareEditorVersion, tryParseEditorVersion, @@ -43,203 +43,195 @@ export const add = async function ( ): Promise { if (!Array.isArray(pkgs)) pkgs = [pkgs]; // parse env - const envOk = await parseEnv(options, { checkPath: true }); - if (!envOk) return 1; - // add - const results = []; - for (const pkg of pkgs) - results.push( - await _add({ pkg, testables: options.test, force: options.force }) - ); - const result: AddResult = { - 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) - log.notice("", "please open Unity project to apply changes"); - return result.code; -}; + const env = await parseEnv(options, true); + if (env === null) return 1; -const _add = async function ({ - pkg, - testables, - force, -}: { - pkg: PackageReference; - testables?: boolean; - force?: boolean; -}): Promise { - // dirty flag - let dirty = false; - // is upstream package flag - let isUpstreamPackage = false; - // parse name - const split = splitPackageReference(pkg); - const name = split[0]; - let version = split[1]; + const addSingle = async function (pkg: PackageReference): Promise { + // dirty flag + let dirty = false; + // is upstream package flag + let isUpstreamPackage = false; + // parse name + const split = splitPackageReference(pkg); + const name = split[0]; + let version = split[1]; - // load manifest - const manifest = loadManifest(); - if (manifest === null) return { code: 1, dirty }; - // packages that added to scope registry - const pkgsInScope: DomainName[] = []; - if (version === undefined || !isPackageUrl(version)) { - // verify name - let pkgInfo = await fetchPackageInfo(name); - if (!pkgInfo && env.upstream) { - pkgInfo = await fetchPackageInfo(name, env.upstreamRegistry); - if (pkgInfo) isUpstreamPackage = true; - } - if (!pkgInfo) { - log.error("404", `package not found: ${name}`); - return { code: 1, dirty }; - } - // verify version - const versions = Object.keys(pkgInfo.versions) as SemanticVersion[]; - // eslint-disable-next-line require-atomic-updates - if (!version || version === "latest") - version = tryGetLatestVersion(pkgInfo); - if (versions.filter((x) => x === version).length <= 0) { - log.warn( - "404", - `version ${version} is not a valid choice of: ${versions - .reverse() - .join(", ")}` - ); - return { code: 1, dirty }; - } - - if (version === undefined) - throw new Error("Could not determine package version to add"); - const versionInfo = pkgInfo.versions[version]; - // verify editor version - if (versionInfo.unity) { - const requiredEditorVersion = versionInfo.unityRelease - ? versionInfo.unity + "." + versionInfo.unityRelease - : versionInfo.unity; - if (env.editorVersion) { - const editorVersionResult = tryParseEditorVersion(env.editorVersion); - const requiredEditorVersionResult = tryParseEditorVersion( - requiredEditorVersion + // load manifest + const manifest = loadManifest(env.cwd); + if (manifest === null) return { code: 1, dirty }; + // packages that added to scope registry + const pkgsInScope: DomainName[] = []; + if (version === undefined || !isPackageUrl(version)) { + // verify name + let pkgInfo = await fetchPackageInfo(env.registry, name); + if (!pkgInfo && env.upstream) { + pkgInfo = await fetchPackageInfo(env.upstreamRegistry, name); + if (pkgInfo) isUpstreamPackage = true; + } + if (!pkgInfo) { + log.error("404", `package not found: ${name}`); + return { code: 1, dirty }; + } + // verify version + const versions = Object.keys(pkgInfo.versions) as SemanticVersion[]; + // eslint-disable-next-line require-atomic-updates + if (!version || version === "latest") + version = tryGetLatestVersion(pkgInfo); + if (versions.filter((x) => x === version).length <= 0) { + log.warn( + "404", + `version ${version} is not a valid choice of: ${versions + .reverse() + .join(", ")}` ); - if (!editorVersionResult) { - log.warn( - "editor.version", - `${env.editorVersion} is unknown, the editor version check is disabled` + return { code: 1, dirty }; + } + + if (version === undefined) + throw new Error("Could not determine package version to add"); + const versionInfo = pkgInfo.versions[version]; + // verify editor version + if (versionInfo.unity) { + const requiredEditorVersion = versionInfo.unityRelease + ? versionInfo.unity + "." + versionInfo.unityRelease + : versionInfo.unity; + if (env.editorVersion) { + const editorVersionResult = tryParseEditorVersion(env.editorVersion); + const requiredEditorVersionResult = tryParseEditorVersion( + requiredEditorVersion ); - } - if (!requiredEditorVersionResult) { - log.warn("package.unity", `${requiredEditorVersion} is not valid`); - if (!force) { - log.notice( - "suggest", - "contact the package author to fix the issue, or run with option -f to ignore the warning" + if (!editorVersionResult) { + log.warn( + "editor.version", + `${env.editorVersion} is unknown, the editor version check is disabled` ); - return { code: 1, dirty }; } - } - if ( - editorVersionResult && - requiredEditorVersionResult && - compareEditorVersion(env.editorVersion, requiredEditorVersion) < 0 - ) { - log.warn( - "editor.version", - `requires ${requiredEditorVersion} but found ${env.editorVersion}` - ); - if (!force) { - log.notice( - "suggest", - `upgrade the editor to ${requiredEditorVersion}, or run with option -f to ignore the warning` + if (!requiredEditorVersionResult) { + log.warn("package.unity", `${requiredEditorVersion} is not valid`); + if (!options.force) { + log.notice( + "suggest", + "contact the package author to fix the issue, or run with option -f to ignore the warning" + ); + return { code: 1, dirty }; + } + } + if ( + editorVersionResult && + requiredEditorVersionResult && + compareEditorVersion(env.editorVersion, requiredEditorVersion) < 0 + ) { + log.warn( + "editor.version", + `requires ${requiredEditorVersion} but found ${env.editorVersion}` ); - return { code: 1, dirty }; + if (!options.force) { + log.notice( + "suggest", + `upgrade the editor to ${requiredEditorVersion}, or run with option -f to ignore the warning` + ); + return { code: 1, dirty }; + } } } } - } - // pkgsInScope - if (!isUpstreamPackage) { - const [depsValid, depsInvalid] = await fetchPackageDependencies({ - name, - version, - deep: true, - }); - // add depsValid to pkgsInScope. - depsValid - .filter((x) => !x.upstream && !x.internal) - .map((x) => x.name) - .forEach((name) => pkgsInScope.push(name)); - // print suggestion for depsInvalid - depsInvalid.forEach((depObj) => { - if (depObj.reason == "package404" || depObj.reason == "version404") { - const resolvedVersion = manifest.dependencies[depObj.name]; - depObj.resolved = Boolean(resolvedVersion); - if (!depObj.resolved) - log.notice( - "suggest", - `to install ${packageReference( - depObj.name, - depObj.version - )} or a replaceable version manually` + // pkgsInScope + if (!isUpstreamPackage) { + const [depsValid, depsInvalid] = await fetchPackageDependencies( + env.registry, + env.upstreamRegistry, + name, + version, + true + ); + // add depsValid to pkgsInScope. + depsValid + .filter((x) => !x.upstream && !x.internal) + .map((x) => x.name) + .forEach((name) => pkgsInScope.push(name)); + // print suggestion for depsInvalid + depsInvalid.forEach((depObj) => { + if (depObj.reason == "package404" || depObj.reason == "version404") { + const resolvedVersion = manifest.dependencies[depObj.name]; + depObj.resolved = Boolean(resolvedVersion); + if (!depObj.resolved) + log.notice( + "suggest", + `to install ${packageReference( + depObj.name, + depObj.version + )} or a replaceable version manually` + ); + } + }); + if (depsInvalid.filter((x) => !x.resolved).length > 0) { + if (!options.force) { + log.error( + "missing dependencies", + "please resolve thie issue or run with option -f to ignore the warning" ); + return { code: 1, dirty }; + } } - }); - if (depsInvalid.filter((x) => !x.resolved).length > 0) { - if (!force) { - log.error( - "missing dependencies", - "please resolve thie issue or run with option -f to ignore the warning" - ); - return { code: 1, dirty }; - } - } - } else pkgsInScope.push(name); - } - // add to dependencies - const oldVersion = manifest.dependencies[name]; - addDependency(manifest, name, version); - if (!oldVersion) { - // Log the added package - log.notice("manifest", `added ${packageReference(name, version)}`); - dirty = true; - } else if (oldVersion != version) { - // Log the modified package version - log.notice("manifest", `modified ${name} ${oldVersion} => ${version}`); - dirty = true; - } else { - // Log the existed package - log.notice("manifest", `existed ${packageReference(name, version)}`); - } - if (!isUpstreamPackage) { - // add to scopedRegistries - if (!manifest.scopedRegistries) { - manifest.scopedRegistries = []; - dirty = true; + } else pkgsInScope.push(name); } - let entry = tryGetScopedRegistryByUrl(manifest, env.registry); - if (entry === null) { - const name = url.parse(env.registry).hostname; - if (name === null) throw new Error("Could not resolve registry name"); - entry = scopedRegistry(name, env.registry); - addScopedRegistry(manifest, entry); + // add to dependencies + const oldVersion = manifest.dependencies[name]; + addDependency(manifest, name, version); + if (!oldVersion) { + // Log the added package + log.notice("manifest", `added ${packageReference(name, version)}`); + dirty = true; + } else if (oldVersion != version) { + // Log the modified package version + log.notice("manifest", `modified ${name} ${oldVersion} => ${version}`); dirty = true; + } else { + // Log the existed package + log.notice("manifest", `existed ${packageReference(name, version)}`); } - // apply pkgsInScope - const scopesSet = new Set(entry.scopes || []); - if (isDomainName(env.namespace)) pkgsInScope.push(env.namespace); - pkgsInScope.forEach((name) => { - if (!scopesSet.has(name)) { - scopesSet.add(name); + if (!isUpstreamPackage) { + // add to scopedRegistries + if (!manifest.scopedRegistries) { + manifest.scopedRegistries = []; dirty = true; } - }); - entry.scopes = Array.from(scopesSet).sort(); - } - if (testables) addTestable(manifest, name); - // save manifest - if (dirty) { - if (!saveManifest(manifest)) return { code: 1, dirty }; - } - return { code: 0, dirty }; + let entry = tryGetScopedRegistryByUrl(manifest, env.registry.url); + if (entry === null) { + const name = url.parse(env.registry.url).hostname; + if (name === null) throw new Error("Could not resolve registry name"); + entry = scopedRegistry(name, env.registry.url); + addScopedRegistry(manifest, entry); + dirty = true; + } + // apply pkgsInScope + const scopesSet = new Set(entry.scopes || []); + if (isDomainName(env.namespace)) pkgsInScope.push(env.namespace); + pkgsInScope.forEach((name) => { + if (!scopesSet.has(name)) { + scopesSet.add(name); + dirty = true; + } + }); + entry.scopes = Array.from(scopesSet).sort(); + } + if (options.test) addTestable(manifest, name); + // save manifest + if (dirty) { + if (!saveManifest(env.cwd, manifest)) return { code: 1, dirty }; + } + return { code: 0, dirty }; + }; + + // add + const results = []; + for (const pkg of pkgs) results.push(await addSingle(pkg)); + const result: AddResult = { + 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) + log.notice("", "please open Unity project to apply changes"); + return result.code; }; diff --git a/src/cmd-deps.ts b/src/cmd-deps.ts index 660031ae..5614116c 100644 --- a/src/cmd-deps.ts +++ b/src/cmd-deps.ts @@ -1,13 +1,11 @@ import log from "./logger"; import { parseEnv } from "./utils/env"; import { fetchPackageDependencies } from "./registry-client"; -import { DomainName } from "./types/domain-name"; import { isPackageUrl } from "./types/package-url"; import { packageReference, PackageReference, splitPackageReference, - VersionReference, } from "./types/package-reference"; import { CmdOptions } from "./types/options"; @@ -20,32 +18,21 @@ export const deps = async function ( options: DepsOptions ) { // parse env - const envOk = await parseEnv(options, { checkPath: false }); - if (!envOk) return 1; - // parse name + const env = await parseEnv(options, false); + if (env === null) return 1; + const [name, version] = splitPackageReference(pkg); - // deps - await _deps({ name, version, deep: options.deep }); - return 0; -}; -const _deps = async function ({ - name, - version, - deep, -}: { - name: DomainName; - version: VersionReference | undefined; - deep?: boolean; -}) { if (version !== undefined && isPackageUrl(version)) throw new Error("Cannot get dependencies for url-version"); - const [depsValid, depsInvalid] = await fetchPackageDependencies({ + const [depsValid, depsInvalid] = await fetchPackageDependencies( + env.registry, + env.upstreamRegistry, name, version, - deep, - }); + options.deep + ); depsValid .filter((x) => !x.self) .forEach((x) => @@ -59,4 +46,6 @@ const _deps = async function ({ else if (x.reason == "version404") reason = "missing dependency version"; log.warn(reason, packageReference(x.name, x.version)); }); + + return 0; }; diff --git a/src/cmd-login.ts b/src/cmd-login.ts index f0ff06fa..07cba4cd 100644 --- a/src/cmd-login.ts +++ b/src/cmd-login.ts @@ -30,8 +30,8 @@ export type LoginOptions = CmdOptions<{ export const login = async function (options: LoginOptions) { // parse env - const envOk = await parseEnv(options, { checkPath: false }); - if (!envOk) return 1; + const env = await parseEnv(options, false); + if (env === null) return 1; // query parameters if (!options.username) options.username = await promptUsername(); if (!options.password) options.password = await promptPassword(); @@ -45,12 +45,12 @@ export const login = async function (options: LoginOptions) { _auth = encodeBasicAuth(options.username, options.password); } else { // npm login - const result = await npmLogin({ - username: options.username, - password: options.password, - email: options.email, - registry: options._global.registry as RegistryUrl, - }); + const result = await npmLogin( + options.username, + options.password, + options.email, + options._global.registry as RegistryUrl + ); if (result.code == 1) return result.code; if (!result.token) { log.error("auth", "can not find token from server response"); @@ -58,37 +58,31 @@ export const login = async function (options: LoginOptions) { } token = result.token; // write npm token - await writeNpmToken({ - registry: options._global.registry as RegistryUrl, - token: result.token, - }); + await writeNpmToken(options._global.registry as RegistryUrl, result.token); } // write unity token - await writeUnityToken({ + const configDir = await getUpmConfigDir(env.wsl, env.systemUser); + await writeUnityToken( + configDir, _auth, - alwaysAuth: options.alwaysAuth || false, - basicAuth: options.basicAuth || false, - email: options.email, - registry: options._global.registry as RegistryUrl, - token, - }); + options.alwaysAuth || false, + options.basicAuth || false, + options.email, + options._global.registry as RegistryUrl, + token + ); }; /** * Return npm login token */ -const npmLogin = async function ({ - username, - password, - email, - registry, -}: { - username: string; - password: string; - email: string; - registry: RegistryUrl; -}) { +const npmLogin = async function ( + username: string, + password: string, + email: string, + registry: RegistryUrl +) { const client = getNpmClient(); try { const data = await client.adduser(registry, { @@ -120,15 +114,8 @@ const npmLogin = async function ({ /** * Write npm token to .npmrc - * @param {*} param0 */ -const writeNpmToken = async function ({ - registry, - token, -}: { - registry: RegistryUrl; - token: string; -}) { +const writeNpmToken = async function (registry: RegistryUrl, token: string) { const configPath = getNpmrcPath(); // read config let content = ""; @@ -193,23 +180,15 @@ export const generateNpmrcLines = function ( /** * Write npm token to Unity */ -const writeUnityToken = async function ({ - _auth, - alwaysAuth, - basicAuth, - email, - registry, - token, -}: { - _auth: Base64 | null; - alwaysAuth: boolean; - basicAuth: boolean; - email: string; - registry: RegistryUrl; - token: string | null; -}) { - // Create config dir if necessary - const configDir = await getUpmConfigDir(); +const writeUnityToken = async function ( + configDir: string, + _auth: Base64 | null, + alwaysAuth: boolean, + basicAuth: boolean, + email: string, + registry: RegistryUrl, + token: string | null +) { // Read config file const config = (await loadUpmConfig(configDir)) || {}; if (!config.npmAuth) config.npmAuth = {}; diff --git a/src/cmd-remove.ts b/src/cmd-remove.ts index ac24679e..74149cfd 100644 --- a/src/cmd-remove.ts +++ b/src/cmd-remove.ts @@ -1,6 +1,6 @@ import log from "./logger"; import { loadManifest, saveManifest } from "./utils/pkg-manifest-io"; -import { env, parseEnv } from "./utils/env"; +import { parseEnv } from "./utils/env"; import { isDomainName } from "./types/domain-name"; import { packageReference, @@ -22,11 +22,59 @@ export const remove = async function ( ) { if (!Array.isArray(pkgs)) pkgs = [pkgs]; // parse env - const envOk = await parseEnv(options, { checkPath: true }); - if (!envOk) return 1; + const env = await parseEnv(options, true); + if (env === null) return 1; + + const removeSingle = async function (pkg: PackageReference) { + // dirty flag + let dirty = false; + // parse name + const split = splitPackageReference(pkg); + const name = split[0]; + let version = split[1]; + if (version) { + log.warn( + "", + `please replace '${packageReference(name, version)}' with '${name}'` + ); + return { code: 1, dirty }; + } + // load manifest + const manifest = loadManifest(env.cwd); + if (manifest === null) return { code: 1, dirty }; + // not found array + const pkgsNotFound = []; + version = manifest.dependencies[name]; + if (version) { + log.notice("manifest", `removed ${packageReference(name, version)}`); + removeDependency(manifest, name); + dirty = true; + } else pkgsNotFound.push(pkg); + + const entry = tryGetScopedRegistryByUrl(manifest, env.registry.url); + if (entry !== null) { + if (hasScope(entry, name)) { + removeScope(entry, name); + const scopesSet = new Set(entry.scopes); + if (isDomainName(env.namespace)) scopesSet.add(env.namespace); + entry.scopes = Array.from(scopesSet).sort(); + dirty = true; + } + } + // save manifest + if (dirty) { + if (!saveManifest(env.cwd, manifest)) return { code: 1, dirty }; + } + if (pkgsNotFound.length) { + log.error("404", `package not found: ${pkgsNotFound.join(", ")}`); + return { code: 1, dirty }; + } + return { code: 0, dirty }; + }; + // remove const results = []; - for (const pkg of pkgs) results.push(await _remove(pkg)); + for (const pkg of pkgs) results.push(await removeSingle(pkg)); const result = { code: results.filter((x) => x.code != 0).length > 0 ? 1 : 0, dirty: results.filter((x) => x.dirty).length > 0, @@ -36,50 +84,3 @@ export const remove = async function ( log.notice("", "please open Unity project to apply changes"); return result.code; }; - -const _remove = async function (pkg: PackageReference) { - // dirty flag - let dirty = false; - // parse name - const split = splitPackageReference(pkg); - const name = split[0]; - let version = split[1]; - if (version) { - log.warn( - "", - `please replace '${packageReference(name, version)}' with '${name}'` - ); - return { code: 1, dirty }; - } - // load manifest - const manifest = loadManifest(); - if (manifest === null) return { code: 1, dirty }; - // not found array - const pkgsNotFound = []; - version = manifest.dependencies[name]; - if (version) { - log.notice("manifest", `removed ${packageReference(name, version)}`); - removeDependency(manifest, name); - dirty = true; - } else pkgsNotFound.push(pkg); - - const entry = tryGetScopedRegistryByUrl(manifest, env.registry); - if (entry !== null) { - if (hasScope(entry, name)) { - removeScope(entry, name); - const scopesSet = new Set(entry.scopes); - if (isDomainName(env.namespace)) scopesSet.add(env.namespace); - entry.scopes = Array.from(scopesSet).sort(); - dirty = true; - } - } - // save manifest - if (dirty) { - if (!saveManifest(manifest)) return { code: 1, dirty }; - } - if (pkgsNotFound.length) { - log.error("404", `package not found: ${pkgsNotFound.join(", ")}`); - return { code: 1, dirty }; - } - return { code: 0, dirty }; -}; diff --git a/src/cmd-search.ts b/src/cmd-search.ts index 9890cab3..9e448758 100644 --- a/src/cmd-search.ts +++ b/src/cmd-search.ts @@ -6,11 +6,11 @@ import { is404Error, isHttpError } from "./utils/error-type-guards"; import * as os from "os"; import assert from "assert"; import { PkgInfo, tryGetLatestVersion } from "./types/pkg-info"; -import { env, parseEnv } from "./utils/env"; +import { parseEnv } from "./utils/env"; import { DomainName } from "./types/domain-name"; import { SemanticVersion } from "./types/semantic-version"; -import { RegistryUrl } from "./types/registry-url"; import { CmdOptions } from "./types/options"; +import { Registry } from "./registry-client"; type DateString = string; @@ -26,26 +26,28 @@ export type OldSearchResult = | SearchedPkgInfo[] | Record; -// Get npm fetch options -const getNpmFetchOptions = function (): Options { +/** + * Get npm fetch options + * @param registry The registry for which to get the options + */ +const getNpmFetchOptions = function (registry: Registry): Options { const opts: Options = { log, - registry: env.registry, + registry: registry.url, }; - const auth = env.auth[env.registry]; - if (auth) Object.assign(opts, auth); + const auth = registry.auth; + if (auth !== null) Object.assign(opts, auth); return opts; }; const searchEndpoint = async function ( - keyword: string, - registry?: RegistryUrl + registry: Registry, + keyword: string ): Promise { - if (!registry) registry = env.registry; try { // NOTE: The results of the search will be PkgInfo objects so we can change the type const results = ( - await npmSearch(keyword, getNpmFetchOptions()) + await npmSearch(keyword, getNpmFetchOptions(registry)) ); log.verbose("npmsearch", results.join(os.EOL)); return results.map(getTableRow); @@ -58,12 +60,13 @@ const searchEndpoint = async function ( }; const searchOld = async function ( + registry: Registry, keyword: string ): Promise { // all endpoint try { const results = ( - await npmFetch.json("/-/all", getNpmFetchOptions()) + await npmFetch.json("/-/all", getNpmFetchOptions(registry)) ); let objects: SearchedPkgInfo[] = []; if (results) { @@ -115,14 +118,15 @@ const getTableRow = function (pkg: SearchedPkgInfo): TableRow { export async function search(keyword: string, options: SearchOptions) { // parse env - const envOk = await parseEnv(options, { checkPath: false }); - if (!envOk) return 1; + const env = await parseEnv(options, false); + if (env === null) return 1; + const table = getTable(); // search endpoint - let results = await searchEndpoint(keyword); + let results = await searchEndpoint(env.registry, keyword); // search old search if (results === undefined) { - results = (await searchOld(keyword)) || []; + results = (await searchOld(env.registry, keyword)) || []; } // search upstream // if (env.upstream) { diff --git a/src/cmd-view.ts b/src/cmd-view.ts index 9c7f7dd8..c9da6af4 100644 --- a/src/cmd-view.ts +++ b/src/cmd-view.ts @@ -2,7 +2,7 @@ import chalk from "chalk"; import log from "./logger"; import assert from "assert"; import { PkgInfo, tryGetLatestVersion } from "./types/pkg-info"; -import { env, parseEnv } from "./utils/env"; +import { parseEnv } from "./utils/env"; import { fetchPackageInfo } from "./registry-client"; import { DomainName } from "./types/domain-name"; import { @@ -19,8 +19,8 @@ export const view = async function ( options: ViewOptions ) { // parse env - const envOk = await parseEnv(options, { checkPath: false }); - if (!envOk) return 1; + const env = await parseEnv(options, false); + if (env === null) return 1; // parse name const [name, version] = splitPackageReference(pkg); if (version) { @@ -31,9 +31,9 @@ export const view = async function ( return 1; } // verify name - let pkgInfo = await fetchPackageInfo(name); + let pkgInfo = await fetchPackageInfo(env.registry, name); if (!pkgInfo && env.upstream) - pkgInfo = await fetchPackageInfo(name, env.upstreamRegistry); + pkgInfo = await fetchPackageInfo(env.upstreamRegistry, name); if (!pkgInfo) { log.error("404", `package not found: ${name}`); return 1; diff --git a/src/registry-client.ts b/src/registry-client.ts index 5cbf9208..be860ca9 100644 --- a/src/registry-client.ts +++ b/src/registry-client.ts @@ -4,11 +4,11 @@ import RegClient, { AddUserResponse, ClientCallback, GetParams, + NpmAuth, } from "another-npm-registry-client"; import log from "./logger"; import request from "request"; import assert, { AssertionError } from "assert"; -import { env } from "./utils/env"; import _ from "lodash"; import { PkgInfo, tryGetLatestVersion } from "./types/pkg-info"; import { DomainName, isInternalPackage } from "./types/domain-name"; @@ -53,6 +53,11 @@ export type Dependency = { resolved?: boolean; }; +export type Registry = { + url: RegistryUrl; + auth: NpmAuth | null; +}; + type NameVersionPair = { name: DomainName; version: SemanticVersion | "latest" | undefined; @@ -106,14 +111,13 @@ export const getNpmClient = (): NpmClient => { }; // Fetch package info json from registry export const fetchPackageInfo = async function ( - name: DomainName, - registry?: RegistryUrl + registry: Registry, + name: DomainName ): Promise { - if (!registry) registry = env.registry; - const pkgPath = `${registry}/${name}`; + const pkgPath = `${registry.url}/${name}`; const client = getNpmClient(); try { - return await client.get(pkgPath, { auth: env.auth[registry] || undefined }); + return await client.get(pkgPath, { auth: registry.auth || undefined }); // eslint-disable-next-line no-empty } catch (err) {} }; @@ -130,15 +134,13 @@ export const fetchPackageInfo = async function ( }, ... ] */ -export const fetchPackageDependencies = async function ({ - name, - version, - deep, -}: { - name: DomainName; - version: SemanticVersion | "latest" | undefined; - deep?: boolean; -}): Promise<[Dependency[], Dependency[]]> { +export const fetchPackageDependencies = async function ( + registry: Registry, + upstreamRegistry: Registry, + name: DomainName, + version: SemanticVersion | "latest" | undefined, + deep?: boolean +): Promise<[Dependency[], Dependency[]]> { log.verbose( "dependency", `fetch: ${packageReference(name, version)} deep=${deep}` @@ -189,7 +191,7 @@ export const fetchPackageDependencies = async function ({ } // try fetching package info from the default registry if (pkgInfo === null) { - pkgInfo = (await fetchPackageInfo(entry.name)) ?? null; + pkgInfo = (await fetchPackageInfo(registry, entry.name)) ?? null; if (pkgInfo) { depObj.upstream = false; cachedPacakgeInfoDict[entry.name] = { pkgInfo, upstream: false }; @@ -198,7 +200,7 @@ export const fetchPackageDependencies = async function ({ // try fetching package info from the upstream registry if (!pkgInfo) { pkgInfo = - (await fetchPackageInfo(entry.name, env.upstreamRegistry)) ?? null; + (await fetchPackageInfo(upstreamRegistry, entry.name)) ?? null; if (pkgInfo) { depObj.upstream = true; cachedPacakgeInfoDict[entry.name] = { pkgInfo, upstream: true }; diff --git a/src/types/pkg-manifest.ts b/src/types/pkg-manifest.ts index 54d99295..cbf2a7bb 100644 --- a/src/types/pkg-manifest.ts +++ b/src/types/pkg-manifest.ts @@ -3,6 +3,7 @@ import { SemanticVersion } from "./semantic-version"; import { PackageUrl } from "./package-url"; import { ScopedRegistry } from "./scoped-registry"; import { RegistryUrl, removeTrailingSlash } from "./registry-url"; +import path from "path"; /** * The content of the package-manifest (manifest.json) of a Unity project @@ -96,3 +97,12 @@ export function addTestable(manifest: PkgManifest, name: DomainName) { if (manifest.testables.indexOf(name) === -1) manifest.testables.push(name); manifest.testables.sort(); } + +/** + * Determines the path to the package manifest based on the working + * directory (Root of Unity project). + * @param workingDirectory The working directory + */ +export function manifestPathFor(workingDirectory: string): string { + return path.join(workingDirectory, "Packages/manifest.json"); +} diff --git a/src/utils/env.ts b/src/utils/env.ts index 46128ae1..a331d199 100644 --- a/src/utils/env.ts +++ b/src/utils/env.ts @@ -1,6 +1,6 @@ import log from "../logger"; import chalk from "chalk"; -import { loadUpmConfig } from "./upm-config-io"; +import { getUpmConfigDir, loadUpmConfig } from "./upm-config-io"; import path from "path"; import fs from "fs"; import yaml from "yaml"; @@ -24,56 +24,49 @@ import { UpmAuth, } from "../types/upm-config"; import { encodeBase64 } from "../types/base64"; -import { NpmAuth } from "another-npm-registry-client"; import { CmdOptions } from "../types/options"; - -type Region = "us" | "cn"; +import { manifestPathFor } from "../types/pkg-manifest"; +import { Registry } from "../registry-client"; +import { NpmAuth } from "another-npm-registry-client"; export type Env = { cwd: string; - color: boolean; systemUser: boolean; wsl: boolean; - npmAuth?: Record; - auth: Record; upstream: boolean; - upstreamRegistry: RegistryUrl; - registry: RegistryUrl; + upstreamRegistry: Registry; + registry: Registry; namespace: DomainName | IpAddress; editorVersion: string | null; - region: Region; - manifestPath: string; }; -export const env: Env = {}; - // Parse env export const parseEnv = async function ( options: CmdOptions, - { checkPath }: { checkPath: unknown } -) { + checkPath: boolean +): Promise { // set defaults - env.registry = registryUrl("https://package.openupm.com"); + const env = {}; + env.registry = { + url: registryUrl("https://package.openupm.com"), + auth: null, + }; env.cwd = ""; - env.manifestPath = ""; env.namespace = openUpmReverseDomainName; env.upstream = true; - env.color = true; - env.upstreamRegistry = registryUrl("https://packages.unity.com"); + env.upstreamRegistry = { + url: registryUrl("https://packages.unity.com"), + auth: null, + }; env.systemUser = false; env.wsl = false; env.editorVersion = null; - env.region = "us"; - // the npmAuth field of .upmconfig.toml - env.npmAuth = {}; - // the dict of auth param for npm registry API - env.auth = {}; // log level log.level = options._global.verbose ? "verbose" : "notice"; // color - if (options._global.color === false) env.color = false; - if (process.env.NODE_ENV == "test") env.color = false; - if (!env.color) { + const useColor = + options._global.color !== false && process.env.NODE_ENV !== "test"; + if (!useColor) { chalk.level = 0; log.disableColor(); } @@ -81,73 +74,92 @@ export const parseEnv = async function ( if (options._global.upstream === false) env.upstream = false; // region cn if (options._global.cn === true) { - env.registry = registryUrl("https://package.openupm.cn"); - env.upstreamRegistry = registryUrl("https://packages.unity.cn"); - env.region = "cn"; + env.registry = { + url: registryUrl("https://package.openupm.cn"), + auth: null, + }; + env.upstreamRegistry = { + url: registryUrl("https://packages.unity.cn"), + auth: null, + }; log.notice("region", "cn"); } // registry if (options._global.registry) { - env.registry = coerceRegistryUrl(options._global.registry); + env.registry = { + url: coerceRegistryUrl(options._global.registry), + auth: null, + }; // TODO: Check hostname for null - const hostname = url.parse(env.registry).hostname as string; + const hostname = url.parse(env.registry.url).hostname as string; if (isIpAddress(hostname)) env.namespace = hostname; else env.namespace = namespaceFor(hostname); } + + function tryToNpmAuth(upmAuth: UpmAuth): NpmAuth | null { + if (isTokenAuth(upmAuth)) { + return { + token: upmAuth.token, + alwaysAuth: shouldAlwaysAuth(upmAuth), + }; + } else if (isBasicAuth(upmAuth)) { + const [username, password] = decodeBasicAuth(upmAuth._auth); + return { + username, + password: encodeBase64(password), + email: upmAuth.email, + alwaysAuth: shouldAlwaysAuth(upmAuth), + }; + } + return null; + } + // auth if (options._global.systemUser) env.systemUser = true; if (options._global.wsl) env.wsl = true; - const upmConfig = await loadUpmConfig(); - if (upmConfig) { - env.npmAuth = upmConfig.npmAuth; - if (env.npmAuth !== undefined) { - (Object.keys(env.npmAuth) as RegistryUrl[]).forEach((reg) => { - const regAuth = env.npmAuth![reg]; - if (isTokenAuth(regAuth)) { - env.auth[reg] = { - token: regAuth.token, - alwaysAuth: shouldAlwaysAuth(regAuth), - }; - } else if (isBasicAuth(regAuth)) { - const [username, password] = decodeBasicAuth(regAuth._auth); - env.auth[reg] = { - username, - password: encodeBase64(password), - email: regAuth.email, - alwaysAuth: shouldAlwaysAuth(regAuth), - }; - } else { - log.warn( - "env.auth", - `failed to parse auth info for ${reg} in .upmconfig.toml: missing token or _auth fields` - ); - log.warn("env.auth", regAuth); - } - }); + const configDir = await getUpmConfigDir(env.wsl, env.systemUser); + const upmConfig = await loadUpmConfig(configDir); + + function tryGetAuthForRegistry(registry: RegistryUrl): NpmAuth | null { + const upmAuth = upmConfig!.npmAuth![registry]; + if (upmAuth === undefined) return null; + const npmAuth = tryToNpmAuth(upmAuth); + if (npmAuth === null) { + log.warn( + "env.auth", + `failed to parse auth info for ${registry} in .upmconfig.toml: missing token or _auth fields` + ); } + return null; + } + + if (upmConfig !== undefined && upmConfig.npmAuth !== undefined) { + env.registry.auth = tryGetAuthForRegistry(env.registry.url); + env.upstreamRegistry.auth = tryGetAuthForRegistry(env.upstreamRegistry.url); } // log.verbose("env.npmAuth", env.npmAuth); // log.verbose("env.auth", env.auth); // return if no need to check path - if (!checkPath) return true; + if (!checkPath) return env; // cwd if (options._global.chdir) { const cwd = path.resolve(options._global.chdir); if (!fs.existsSync(cwd)) { log.error("env", `can not resolve path ${cwd}`); - return false; + return null; } env.cwd = cwd; } else env.cwd = process.cwd(); // manifest path - const manifestPath = path.join(env.cwd, "Packages/manifest.json"); + const manifestPath = manifestPathFor(env.cwd); if (!fs.existsSync(manifestPath)) { log.error( "manifest", `can not locate manifest.json at path ${manifestPath}` ); - return false; - } else env.manifestPath = manifestPath; + return null; + } + // editor version const projectVersionPath = path.join( env.cwd, @@ -164,5 +176,5 @@ export const parseEnv = async function ( env.editorVersion = projectVersionContent.m_EditorVersion; } // return - return true; + return env; }; diff --git a/src/utils/pkg-manifest-io.ts b/src/utils/pkg-manifest-io.ts index 8941ab61..1817698b 100644 --- a/src/utils/pkg-manifest-io.ts +++ b/src/utils/pkg-manifest-io.ts @@ -1,25 +1,25 @@ import fs from "fs"; import { assertIsError } from "./error-type-guards"; import log from "../logger"; -import { env } from "./env"; -import { PkgManifest } from "../types/pkg-manifest"; +import { manifestPathFor, PkgManifest } from "../types/pkg-manifest"; /** * Attempts to load the manifest from the path specified in env + * @param workingDirectory The working directory */ -export const loadManifest = function (): PkgManifest | null { +export const loadManifest = function ( + workingDirectory: string +): PkgManifest | null { + const manifestPath = manifestPathFor(workingDirectory); try { - const text = fs.readFileSync(env.manifestPath, { encoding: "utf8" }); + const text = fs.readFileSync(manifestPath, { encoding: "utf8" }); return JSON.parse(text); } catch (err) { assertIsError(err); if (err.code == "ENOENT") - log.error("manifest", "file Packages/manifest.json does not exist"); + log.error("manifest", `manifest at ${manifestPath} does not exist`); else { - log.error( - "manifest", - `failed to parse Packages/manifest.json at ${env.manifestPath}` - ); + log.error("manifest", `failed to parse manifest at ${manifestPath}`); log.error("manifest", err.message); } return null; @@ -27,12 +27,18 @@ export const loadManifest = function (): PkgManifest | null { }; /** - * Save manifest json file to the path specified in env + * Save manifest json file to the path specified in enva + * @param workingDirectory The working directory + * @param data The manifest to save */ -export const saveManifest = function (data: PkgManifest) { +export const saveManifest = function ( + workingDirectory: string, + data: PkgManifest +) { + const manifestPath = manifestPathFor(workingDirectory); const json = JSON.stringify(data, null, 2); try { - fs.writeFileSync(env.manifestPath, json); + fs.writeFileSync(manifestPath, json); return true; } catch (err) { assertIsError(err); diff --git a/src/utils/upm-config-io.ts b/src/utils/upm-config-io.ts index 49913f9f..4a13ea25 100644 --- a/src/utils/upm-config-io.ts +++ b/src/utils/upm-config-io.ts @@ -5,22 +5,26 @@ import fs from "fs"; import log from "../logger"; import isWsl from "is-wsl"; import execute from "./process"; -import { env } from "./env"; import { UPMConfig } from "../types/upm-config"; const configFileName = ".upmconfig.toml"; /** * Gets the path to directory in which the upm config is stored + * @param wsl Whether WSL should be treated as Windows + * @param systemUser Whether to authenticate as a Windows system-user */ -export const getUpmConfigDir = async (): Promise => { +export const getUpmConfigDir = async ( + wsl: boolean, + systemUser: boolean +): Promise => { let dirPath: string | undefined = ""; const systemUserSubPath = "Unity/config/ServiceAccounts"; - if (env.wsl) { + if (wsl) { if (!isWsl) { throw new Error("no WSL detected"); } - if (env.systemUser) { + if (systemUser) { const allUserProfilePath = await execute( 'wslpath "$(wslvar ALLUSERSPROFILE)"', { trim: true } @@ -35,7 +39,7 @@ export const getUpmConfigDir = async (): Promise => { dirPath = process.env.USERPROFILE ? process.env.USERPROFILE : process.env.HOME; - if (env.systemUser) { + if (systemUser) { if (!process.env.ALLUSERSPROFILE) { throw new Error("env ALLUSERSPROFILE is empty"); } @@ -49,11 +53,11 @@ export const getUpmConfigDir = async (): Promise => { /** * Attempts to load the upm config + * @param configDir The directory from which to load the config */ export const loadUpmConfig = async ( - configDir?: string + configDir: string ): Promise => { - if (configDir === undefined) configDir = await getUpmConfigDir(); const configPath = path.join(configDir, configFileName); if (fs.existsSync(configPath)) { const content = fs.readFileSync(configPath, "utf8"); @@ -66,9 +70,10 @@ export const loadUpmConfig = async ( /** * Save the upm config + * @param config The config to save + * @param configDir The directory in which to save the config */ export const saveUpmConfig = async (config: UPMConfig, configDir: string) => { - if (configDir === undefined) configDir = await getUpmConfigDir(); mkdirp.sync(configDir); const configPath = path.join(configDir, configFileName); const content = TOML.stringify(config); diff --git a/test/manifest-assertions.ts b/test/manifest-assertions.ts index b10794ba..1fd6318b 100644 --- a/test/manifest-assertions.ts +++ b/test/manifest-assertions.ts @@ -6,14 +6,14 @@ import { PackageUrl } from "../src/types/package-url"; import { hasScope } from "../src/types/scoped-registry"; import { PkgManifest } from "../src/types/pkg-manifest"; -export function shouldHaveManifest(): PkgManifest { - const manifest = loadManifest(); +export function shouldHaveManifest(workingDirectory: string): PkgManifest { + const manifest = loadManifest(workingDirectory); should(manifest).not.be.null(); return manifest!; } -export function shouldHaveNoManifest() { - const manifest = loadManifest(); +export function shouldHaveNoManifest(workingDirectory: string) { + const manifest = loadManifest(workingDirectory); should(manifest).be.null(); } diff --git a/test/mock-work-dir.ts b/test/mock-work-dir.ts index fd795ea5..222340ad 100644 --- a/test/mock-work-dir.ts +++ b/test/mock-work-dir.ts @@ -14,7 +14,7 @@ export const getWorkDir = function (pathToTmp: string): string { export const createWorkDir = function ( pathToTmp: string, { manifest, editorVersion }: ManifestCreationOptions -) { +): string { const workDir = getWorkDir(pathToTmp); fse.mkdirpSync(workDir); if (manifest) { @@ -33,6 +33,7 @@ export const createWorkDir = function ( data ); } + return workDir; }; export const removeWorkDir = function (pathToTmp: string) { const cwd = getWorkDir(pathToTmp); diff --git a/test/test-cmd-add.ts b/test/test-cmd-add.ts index b58c690b..19efa4b8 100644 --- a/test/test-cmd-add.ts +++ b/test/test-cmd-add.ts @@ -22,6 +22,7 @@ import { semanticVersion } from "../src/types/semantic-version"; import { packageReference } from "../src/types/package-reference"; describe("cmd-add.ts", function () { + const workDirName = "test-openupm-cli"; const packageMissing = domainName("pkg-not-exist"); const packageA = domainName("com.base.package-a"); const packageB = domainName("com.base.package-b"); @@ -42,21 +43,21 @@ describe("cmd-add.ts", function () { _global: { registry: exampleRegistryUrl, upstream: false, - chdir: getWorkDir("test-openupm-cli"), + chdir: getWorkDir(workDirName), }, }; const upstreamOptions: AddOptions = { _global: { registry: exampleRegistryUrl, upstream: true, - chdir: getWorkDir("test-openupm-cli"), + chdir: getWorkDir(workDirName), }, }; const testableOptions: AddOptions = { _global: { registry: exampleRegistryUrl, upstream: false, - chdir: getWorkDir("test-openupm-cli"), + chdir: getWorkDir(workDirName), }, test: true, }; @@ -64,12 +65,13 @@ describe("cmd-add.ts", function () { _global: { registry: exampleRegistryUrl, upstream: false, - chdir: getWorkDir("test-openupm-cli"), + chdir: getWorkDir(workDirName), }, force: true, }; describe("add", function () { let mockConsole: MockConsole = null!; + let workDir = ""; const remotePkgInfoA = buildPackageInfo(packageA, (pkg) => pkg.addVersion("0.1.0").addVersion("1.0.0") @@ -134,8 +136,8 @@ describe("cmd-add.ts", function () { ); beforeEach(function () { - removeWorkDir("test-openupm-cli"); - createWorkDir("test-openupm-cli", { + removeWorkDir(workDirName); + workDir = createWorkDir(workDirName, { manifest: true, editorVersion: "2019.2.13f1", }); @@ -154,7 +156,7 @@ describe("cmd-add.ts", function () { mockConsole = attachMockConsole(); }); afterEach(function () { - removeWorkDir("test-openupm-cli"); + removeWorkDir(workDirName); stopMockRegistry(); mockConsole.detach(); }); @@ -162,7 +164,7 @@ describe("cmd-add.ts", function () { it("add pkg", async function () { const retCode = await add(packageA, options); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(expectedManifestA); mockConsole.hasLineIncluding("out", "added").should.be.ok(); mockConsole.hasLineIncluding("out", "open Unity").should.be.ok(); @@ -173,7 +175,7 @@ describe("cmd-add.ts", function () { options ); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(expectedManifestA); mockConsole.hasLineIncluding("out", "added").should.be.ok(); mockConsole.hasLineIncluding("out", "open Unity").should.be.ok(); @@ -181,7 +183,7 @@ describe("cmd-add.ts", function () { it("add pkg@latest", async function () { const retCode = await add(packageReference(packageA, "latest"), options); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(expectedManifestA); mockConsole.hasLineIncluding("out", "added").should.be.ok(); mockConsole.hasLineIncluding("out", "open Unity").should.be.ok(); @@ -197,7 +199,7 @@ describe("cmd-add.ts", function () { options ); retCode2.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(expectedManifestA); mockConsole.hasLineIncluding("out", "modified ").should.be.ok(); mockConsole.hasLineIncluding("out", "open Unity").should.be.ok(); @@ -213,7 +215,7 @@ describe("cmd-add.ts", function () { options ); retCode2.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(expectedManifestA); mockConsole.hasLineIncluding("out", "existed ").should.be.ok(); mockConsole.hasLineIncluding("out", "open Unity").should.be.ok(); @@ -224,7 +226,7 @@ describe("cmd-add.ts", function () { options ); retCode.should.equal(1); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(defaultManifest); mockConsole .hasLineIncluding("out", "version 2.0.0 is not a valid choice") @@ -235,7 +237,7 @@ describe("cmd-add.ts", function () { const gitUrl = "https://github.com/yo/com.base.package-a" as PackageUrl; const retCode = await add(packageReference(packageA, gitUrl), options); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); shouldHaveDependency(manifest, packageA, gitUrl); mockConsole.hasLineIncluding("out", "added").should.be.ok(); mockConsole.hasLineIncluding("out", "open Unity").should.be.ok(); @@ -244,7 +246,7 @@ describe("cmd-add.ts", function () { const gitUrl = "git@github.com:yo/com.base.package-a" as PackageUrl; const retCode = await add(packageReference(packageA, gitUrl), options); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); shouldHaveDependency(manifest, packageA, gitUrl); mockConsole.hasLineIncluding("out", "added").should.be.ok(); mockConsole.hasLineIncluding("out", "open Unity").should.be.ok(); @@ -253,7 +255,7 @@ describe("cmd-add.ts", function () { const fileUrl = "file../yo/com.base.package-a" as PackageUrl; const retCode = await add(packageReference(packageA, fileUrl), options); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); shouldHaveDependency(manifest, packageA, fileUrl); mockConsole.hasLineIncluding("out", "added").should.be.ok(); mockConsole.hasLineIncluding("out", "open Unity").should.be.ok(); @@ -261,14 +263,14 @@ describe("cmd-add.ts", function () { it("add pkg-not-exist", async function () { const retCode = await add(packageMissing, options); retCode.should.equal(1); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(defaultManifest); mockConsole.hasLineIncluding("out", "package not found").should.be.ok(); }); it("add more than one pkgs", async function () { const retCode = await add([packageA, packageB], options); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(expectedManifestAB); mockConsole .hasLineIncluding("out", "added com.base.package-a") @@ -281,7 +283,7 @@ describe("cmd-add.ts", function () { it("add pkg from upstream", async function () { const retCode = await add(packageUp, upstreamOptions); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(expectedManifestUpstream); mockConsole .hasLineIncluding("out", "added com.upstream.package-up") @@ -291,7 +293,7 @@ describe("cmd-add.ts", function () { it("add pkg-not-exist from upstream", async function () { const retCode = await add(packageMissing, upstreamOptions); retCode.should.equal(1); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(defaultManifest); mockConsole.hasLineIncluding("out", "package not found").should.be.ok(); }); @@ -301,7 +303,7 @@ describe("cmd-add.ts", function () { upstreamOptions ); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(expectedManifestC); mockConsole.hasLineIncluding("out", "added").should.be.ok(); mockConsole.hasLineIncluding("out", "open Unity").should.be.ok(); @@ -309,7 +311,7 @@ describe("cmd-add.ts", function () { it("add pkg with tests", async function () { const retCode = await add(packageA, testableOptions); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(expectedManifestTestable); mockConsole.hasLineIncluding("out", "added").should.be.ok(); mockConsole.hasLineIncluding("out", "open Unity").should.be.ok(); diff --git a/test/test-cmd-remove.ts b/test/test-cmd-remove.ts index 6ad76d58..8eff7b3a 100644 --- a/test/test-cmd-remove.ts +++ b/test/test-cmd-remove.ts @@ -4,7 +4,7 @@ import { exampleRegistryReverseDomain, exampleRegistryUrl, } from "./mock-registry"; -import { createWorkDir, getWorkDir, removeWorkDir } from "./mock-work-dir"; +import { createWorkDir, removeWorkDir } from "./mock-work-dir"; import { attachMockConsole, MockConsole } from "./mock-console"; import { shouldHaveManifest, @@ -19,10 +19,12 @@ import { packageReference } from "../src/types/package-reference"; const packageA = domainName("com.example.package-a"); const packageB = domainName("com.example.package-b"); const missingPackage = domainName("pkg-not-exist"); +const workDirName = "test-openupm-cli"; describe("cmd-remove.ts", function () { describe("remove", function () { let mockConsole: MockConsole = null!; + let workDir = ""; const defaultManifest = buildPackageManifest((manifest) => manifest @@ -31,26 +33,26 @@ describe("cmd-remove.ts", function () { ); beforeEach(function () { - removeWorkDir("test-openupm-cli"); - createWorkDir("test-openupm-cli", { + removeWorkDir(workDirName); + workDir = createWorkDir(workDirName, { manifest: defaultManifest, }); mockConsole = attachMockConsole(); }); afterEach(function () { - removeWorkDir("test-openupm-cli"); + removeWorkDir(workDirName); mockConsole.detach(); }); it("remove pkg", async function () { const options = { _global: { registry: exampleRegistryUrl, - chdir: getWorkDir("test-openupm-cli"), + chdir: workDir, }, }; const retCode = await remove(packageA, options); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); shouldNotHaveDependency(manifest, packageA); shouldHaveRegistryWithScopes(manifest, [ exampleRegistryReverseDomain, @@ -63,7 +65,7 @@ describe("cmd-remove.ts", function () { const options = { _global: { registry: exampleRegistryUrl, - chdir: getWorkDir("test-openupm-cli"), + chdir: workDir, }, }; const retCode = await remove( @@ -71,7 +73,7 @@ describe("cmd-remove.ts", function () { options ); retCode.should.equal(1); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(defaultManifest); mockConsole.hasLineIncluding("out", "please replace").should.be.ok(); }); @@ -79,12 +81,12 @@ describe("cmd-remove.ts", function () { const options = { _global: { registry: exampleRegistryUrl, - chdir: getWorkDir("test-openupm-cli"), + chdir: workDir, }, }; const retCode = await remove(missingPackage, options); retCode.should.equal(1); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.deepEqual(defaultManifest); mockConsole.hasLineIncluding("out", "package not found").should.be.ok(); }); @@ -92,12 +94,12 @@ describe("cmd-remove.ts", function () { const options = { _global: { registry: exampleRegistryUrl, - chdir: getWorkDir("test-openupm-cli"), + chdir: workDir, }, }; const retCode = await remove([packageA, packageB], options); retCode.should.equal(0); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); shouldNotHaveDependency(manifest, packageA); shouldNotHaveDependency(manifest, packageB); shouldHaveRegistryWithScopes(manifest, [exampleRegistryReverseDomain]); diff --git a/test/test-env.ts b/test/test-env.ts index 803d392e..d3be0014 100644 --- a/test/test-env.ts +++ b/test/test-env.ts @@ -1,6 +1,5 @@ import "should"; -import { env, parseEnv } from "../src/utils/env"; -import path from "path"; +import { parseEnv } from "../src/utils/env"; import { createWorkDir, getWorkDir, removeWorkDir } from "./mock-work-dir"; import { attachMockConsole, MockConsole } from "./mock-console"; import should from "should"; @@ -31,167 +30,148 @@ describe("env", function () { mockConsole.detach(); }); it("defaults", async function () { - (await parseEnv({ _global: {} }, { checkPath: false })).should.be.ok(); - env.registry.should.equal("https://package.openupm.com"); - env.upstream.should.be.ok(); - env.upstreamRegistry.should.equal("https://packages.unity.com"); - env.namespace.should.equal("com.openupm"); - env.cwd.should.equal(""); - env.manifestPath.should.equal(""); - (env.editorVersion === null).should.be.ok(); + const env = await parseEnv({ _global: {} }, false); + should(env).not.be.null(); + env!.registry.url.should.equal("https://package.openupm.com"); + env!.upstream.should.be.ok(); + env!.upstreamRegistry.url.should.equal("https://packages.unity.com"); + env!.namespace.should.equal("com.openupm"); + env!.cwd.should.equal(""); + (env!.editorVersion === null).should.be.ok(); }); it("check path", async function () { - ( - await parseEnv( - { _global: { chdir: getWorkDir("test-openupm-cli") } }, - { checkPath: true } - ) - ).should.be.ok(); - env.cwd.should.be.equal(getWorkDir("test-openupm-cli")); - env.manifestPath.should.be.equal( - path.join(getWorkDir("test-openupm-cli"), "Packages/manifest.json") + const env = await parseEnv( + { _global: { chdir: getWorkDir("test-openupm-cli") } }, + true ); + should(env).not.be.null(); + env!.cwd.should.be.equal(getWorkDir("test-openupm-cli")); }); it("can not resolve path", async function () { - ( - await parseEnv( - { _global: { chdir: getWorkDir("path-not-exist") } }, - { checkPath: true } - ) - ).should.not.be.ok(); + const env = await parseEnv( + { _global: { chdir: getWorkDir("path-not-exist") } }, + true + ); + should(env).be.null(); mockConsole .hasLineIncluding("out", "can not resolve path") .should.be.ok(); }); it("can not locate manifest.json", async function () { - ( - await parseEnv( - { _global: { chdir: getWorkDir("test-openupm-cli-no-manifest") } }, - { checkPath: true } - ) - ).should.not.be.ok(); + const env = await parseEnv( + { _global: { chdir: getWorkDir("test-openupm-cli-no-manifest") } }, + true + ); + should(env).be.null(); mockConsole .hasLineIncluding("out", "can not locate manifest.json") .should.be.ok(); }); it("custom registry", async function () { - ( - await parseEnv( - { _global: { registry: "https://registry.npmjs.org" } }, - { checkPath: false } - ) - ).should.be.ok(); - env.registry.should.be.equal("https://registry.npmjs.org"); - env.namespace.should.be.equal("org.npmjs"); + const env = await parseEnv( + { _global: { registry: "https://registry.npmjs.org" } }, + false + ); + should(env).not.be.null(); + env!.registry.url.should.be.equal("https://registry.npmjs.org"); + env!.namespace.should.be.equal("org.npmjs"); }); it("custom registry with splash", async function () { - ( - await parseEnv( - { _global: { registry: "https://registry.npmjs.org/" } }, - { checkPath: false } - ) - ).should.be.ok(); - env.registry.should.be.equal("https://registry.npmjs.org"); - env.namespace.should.be.equal("org.npmjs"); + const env = await parseEnv( + { _global: { registry: "https://registry.npmjs.org/" } }, + false + ); + should(env).not.be.null(); + env!.registry.url.should.be.equal("https://registry.npmjs.org"); + env!.namespace.should.be.equal("org.npmjs"); }); it("custom registry with extra path", async function () { - ( - await parseEnv( - { - _global: { - registry: "https://registry.npmjs.org/some", - }, + const env = await parseEnv( + { + _global: { + registry: "https://registry.npmjs.org/some", }, - { checkPath: false } - ) - ).should.be.ok(); - env.registry.should.be.equal("https://registry.npmjs.org/some"); - env.namespace.should.be.equal("org.npmjs"); + }, + false + ); + should(env).not.be.null(); + env!.registry.url.should.be.equal("https://registry.npmjs.org/some"); + env!.namespace.should.be.equal("org.npmjs"); }); it("custom registry with extra path and splash", async function () { - ( - await parseEnv( - { - _global: { - registry: "https://registry.npmjs.org/some/", - }, + const env = await parseEnv( + { + _global: { + registry: "https://registry.npmjs.org/some/", }, - { checkPath: false } - ) - ).should.be.ok(); - env.registry.should.be.equal("https://registry.npmjs.org/some"); - env.namespace.should.be.equal("org.npmjs"); + }, + false + ); + should(env).not.be.null(); + env!.registry.url.should.be.equal("https://registry.npmjs.org/some"); + env!.namespace.should.be.equal("org.npmjs"); }); it("custom registry without http", async function () { - ( - await parseEnv( - { _global: { registry: "registry.npmjs.org" } }, - { checkPath: false } - ) - ).should.be.ok(); - env.registry.should.be.equal("http://registry.npmjs.org"); - env.namespace.should.be.equal("org.npmjs"); + const env = await parseEnv( + { _global: { registry: "registry.npmjs.org" } }, + false + ); + should(env).not.be.null(); + env!.registry.url.should.be.equal("http://registry.npmjs.org"); + env!.namespace.should.be.equal("org.npmjs"); }); it("custom registry with ipv4+port", async function () { - ( - await parseEnv( - { _global: { registry: "http://127.0.0.1:4873" } }, - { checkPath: false } - ) - ).should.be.ok(); - env.registry.should.be.equal("http://127.0.0.1:4873"); - env.namespace.should.be.equal("127.0.0.1"); + const env = await parseEnv( + { _global: { registry: "http://127.0.0.1:4873" } }, + false + ); + should(env).not.be.null(); + env!.registry.url.should.be.equal("http://127.0.0.1:4873"); + env!.namespace.should.be.equal("127.0.0.1"); }); it("custom registry with ipv6+port", async function () { - ( - await parseEnv( - { - _global: { registry: "http://[1:2:3:4:5:6:7:8]:4873" }, - }, - { checkPath: false } - ) - ).should.be.ok(); - env.registry.should.be.equal("http://[1:2:3:4:5:6:7:8]:4873"); - env.namespace.should.be.equal("1:2:3:4:5:6:7:8"); + const env = await parseEnv( + { + _global: { registry: "http://[1:2:3:4:5:6:7:8]:4873" }, + }, + false + ); + should(env).not.be.null(); + env!.registry.url.should.be.equal("http://[1:2:3:4:5:6:7:8]:4873"); + env!.namespace.should.be.equal("1:2:3:4:5:6:7:8"); }); it("upstream", async function () { - ( - await parseEnv({ _global: { upstream: false } }, { checkPath: false }) - ).should.be.ok(); - env.upstream.should.not.be.ok(); + const env = await parseEnv({ _global: { upstream: false } }, false); + should(env).not.be.null(); + env!.upstream.should.not.be.ok(); }); it("editorVersion", async function () { - ( - await parseEnv( - { _global: { chdir: getWorkDir("test-openupm-cli") } }, - { checkPath: true } - ) - ).should.be.ok(); - should(env.editorVersion).be.equal("2019.2.13f1"); + const env = await parseEnv( + { _global: { chdir: getWorkDir("test-openupm-cli") } }, + true + ); + should(env).not.be.null(); + should(env!.editorVersion).be.equal("2019.2.13f1"); }); it("region cn", async function () { - ( - await parseEnv({ _global: { cn: true } }, { checkPath: false }) - ).should.be.ok(); - env.registry.should.be.equal("https://package.openupm.cn"); - env.upstreamRegistry.should.be.equal("https://packages.unity.cn"); - env.region.should.be.equal("cn"); + const env = await parseEnv({ _global: { cn: true } }, false); + should(env).not.be.null(); + env!.registry.url.should.be.equal("https://package.openupm.cn"); + env!.upstreamRegistry.url.should.be.equal("https://packages.unity.cn"); }); it("region cn with a custom registry", async function () { - ( - await parseEnv( - { - _global: { - cn: true, - registry: "https://reg.custom-package.com", - }, + const env = await parseEnv( + { + _global: { + cn: true, + registry: "https://reg.custom-package.com", }, - { checkPath: false } - ) - ).should.be.ok(); - env.registry.should.be.equal("https://reg.custom-package.com"); - env.upstreamRegistry.should.be.equal("https://packages.unity.cn"); - env.region.should.be.equal("cn"); + }, + false + ); + should(env).not.be.null(); + env!.registry.url.should.be.equal("https://reg.custom-package.com"); + env!.upstreamRegistry.url.should.be.equal("https://packages.unity.cn"); }); }); }); diff --git a/test/test-pkg-manifest-io.ts b/test/test-pkg-manifest-io.ts index 2f020b8c..21ad3e42 100644 --- a/test/test-pkg-manifest-io.ts +++ b/test/test-pkg-manifest-io.ts @@ -1,10 +1,8 @@ import { attachMockConsole, MockConsole } from "./mock-console"; import fs from "fs"; import "should"; -import path from "path"; import { saveManifest } from "../src/utils/pkg-manifest-io"; import { describe } from "mocha"; -import { parseEnv } from "../src/utils/env"; import { createWorkDir, getWorkDir, removeWorkDir } from "./mock-work-dir"; import { shouldHaveManifest, @@ -13,72 +11,56 @@ import { } from "./manifest-assertions"; import { domainName } from "../src/types/domain-name"; import { semanticVersion } from "../src/types/semantic-version"; -import { addDependency } from "../src/types/pkg-manifest"; +import { addDependency, manifestPathFor } from "../src/types/pkg-manifest"; +import should from "should"; + +const workDirName = "test-openupm-cli"; +const wrongJsonWorkDirName = "test-openupm-cli-wrong-json"; describe("pkg-manifest io", function () { let mockConsole: MockConsole = null!; + let workDir = ""; + let wrongJsonWorkDir = ""; + beforeEach(function () { - removeWorkDir("test-openupm-cli"); - createWorkDir("test-openupm-cli", { manifest: true }); - createWorkDir("test-openupm-cli-wrong-json", { + removeWorkDir(workDirName); + workDir = createWorkDir(workDirName, { manifest: true }); + wrongJsonWorkDir = createWorkDir(wrongJsonWorkDirName, { manifest: true, }); fs.writeFileSync( - path.join( - getWorkDir("test-openupm-cli-wrong-json"), - "Packages/manifest.json" - ), + manifestPathFor(getWorkDir(wrongJsonWorkDirName)), "wrong-json" ); mockConsole = attachMockConsole(); }); afterEach(function () { - removeWorkDir("test-openupm-cli"); - removeWorkDir("test-openupm-cli-wrong-json"); + removeWorkDir(workDirName); + removeWorkDir(wrongJsonWorkDirName); mockConsole.detach(); }); it("loadManifest", async function () { - ( - await parseEnv( - { _global: { chdir: getWorkDir("test-openupm-cli") } }, - { checkPath: true } - ) - ).should.be.ok(); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); manifest.should.be.deepEqual({ dependencies: {} }); }); it("no manifest file", async function () { - ( - await parseEnv( - { _global: { chdir: getWorkDir("path-not-exist") } }, - { checkPath: false } - ) - ).should.be.ok(); - shouldHaveNoManifest(); + shouldHaveNoManifest("path-not-exist"); mockConsole.hasLineIncluding("out", "does not exist").should.be.ok(); }); it("wrong json content", async function () { - ( - await parseEnv( - { _global: { chdir: getWorkDir("test-openupm-cli-wrong-json") } }, - { checkPath: true } - ) - ).should.be.ok(); - shouldHaveNoManifest(); + shouldHaveNoManifest(wrongJsonWorkDir); mockConsole.hasLineIncluding("out", "failed to parse").should.be.ok(); }); it("saveManifest", async function () { - ( - await parseEnv( - { _global: { chdir: getWorkDir("test-openupm-cli") } }, - { checkPath: true } - ) - ).should.be.ok(); - const manifest = shouldHaveManifest(); + const manifest = shouldHaveManifest(workDir); shouldNotHaveAnyDependencies(manifest); addDependency(manifest, domainName("some-pack"), semanticVersion("1.0.0")); - saveManifest(manifest).should.be.ok(); - const manifest2 = shouldHaveManifest(); + saveManifest(workDir, manifest).should.be.ok(); + const manifest2 = shouldHaveManifest(workDir); manifest2.should.be.deepEqual(manifest); }); + it("manifest-path is correct", function () { + const manifestPath = manifestPathFor(workDirName); + should(manifestPath).be.equal("test-openupm-cli/Packages/manifest.json"); + }); }); diff --git a/test/test-registry-client.ts b/test/test-registry-client.ts index da03aaaa..dc3444fa 100644 --- a/test/test-registry-client.ts +++ b/test/test-registry-client.ts @@ -24,27 +24,24 @@ describe("registry-client", function () { stopMockRegistry(); }); it("simple", async function () { - ( - await parseEnv( - { _global: { registry: exampleRegistryUrl } }, - { checkPath: false } - ) - ).should.be.ok(); + const env = await parseEnv( + { _global: { registry: exampleRegistryUrl } }, + false + ); + should(env).not.be.null(); const pkgInfoRemote = buildPackageInfo(packageA); registerRemotePkg(pkgInfoRemote); - const info = await fetchPackageInfo(packageA); + const info = await fetchPackageInfo(env!.registry, packageA); should(info).deepEqual(pkgInfoRemote); }); it("404", async function () { - ( - await parseEnv( - { _global: { registry: exampleRegistryUrl } }, - { checkPath: false } - ) - ).should.be.ok(); - + const env = await parseEnv( + { _global: { registry: exampleRegistryUrl } }, + false + ); + should(env).not.be.null(); registerMissingPackage(packageA); - const info = await fetchPackageInfo(packageA); + const info = await fetchPackageInfo(env!.registry, packageA); (info === undefined).should.be.ok(); }); });