Skip to content

Commit 25460ab

Browse files
committed
(maint) Extract Puppet Forge function
Extract all puppet forge api calls to a single file. This makes sure we call the forge with the correct headers for all hover providers and provide a consistent interface to the forge. This makes a cosmetic change to how the metadata.json hover provider shows hover information by making it the same as the pupeptfile hover provider.
1 parent cfec859 commit 25460ab

File tree

4 files changed

+117
-136
lines changed

4 files changed

+117
-136
lines changed

src/extension.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { PuppetNodeGraphFeature } from './feature/PuppetNodeGraphFeature';
1616
import { PuppetResourceFeature } from './feature/PuppetResourceFeature';
1717
import { PuppetStatusBarFeature } from './feature/PuppetStatusBarFeature';
1818
import { UpdateConfigurationFeature } from './feature/UpdateConfigurationFeature';
19+
import { getPDKVersion } from './forge';
1920
import { ConnectionHandler } from './handler';
2021
import { StdioConnectionHandler } from './handlers/stdio';
2122
import { TcpConnectionHandler } from './handlers/tcp';
@@ -26,9 +27,6 @@ import { reporter } from './telemetry';
2627
import { PuppetFactsProvider } from './views/facts';
2728
import { PuppetfileProvider } from './views/puppetfile';
2829

29-
// eslint-disable-next-line @typescript-eslint/no-var-requires
30-
const axios = require('axios');
31-
3230
export const puppetLangID = 'puppet'; // don't change this
3331
export const puppetFileLangID = 'puppetfile'; // don't change this
3432
const debugType = 'Puppet'; // don't change this
@@ -287,11 +285,7 @@ async function notifyIfNewPDKVersion(context: vscode.ExtensionContext, settings:
287285
return;
288286
}
289287

