Skip to content

Commit

Permalink
feat(help): Skip version checks if it will cause permission prompts
Browse files Browse the repository at this point in the history
When a user hasn't granted net permissions to the default upgrade provider,
they would be prompted to allow it when running the `help`/`--help` command.

This commit adds an extra method to `Provider` where a provider should check
any permissions it needs to return available versions have been pre-granted.

If the necessary permissions have NOT been granted, the help command will
skip checking for newer versions. The upgrade command is not affected.

BREAKING CHANGE: Custom `Provider` implementations will have to implement `hasRequiredPermissions()`
  • Loading branch information
annervisser committed Oct 15, 2023
1 parent aa1311f commit d9d6a6a
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 3 deletions.
9 changes: 8 additions & 1 deletion command/upgrade/_check_version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ export async function checkVersion(cmd: Command<any>): Promise<void> {
if (!isUpgradeCommand(upgradeCommand)) {
return;
}

if (!await upgradeCommand.hasRequiredPermissions()) {
// If not all required permissions were pre-granted, skip the version check to prevent prompting user
return;
}
const latestVersion = await upgradeCommand.getLatestVersion();
const currentVersion = mainCommand.getVersion();

Expand All @@ -23,9 +28,11 @@ export async function checkVersion(cmd: Command<any>): Promise<void> {
}

function isUpgradeCommand(command: unknown): command is UpgradeCommandImpl {
return command instanceof Command && "getLatestVersion" in command;
return command instanceof Command && "getLatestVersion" in command &&
"hasRequiredPermissions" in command;
}

interface UpgradeCommandImpl {
hasRequiredPermissions(): Promise<boolean>;
getLatestVersion(): Promise<string>;
}
2 changes: 2 additions & 0 deletions command/upgrade/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export abstract class Provider {
protected readonly maxListSize: number = 25;
private maxCols = 8;

abstract hasRequiredPermissions(): Promise<boolean>;

abstract getVersions(name: string): Promise<Versions>;

abstract getRepositoryUrl(name: string): string;
Expand Down
12 changes: 11 additions & 1 deletion command/upgrade/provider/deno_land.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,28 @@ export class DenoLandProvider extends Provider {
name = "deno.land";
private readonly repositoryUrl = "https://deno.land/x/";
private readonly registryUrl = "https://deno.land/x/";
private readonly apiUrl = "https://cdn.deno.land/";
private readonly moduleName?: string;

constructor({ name }: DenoLandProviderOptions = {}) {
super();
this.moduleName = name;
}

async hasRequiredPermissions(): Promise<boolean> {
const apiUrl = new URL(this.apiUrl);
const permissionStatus = await Deno.permissions.query({
name: "net",
host: apiUrl.host,
});
return permissionStatus.state === "granted";
}

async getVersions(
name: string,
): Promise<Versions> {
const response = await fetch(
`https://cdn.deno.land/${this.moduleName ?? name}/meta/versions.json`,
`${this.apiUrl}${this.moduleName ?? name}/meta/versions.json`,
);
if (!response.ok) {
throw new Error(
Expand Down
9 changes: 9 additions & 0 deletions command/upgrade/provider/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ export class GithubProvider extends Provider {
this.githubToken = token;
}

async hasRequiredPermissions(): Promise<boolean> {
const apiUrl = new URL(this.apiUrl);
const permissionStatus = await Deno.permissions.query({
name: "net",
host: apiUrl.host,
});
return permissionStatus.state === "granted";
}

async getVersions(
_name: string,
): Promise<GithubVersions> {
Expand Down
12 changes: 11 additions & 1 deletion command/upgrade/provider/nest_land.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,27 @@ export class NestLandProvider extends Provider {
name = "nest.land";
private readonly repositoryUrl = "https://nest.land/package/";
private readonly registryUrl = "https://x.nest.land/";
private readonly apiUrl = "https://nest.land/api/";
private readonly moduleName?: string;

constructor({ name }: NestLandProviderOptions = {}) {
super();
this.moduleName = name;
}

async hasRequiredPermissions(): Promise<boolean> {
const apiUrl = new URL(this.apiUrl);
const permissionStatus = await Deno.permissions.query({
name: "net",
host: apiUrl.host,
});
return permissionStatus.state === "granted";
}

async getVersions(
name: string,
): Promise<Versions> {
const response = await fetch(`https://nest.land/api/package-client`, {
const response = await fetch(`${this.apiUrl}package-client`, {
method: "post",
body: JSON.stringify({ data: { name: this.moduleName ?? name } }),
headers: { "Content-Type": "application/json" },
Expand Down
4 changes: 4 additions & 0 deletions command/upgrade/upgrade_command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ export class UpgradeCommand extends Command {
return versions;
}

public async hasRequiredPermissions(): Promise<boolean> {
return await this.getProvider().hasRequiredPermissions();
}

public async getLatestVersion(): Promise<string> {
const { latest } = await this.getVersions();
return latest;
Expand Down

0 comments on commit d9d6a6a

Please sign in to comment.