Skip to content

Commit d9d6a6a

Browse files
committed
feat(help): Skip version checks if it will cause permission prompts
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()`
1 parent aa1311f commit d9d6a6a

File tree

6 files changed

+45
-3
lines changed

6 files changed

+45
-3
lines changed

command/upgrade/_check_version.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ export async function checkVersion(cmd: Command<any>): Promise<void> {
1010
if (!isUpgradeCommand(upgradeCommand)) {
1111
return;
1212
}
13+
14+
if (!await upgradeCommand.hasRequiredPermissions()) {
15+
// If not all required permissions were pre-granted, skip the version check to prevent prompting user
16+
return;
17+
}
1318
const latestVersion = await upgradeCommand.getLatestVersion();
1419
const currentVersion = mainCommand.getVersion();
1520

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

2530
function isUpgradeCommand(command: unknown): command is UpgradeCommandImpl {
26-
return command instanceof Command && "getLatestVersion" in command;
31+
return command instanceof Command && "getLatestVersion" in command &&
32+
"hasRequiredPermissions" in command;
2733
}
2834

2935
interface UpgradeCommandImpl {
36+
hasRequiredPermissions(): Promise<boolean>;
3037
getLatestVersion(): Promise<string>;
3138
}

command/upgrade/provider.ts

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export abstract class Provider {
2121
protected readonly maxListSize: number = 25;
2222
private maxCols = 8;
2323

24+
abstract hasRequiredPermissions(): Promise<boolean>;
25+
2426
abstract getVersions(name: string): Promise<Versions>;
2527

2628
abstract getRepositoryUrl(name: string): string;

command/upgrade/provider/deno_land.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,28 @@ export class DenoLandProvider extends Provider {
88
name = "deno.land";
99
private readonly repositoryUrl = "https://deno.land/x/";
1010
private readonly registryUrl = "https://deno.land/x/";
11+
private readonly apiUrl = "https://cdn.deno.land/";
1112
private readonly moduleName?: string;
1213

1314
constructor({ name }: DenoLandProviderOptions = {}) {
1415
super();
1516
this.moduleName = name;
1617
}
1718

19+
async hasRequiredPermissions(): Promise<boolean> {
20+
const apiUrl = new URL(this.apiUrl);
21+
const permissionStatus = await Deno.permissions.query({
22+
name: "net",
23+
host: apiUrl.host,
24+
});
25+
return permissionStatus.state === "granted";
26+
}
27+
1828
async getVersions(
1929
name: string,
2030
): Promise<Versions> {
2131
const response = await fetch(
22-
`https://cdn.deno.land/${this.moduleName ?? name}/meta/versions.json`,
32+
`${this.apiUrl}${this.moduleName ?? name}/meta/versions.json`,
2333
);
2434
if (!response.ok) {
2535
throw new Error(

command/upgrade/provider/github.ts

+9
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ export class GithubProvider extends Provider {
2828
this.githubToken = token;
2929
}
3030

31+
async hasRequiredPermissions(): Promise<boolean> {
32+
const apiUrl = new URL(this.apiUrl);
33+
const permissionStatus = await Deno.permissions.query({
34+
name: "net",
35+
host: apiUrl.host,
36+
});
37+
return permissionStatus.state === "granted";
38+
}
39+
3140
async getVersions(
3241
_name: string,
3342
): Promise<GithubVersions> {

command/upgrade/provider/nest_land.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,27 @@ export class NestLandProvider extends Provider {
88
name = "nest.land";
99
private readonly repositoryUrl = "https://nest.land/package/";
1010
private readonly registryUrl = "https://x.nest.land/";
11+
private readonly apiUrl = "https://nest.land/api/";
1112
private readonly moduleName?: string;
1213

1314
constructor({ name }: NestLandProviderOptions = {}) {
1415
super();
1516
this.moduleName = name;
1617
}
1718

19+
async hasRequiredPermissions(): Promise<boolean> {
20+
const apiUrl = new URL(this.apiUrl);
21+
const permissionStatus = await Deno.permissions.query({
22+
name: "net",
23+
host: apiUrl.host,
24+
});
25+
return permissionStatus.state === "granted";
26+
}
27+
1828
async getVersions(
1929
name: string,
2030
): Promise<Versions> {
21-
const response = await fetch(`https://nest.land/api/package-client`, {
31+
const response = await fetch(`${this.apiUrl}package-client`, {
2232
method: "post",
2333
body: JSON.stringify({ data: { name: this.moduleName ?? name } }),
2434
headers: { "Content-Type": "application/json" },

command/upgrade/upgrade_command.ts

+4
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ export class UpgradeCommand extends Command {
8989
return versions;
9090
}
9191

92+
public async hasRequiredPermissions(): Promise<boolean> {
93+
return await this.getProvider().hasRequiredPermissions();
94+
}
95+
9296
public async getLatestVersion(): Promise<string> {
9397
const { latest } = await this.getVersions();
9498
return latest;

0 commit comments

Comments
 (0)