Skip to content

Commit 75b5275

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 dfb1762 commit 75b5275

File tree

8 files changed

+63
-3
lines changed

8 files changed

+63
-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
@@ -61,6 +61,8 @@ export abstract class Provider {
6161
this.logger = logger;
6262
}
6363

64+
abstract hasRequiredPermissions(): Promise<boolean>;
65+
6466
abstract getVersions(name: string): Promise<Versions>;
6567

6668
abstract getRepositoryUrl(name: string, version?: 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, main, logger }: DenoLandProviderOptions = {}) {
1415
super({ main, logger });
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
@@ -30,6 +30,15 @@ export class GithubProvider extends Provider {
3030
this.githubToken = token;
3131
}
3232

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

command/upgrade/provider/jsr.ts

+9
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ export class JsrProvider extends Provider {
4040
: options.name;
4141
}
4242

43+
async hasRequiredPermissions(): Promise<boolean> {
44+
const apiUrl = new URL(this.repositoryUrl);
45+
const permissionStatus = await Deno.permissions.query({
46+
name: "net",
47+
host: apiUrl.host,
48+
});
49+
return permissionStatus.state === "granted";
50+
}
51+
4352
async getVersions(
4453
name: string,
4554
): Promise<Versions> {

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, main, logger }: NestLandProviderOptions = {}) {
1415
super({ main, logger });
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/provider/npm.ts

+9
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ export class NpmProvider extends Provider {
3131
}
3232
}
3333

34+
async hasRequiredPermissions(): Promise<boolean> {
35+
const apiUrl = new URL(this.apiUrl);
36+
const permissionStatus = await Deno.permissions.query({
37+
name: "net",
38+
host: apiUrl.host,
39+
});
40+
return permissionStatus.state === "granted";
41+
}
42+
3443
async getVersions(
3544
name: string,
3645
): Promise<Versions> {

command/upgrade/upgrade_command.ts

+4
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ export class UpgradeCommand extends Command {
169169
return versions;
170170
}
171171

172+
public async hasRequiredPermissions(): Promise<boolean> {
173+
return await this.getProvider().hasRequiredPermissions();
174+
}
175+
172176
public async getLatestVersion(): Promise<string> {
173177
const { latest } = await this.getVersions();
174178
return latest;

0 commit comments

Comments
 (0)