Skip to content

Commit

Permalink
refactor: add registry-url type
Browse files Browse the repository at this point in the history
  • Loading branch information
ComradeVanti committed Nov 25, 2023
1 parent dd0eab6 commit b4fecdb
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 75 deletions.
39 changes: 17 additions & 22 deletions src/cmd-login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@ import { assertIsNpmClientError, getNpmClient } from "./registry-client";

import log from "./logger";

import { GlobalOptions, Registry } from "./types/global";
import { GlobalOptions } from "./types/global";
import {
getUpmConfigDir,
loadUpmConfig,
saveUpmConfig,
} from "./utils/upm-config";
import { parseEnv } from "./utils/env";
import {
RegistryUrl,
registryUrl,
removeTrailingSlash,
} from "./types/registry-url";

export type LoginOptions = {
username?: string;
Expand All @@ -33,9 +38,9 @@ export const login = async function (options: LoginOptions) {
options.password = await promptly.password("Password: ");
if (!options.email) options.email = await promptly.prompt("Email: ");
if (!options._global.registry)
options._global.registry = await promptly.prompt("Registry: ", {
validator: [validateRegistry],
});
options._global.registry = (await promptly.prompt("Registry: ", {
validator: [registryUrl],
})) as RegistryUrl;
let token: string | null = null;
let _auth: string | null = null;
if (options.basicAuth) {
Expand All @@ -48,7 +53,7 @@ export const login = async function (options: LoginOptions) {
username: options.username,
password: options.password,
email: options.email,
registry: options._global.registry,
registry: options._global.registry as RegistryUrl,
});
if (result.code == 1) return result.code;
if (!result.token) {
Expand All @@ -58,7 +63,7 @@ export const login = async function (options: LoginOptions) {
token = result.token;
// write npm token
await writeNpmToken({
registry: options._global.registry,
registry: options._global.registry as RegistryUrl,
token: result.token,
});
}
Expand All @@ -69,7 +74,7 @@ export const login = async function (options: LoginOptions) {
alwaysAuth: options.alwaysAuth || false,
basicAuth: options.basicAuth || false,
email: options.email,
registry: options._global.registry,
registry: options._global.registry as RegistryUrl,
token,
});
};
Expand All @@ -86,7 +91,7 @@ const npmLogin = async function ({
username: string;
password: string;
email: string;
registry: Registry;
registry: RegistryUrl;
}) {
const client = getNpmClient();
try {
Expand Down Expand Up @@ -125,7 +130,7 @@ const writeNpmToken = async function ({
registry,
token,
}: {
registry: Registry;
registry: RegistryUrl;
token: string;
}) {
const configPath = getNpmrcPath();
Expand Down Expand Up @@ -160,7 +165,7 @@ export const getNpmrcPath = function () {
*/
export const generateNpmrcLines = function (
content: string,
registry: Registry,
registry: RegistryUrl,
token: string
) {
let lines = content ? content.split("\n") : [];
Expand Down Expand Up @@ -189,16 +194,6 @@ export const generateNpmrcLines = function (
return lines;
};

/**
* http protocal validator
* @param {*} 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;
};

/**
* Write npm token to Unity
*/
Expand All @@ -214,7 +209,7 @@ const writeUnityToken = async function ({
alwaysAuth: boolean;
basicAuth: boolean;
email: string;
registry: Registry;
registry: RegistryUrl;
token: string | null;
}) {
// Create config dir if necessary
Expand All @@ -223,7 +218,7 @@ const writeUnityToken = async function ({
const config = (await loadUpmConfig(configDir)) || {};
if (!config.npmAuth) config.npmAuth = {};
// Remove ending slash of registry
if (registry.endsWith("/")) registry = registry.replace(/\/$/, "");
registry = removeTrailingSlash(registry);

if (basicAuth) {
if (_auth === null) throw new Error("Auth is null");
Expand Down
5 changes: 3 additions & 2 deletions src/cmd-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import log from "./logger";
import { is404Error, isHttpError } from "./utils/error-type-guards";
import * as os from "os";
import assert from "assert";
import { GlobalOptions, PkgInfo, Registry } from "./types/global";
import { GlobalOptions, PkgInfo } from "./types/global";
import { tryGetLatestVersion } from "./utils/pkg-info";
import { env, parseEnv } from "./utils/env";
import { DomainName } from "./types/domain-name";
import { SemanticVersion } from "./types/semantic-version";
import { RegistryUrl } from "./types/registry-url";

type DateString = string;

Expand Down Expand Up @@ -40,7 +41,7 @@ const getNpmFetchOptions = function (): Options {

const searchEndpoint = async function (
keyword: string,
registry?: Registry
registry?: RegistryUrl
): Promise<TableRow[] | undefined> {
if (!registry) registry = env.registry;
try {
Expand Down
5 changes: 3 additions & 2 deletions src/registry-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import RegClient, {
import log from "./logger";
import request from "request";
import assert, { AssertionError } from "assert";
import { Dependency, NameVersionPair, PkgInfo, Registry } from "./types/global";
import { Dependency, NameVersionPair, PkgInfo } from "./types/global";
import { env } from "./utils/env";
import _ from "lodash";
import { tryGetLatestVersion } from "./utils/pkg-info";
import { DomainName, isInternalPackage } from "./types/domain-name";
import { SemanticVersion } from "./types/semantic-version";
import { packageReference } from "./types/package-reference";
import { RegistryUrl } from "./types/registry-url";

export type NpmClient = {
rawClient: RegClient;
Expand Down Expand Up @@ -92,7 +93,7 @@ export const getNpmClient = (): NpmClient => {
// Fetch package info json from registry
export const fetchPackageInfo = async function (
name: DomainName,
registry?: Registry
registry?: RegistryUrl
): Promise<PkgInfo | undefined> {
if (!registry) registry = env.registry;
const pkgPath = `${registry}/${name}`;
Expand Down
15 changes: 7 additions & 8 deletions src/types/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import { DomainName } from "./domain-name";
import { PackageUrl } from "./package-url";
import { SemanticVersion } from "./semantic-version";
import { PackageId } from "./package-id";
import { RegistryUrl } from "./registry-url";

export type Region = "us" | "cn";

export type Registry = string;

export type EditorVersion = {
major: number;
minor: number;
Expand All @@ -26,11 +25,11 @@ export type Env = {
color: boolean;
systemUser: boolean;
wsl: boolean;
npmAuth?: Record<Registry, UpmAuth>;
auth: Record<Registry, NpmAuth>;
npmAuth?: Record<RegistryUrl, UpmAuth>;
auth: Record<RegistryUrl, NpmAuth>;
upstream: boolean;
upstreamRegistry: string;
registry: string;
upstreamRegistry: RegistryUrl;
registry: RegistryUrl;
namespace: DomainName | IpAddress;
editorVersion: string | null;
region: Region;
Expand Down Expand Up @@ -120,7 +119,7 @@ export type PkgManifest = {
};

export type GlobalOptions = {
registry?: Registry;
registry?: string;
verbose?: boolean;
color?: boolean;
upstream?: boolean;
Expand All @@ -136,5 +135,5 @@ export type UpmAuth = {
} & ({ token: string } | { _auth: string });

export type UPMConfig = {
npmAuth?: Record<Registry, UpmAuth>;
npmAuth?: Record<RegistryUrl, UpmAuth>;
};
45 changes: 45 additions & 0 deletions src/types/registry-url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Brand } from "ts-brand";
import assert from "assert";

/**
* A string of a http-based registry-url
*/
export type RegistryUrl = Brand<string, "RegistryUrl">;

/**
* Checks that a string is a valid registry
* @param s The string
*/
export function isRegistryUrl(s: string): s is RegistryUrl {
return /http(s?):\/\//.test(s);
}

/**
* Constructs a registry-url
* @param s The string
* @throws assert.AssertionError if string does not have valid format
*/
export function registryUrl(s: string): RegistryUrl {
assert(isRegistryUrl(s), `"${s}" is url`);
return s;
}

/**
* Removes trailing slash from a registry-url
* @param registry The url
*/
export function removeTrailingSlash(registry: RegistryUrl): RegistryUrl {
if (registry.endsWith("/")) return registry.slice(0, -1) as RegistryUrl;
return registry;
}

/**
* Attempts to coerce a string into a registry-url, by
* - Prepending http if it is missing
* - Removing trailing slashes
* @param s The string
*/
export function coerceRegistryUrl(s: string): RegistryUrl {
if (!s.toLowerCase().startsWith("http")) s = "http://" + s;
return removeTrailingSlash(registryUrl(s));
}
31 changes: 16 additions & 15 deletions src/utils/env.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { Env, GlobalOptions } from "../types/global";
import log from "../logger";
import chalk from "chalk";
import url from "url";
import { loadUpmConfig } from "./upm-config";
import path from "path";
import fs from "fs";
import yaml from "yaml";
import { isIpAddress } from "../types/ip-address";
import { namespaceFor, openUpmReverseDomainName } from "../types/domain-name";
import {
coerceRegistryUrl,
RegistryUrl,
registryUrl,
} from "../types/registry-url";
import url from "url";

export const env: Env = <Env>{};

Expand All @@ -17,13 +22,13 @@ export const parseEnv = async function (
{ checkPath }: { checkPath: unknown }
) {
// set defaults
env.registry = "https://package.openupm.com";
env.registry = registryUrl("https://package.openupm.com");
env.cwd = "";
env.manifestPath = "";
env.namespace = openUpmReverseDomainName;
env.upstream = true;
env.color = true;
env.upstreamRegistry = "https://packages.unity.com";
env.upstreamRegistry = registryUrl("https://packages.unity.com");
env.systemUser = false;
env.wsl = false;
env.editorVersion = null;
Expand All @@ -45,20 +50,16 @@ export const parseEnv = async function (
if (options._global.upstream === false) env.upstream = false;
// region cn
if (options._global.cn === true) {
env.registry = "https://package.openupm.cn";
env.upstreamRegistry = "https://packages.unity.cn";
env.registry = registryUrl("https://package.openupm.cn");
env.upstreamRegistry = registryUrl("https://packages.unity.cn");
env.region = "cn";
log.notice("region", "cn");
}
// registry
if (options._global.registry) {
let registry = options._global.registry;
if (!registry.toLowerCase().startsWith("http"))
registry = "http://" + registry;
if (registry.endsWith("/")) registry = registry.slice(0, -1);
env.registry = registry;
env.registry = coerceRegistryUrl(options._global.registry);
// TODO: Check hostname for null
const hostname = url.parse(registry).hostname as string;
const hostname = url.parse(env.registry).hostname as string;
if (isIpAddress(hostname)) env.namespace = hostname;
else env.namespace = namespaceFor(hostname);
}
Expand All @@ -68,9 +69,9 @@ export const parseEnv = async function (
const upmConfig = await loadUpmConfig();
if (upmConfig) {
env.npmAuth = upmConfig.npmAuth;
if (env.npmAuth) {
for (const reg in env.npmAuth) {
const regAuth = env.npmAuth[reg];
if (env.npmAuth !== undefined) {
(Object.keys(env.npmAuth) as RegistryUrl[]).forEach((reg) => {
const regAuth = env.npmAuth![reg];
if ("token" in regAuth) {
env.auth[reg] = {
token: regAuth.token,
Expand All @@ -93,7 +94,7 @@ export const parseEnv = async function (
);
log.warn("env.auth", regAuth);
}
}
});
}
}
// log.verbose("env.npmAuth", env.npmAuth);
Expand Down
Loading

0 comments on commit b4fecdb

Please sign in to comment.