290-
axios
291-
.get('https://s3.amazonaws.com/puppet-pdk/pdk/LATEST')
292-
.then((response) => {
293-
return response.data;
294-
})
288+
getPDKVersion(logger)
295289
.then((latestVersion) => {
296290
if (version !== latestVersion) {
297291
return vscode.window.showWarningMessage(
Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { getLocation } from 'jsonc-parser';
22
import * as vscode from 'vscode';
33
import { IFeature } from '../feature';
4+
import { buildMarkdown, getModuleInfo } from '../forge';
45
import { ILogger } from '../logging';
56
import { reporter } from '../telemetry';
67

@@ -18,11 +19,11 @@ export class PuppetModuleHoverFeature implements IFeature {
1819
export class PuppetModuleHoverProvider implements vscode.HoverProvider {
1920
constructor(public logger: ILogger) {}
2021

21-
provideHover(
22+
async provideHover(
2223
document: vscode.TextDocument,
2324
position: vscode.Position,
2425
token: vscode.CancellationToken,
25-
): Thenable<vscode.Hover> | null {
26+
): Promise<vscode.Hover> | null {
2627
const offset = document.offsetAt(position);
2728
const location = getLocation(document.getText(), offset);
2829

@@ -49,49 +50,9 @@ export class PuppetModuleHoverProvider implements vscode.HoverProvider {
4950

5051
const name = word.replace('"', '').replace('"', '').replace('/', '-');
5152

52-
return this.getModuleInfo(name).then(function (result: any) {
53-
const msg: string[] = [];
54-
msg.push(`### ${result.slug}`);
55-
56-
const releaseDate = new Date(result.releases[0].created_at);
57-
// eslint-disable-next-line @typescript-eslint/no-var-requires
58-
const dateformat = require('dateformat');
59-
msg.push(`\nLatest version: ${result.releases[0].version} (${dateformat(releaseDate, 'dS mmmm yyyy')})`);
60-
61-
if (result.endorsement !== null) {
62-
const endorsementCapitalized = result.endorsement.charAt(0).toUpperCase() + result.endorsement.slice(1);
63-
msg.push(`\nEndorsement: ${endorsementCapitalized}`);
64-
}
65-
66-
msg.push(`\nOwner: ${result.owner.slug}`);
67-
68-
const forgeUri = `https://forge.puppet.com/${result.owner.username}/${result.name}`;
69-
msg.push(`\nForge: [${forgeUri}](${forgeUri})\n`);
70-
71-
if (result.homepage_url !== null) {
72-
msg.push(`\nProject: [${result.homepage_url}](${result.homepage_url})\n`);
73-
}
74-
75-
const md = msg.join('\n');
76-
77-
return Promise.resolve(new vscode.Hover(new vscode.MarkdownString(md), range));
78-
});
79-
}
80-
81-
private getModuleInfo(name: string) {
82-
const options = {
83-
url: `https://forgeapi.puppet.com/v3/modules/${name}?exclude_fields=readme%20changelog%20license%20reference`,
84-
};
85-
return new Promise(function (resolve, reject) {
86-
// eslint-disable-next-line @typescript-eslint/no-var-requires
87-
const request = require('request');
88-
request.get(options, function (err, resp, body) {
89-
if (err) {
90-
reject(err);
91-
} else {
92-
resolve(JSON.parse(body));
93-
}
94-
});
95-
});
53+
const info = await getModuleInfo(name, this.logger);
54+
const markdown = buildMarkdown(info);
55+
const hoverinfo = new vscode.Hover(markdown, range);
56+
return hoverinfo;
9657
}
9758
}

src/feature/PuppetfileHoverFeature.ts

Lines changed: 3 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,10 @@
11
// const axios = require('axios');
2-
import axios from 'axios';
32
import * as vscode from 'vscode';
43
import { IFeature } from '../feature';
4+
import { buildMarkdown, getModuleInfo } from '../forge';
55
import { ILogger } from '../logging';
66
import { reporter } from '../telemetry';
77

8-
interface PuppetForgeModuleInfo {
9-
uri: string;
10-
slug: string;
11-
name: string;
12-
downloads: number;
13-
score: number;
14-
created: Date;
15-
updated: Date;
16-
endorsement: string;
17-
owner: { slug: string; username: string };
18-
forgeUrl: string;
19-
homepageUrl: string;
20-
version: number;
21-
summary: string;
22-
}
23-
248
class PuppetfileHoverProvider implements vscode.HoverProvider {
259
constructor(public readonly logger: ILogger) {}
2610

@@ -50,74 +34,11 @@ class PuppetfileHoverProvider implements vscode.HoverProvider {
5034
.replace("'", '')
5135
.replace("'", '');
5236

53-
const info = await this.getModuleInfo(text);
54-
const markdown = this.buildmarkdown(info);
37+
const info = await getModuleInfo(text, this.logger);
38+
const markdown = buildMarkdown(info);
5539
const hoverinfo = new vscode.Hover(markdown, range);
5640
return hoverinfo;
5741
}
58-
59-
private buildmarkdown(info: PuppetForgeModuleInfo): vscode.MarkdownString {
60-
const message = `## ${info.name}\n
61-
${info.summary}\n
62-
**Latest version:** ${info.version} (${info.created.toDateString()})\n
63-
**Forge**: [${info.forgeUrl}](${info.forgeUrl})\n
64-
**Project**: [${info.homepageUrl}](${info.homepageUrl})\n
65-
**Owner:** ${info.owner.username}\n
66-
**Endorsement:** ${info.endorsement?.toLocaleUpperCase()}\n
67-
**Score:** ${info.score}\n
68-
`;
69-
return new vscode.MarkdownString(message);
70-
}
71-
72-
private getModuleInfo(title: string): Promise<PuppetForgeModuleInfo> {
73-
return new Promise((resolve) => {
74-
return axios
75-
.get(`https://forgeapi.puppet.com/v3/modules/${title}`, {
76-
params: {
77-
// eslint-disable-next-line @typescript-eslint/camelcase
78-
exclude_fields: 'readme changelog license reference',
79-
},
80-
headers: {
81-
'Content-Type': 'application/json;charset=UTF-8',
82-
'User-Agent': 'puppet-vscode/0.27.0',
83-
},
84-
})
85-
.then((response) => {
86-
if (response.status !== 200) {
87-
this.logger.error(`Error getting Puppet forge data. Status: ${response.status}:${response.statusText}`);
88-
resolve();
89-
}
90-
91-
const info = response.data;
92-
const module = {
93-
uri: info.uri,
94-
slug: info.slug,
95-
name: info.name,
96-
downloads: info.downloads,
97-
score: info.feedback_score,
98-
created: new Date(info.created_at),
99-
updated: new Date(info.updated_at),
100-
endorsement: info.endorsement ?? '',
101-
forgeUrl: `https://forge.puppet.com/${info.owner.username}/${info.name}`,
102-
homepageUrl: info.homepage_url ?? '',
103-
version: info.current_release.version,
104-
owner: {
105-
uri: info.owner.uri,
106-
slug: info.owner.slug,
107-
username: info.owner.username,
108-
gravatar: info.owner.gravatar_id,
109-
},
110-
summary: info.current_release.metadata.summary,
111-
};
112-
113-
resolve(module);
114-
})
115-
.catch((error) => {
116-
this.logger.error(`Error getting Puppet forge data: ${error}`);
117-
resolve();
118-
});
119-
});
120-
}
12142
}
12243

12344
export class PuppetfileHoverFeature implements IFeature {

src/forge.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import axios from 'axios';
2+
import { MarkdownString } from 'vscode';
3+
import { ILogger } from './logging';
4+
5+
export interface PuppetForgeModuleInfo {
6+
uri: string;
7+
slug: string;
8+
name: string;
9+
downloads: number;
10+
score: number;
11+
created: Date;
12+
updated: Date;
13+
endorsement: string;
14+
owner: { slug: string; username: string };
15+
forgeUrl: string;
16+
homepageUrl: string;
17+
version: number;
18+
summary: string;
19+
}
20+
21+
export function buildMarkdown(info: PuppetForgeModuleInfo): MarkdownString {
22+
const message = `## ${info.name}\n
23+
${info.summary}\n
24+
**Latest version:** ${info.version} (${info.created.toDateString()})\n
25+
**Forge**: [${info.forgeUrl}](${info.forgeUrl})\n
26+
**Project**: [${info.homepageUrl}](${info.homepageUrl})\n
27+
**Owner:** ${info.owner.username}\n
28+
**Endorsement:** ${info.endorsement?.toLocaleUpperCase()}\n
29+
**Score:** ${info.score}\n
30+
`;
31+
return new MarkdownString(message);
32+
}
33+
34+
export function getPDKVersion(logger: ILogger): Promise<string> {
35+
return new Promise((resolve) => {
36+
return axios
37+
.get('https://s3.amazonaws.com/puppet-pdk/pdk/LATEST', {
38+
params: {
39+
// eslint-disable-next-line @typescript-eslint/camelcase
40+
exclude_fields: 'readme changelog license reference',
41+
},
42+
headers: {
43+
'Content-Type': 'application/json;charset=UTF-8',
44+
'User-Agent': 'puppet-vscode/0.27.1',
45+
},
46+
})
47+
.then((response) => {
48+
if (response.status !== 200) {
49+
logger.error(`Error getting Puppet forge data. Status: ${response.status}:${response.statusText}`);
50+
resolve();
51+
}
52+
return response.data;
53+
});
54+
});
55+
}
56+
57+
export function getModuleInfo(title: string, logger: ILogger): Promise<PuppetForgeModuleInfo> {
58+
return new Promise((resolve) => {
59+
return axios
60+
.get(`https://forgeapi.puppet.com/v3/modules/${title}`, {
61+
params: {
62+
// eslint-disable-next-line @typescript-eslint/camelcase
63+
exclude_fields: 'readme changelog license reference',
64+
},
65+
headers: {
66+
'Content-Type': 'application/json;charset=UTF-8',
67+
'User-Agent': 'puppet-vscode/0.27.1',
68+
},
69+
})
70+
.then((response) => {
71+
if (response.status !== 200) {
72+
logger.error(`Error getting Puppet forge data. Status: ${response.status}:${response.statusText}`);
73+
resolve();
74+
}
75+
76+
const info = response.data;
77+
const module = {
78+
uri: info.uri,
79+
slug: info.slug,
80+
name: info.name,
81+
downloads: info.downloads,
82+
score: info.feedback_score,
83+
created: new Date(info.created_at),
84+
updated: new Date(info.updated_at),
85+
endorsement: info.endorsement ?? '',
86+
forgeUrl: `https://forge.puppet.com/${info.owner.username}/${info.name}`,
87+
homepageUrl: info.homepage_url ?? '',
88+
version: info.current_release.version,
89+
owner: {
90+
uri: info.owner.uri,
91+
slug: info.owner.slug,
92+
username: info.owner.username,
93+
gravatar: info.owner.gravatar_id,
94+
},
95+
summary: info.current_release.metadata.summary,
96+
};
97+
98+
resolve(module);
99+
})
100+
.catch((error) => {
101+
logger.error(`Error getting Puppet forge data: ${error}`);
102+
resolve();
103+
});
104+
});
105+
}

0 commit comments

Comments
 (0)