Skip to content

Commit 1f2664e

Browse files
feat(interface): disable external requests (#514)
1 parent ad46d2c commit 1f2664e

12 files changed

Lines changed: 128 additions & 52 deletions

File tree

i18n/english.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,9 @@ const ui = {
186186
warnings: "SAST Warnings to ignore",
187187
flags: "Flags (emojis) to ignore",
188188
network: "Network",
189-
showFriendly: "Show friendly dependencies"
189+
showFriendly: "Show friendly dependencies",
190+
security: "Security",
191+
disableExternalRequests: "Disable external requests"
190192
},
191193
shortcuts: {
192194
title: "Shortcuts",

i18n/french.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,9 @@ const ui = {
186186
warnings: "Avertissements à ignorer",
187187
flags: "Drapeau (emojis) à ignorer",
188188
network: "Réseau",
189-
showFriendly: "Afficher les dépendances amicales"
189+
showFriendly: "Afficher les dépendances amicales",
190+
security: "Sécurité",
191+
disableExternalRequests: "Désactiver les requêtes externes"
190192
},
191193
shortcuts: {
192194
title: "Raccourcis",

public/components/package/package.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@
137137
<div class="head-title">
138138
<p>bundlephobia</p>
139139
</div>
140-
<div class="bundlephobia">
140+
<div class="bundlephobia" id="bundlephobia-sizes">
141141
<div>
142142
<b class="size-min">N/A</b>
143143
<span>MIN</span>

public/components/package/package.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ export class PackageInfo {
8282
);
8383
packageHTMLElement.setAttribute("class", "slide-in");
8484

85+
if (window.settings.config.disableExternalRequests) {
86+
const bundlephobiaElement = packageHTMLElement.querySelector("#bundlephobia-sizes");
87+
const bundlephobiaTitleElement = bundlephobiaElement.previousElementSibling;
88+
bundlephobiaElement.classList.add("hidden");
89+
bundlephobiaTitleElement.classList.add("hidden");
90+
91+
return;
92+
}
93+
8594
new Bundlephobia(this.dependencyVersion.name, this.dependencyVersion.version)
8695
.fetchDataOnHttpServer()
8796
.catch(console.error);
@@ -149,7 +158,9 @@ export class PackageInfo {
149158
new Pannels.Warnings(this).generate(clone);
150159
new Pannels.Scripts(this).generate(clone);
151160
new Pannels.Vulnerabilities(this).generate(clone);
152-
new Pannels.Scorecard(this).generate(clone);
161+
if (window.settings.config.disableExternalRequests === false) {
162+
new Pannels.Scorecard(this).generate(clone);
163+
}
153164
new Pannels.Files(this).generate(clone);
154165

155166
return clone;

public/components/package/pannels/overview/overview.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,15 @@ export class Overview {
3232

3333
clone.querySelector(".fields")
3434
.appendChild(this.renderTopFields());
35-
this.renderNPMStats();
35+
if (window.settings.config.disableExternalRequests === false) {
36+
this.renderNPMStats();
37+
}
38+
else {
39+
const npmStatElement = clone.querySelector("#npm-stats");
40+
const npmStatTitleElement = npmStatElement.previousElementSibling;
41+
npmStatElement.classList.add("hidden");
42+
npmStatTitleElement.classList.add("hidden");
43+
}
3644
clone.querySelector(".fields.releases")
3745
.appendChild(this.renderReleases());
3846

@@ -47,7 +55,13 @@ export class Overview {
4755

4856
// Fetch Github/Gitlab stats
4957
const githubLink = this.package.links.github;
50-
if (githubLink.showInHeader) {
58+
if (window.settings.config.disableExternalRequests) {
59+
setTimeout(() => {
60+
document.querySelector(".gitlab-overview")?.classList.add("hidden");
61+
document.querySelector(".github-overview")?.classList.add("hidden");
62+
});
63+
}
64+
else if (githubLink.showInHeader) {
5165
setTimeout(() => {
5266
document.querySelector(".gitlab-overview")?.classList.add("hidden");
5367
});

public/components/views/home/home.js

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ export class HomeView {
4444
homeViewHTMLElement.innerHTML = "";
4545
homeViewHTMLElement.appendChild(this.render());
4646

47-
this.generateScorecard();
47+
if (window.settings.config.disableExternalRequests === false) {
48+
this.generateScorecard();
49+
}
4850
this.generateHeader();
4951
this.generateOverview();
5052
this.generatePackagesToWatch();
@@ -133,25 +135,25 @@ export class HomeView {
133135
document.getElementById("project-links").appendChild(linksFragment);
134136
}
135137

136-
async generateOverview() {
137-
const fragment = document.createDocumentFragment();
138+
#createOverviewDiv(icon, title, value) {
139+
const titleDiv = utils.createDOMElement("div", {
140+
className: "title",
141+
childs: [
142+
utils.createDOMElement("i", { className: icon }),
143+
utils.createDOMElement("p", { text: title })
144+
]
145+
});
138146

139-
function createOverviewDiv(icon, title, value) {
140-
const titleDiv = utils.createDOMElement("div", {
141-
className: "title",
142-
childs: [
143-
utils.createDOMElement("i", { className: icon }),
144-
utils.createDOMElement("p", { text: title })
145-
]
146-
});
147+
return utils.createDOMElement("div", {
148+
childs: [
149+
titleDiv,
150+
utils.createDOMElement("span", { text: value })
151+
]
152+
});
153+
}
147154

148-
return utils.createDOMElement("div", {
149-
childs: [
150-
titleDiv,
151-
utils.createDOMElement("span", { text: value })
152-
]
153-
});
154-
}
155+
async generateOverview() {
156+
const fragment = document.createDocumentFragment();
155157

156158
const { name } = this.secureDataSet.linker.get(0);
157159
let directDependencies = 0;
@@ -160,35 +162,27 @@ export class HomeView {
160162
directDependencies++;
161163
}
162164
}
163-
fragment.appendChild(createOverviewDiv(
165+
fragment.appendChild(this.#createOverviewDiv(
164166
"icon-cubes", `# ${window.i18n[this.lang].home.overview.dependencies}`, this.secureDataSet.dependenciesCount
165167
));
166-
fragment.appendChild(createOverviewDiv(
168+
fragment.appendChild(this.#createOverviewDiv(
167169
"icon-archive", window.i18n[this.lang].home.overview.totalSize, this.secureDataSet.prettySize
168170
));
169-
fragment.appendChild(createOverviewDiv(
171+
fragment.appendChild(this.#createOverviewDiv(
170172
"icon-link", `# ${window.i18n[this.lang].home.overview.directDeps}`, directDependencies
171173
));
172-
fragment.appendChild(createOverviewDiv(
174+
fragment.appendChild(this.#createOverviewDiv(
173175
"icon-sitemap", `# ${window.i18n[this.lang].home.overview.transitiveDeps}`, this.secureDataSet.indirectDependencies
174176
));
175177

176178
const homeOverviewElement = document.querySelector(".home--overview");
177179
homeOverviewElement.appendChild(fragment);
178180

179-
try {
180-
const { downloads } = await getJSON(`/downloads/${name.replaceAll("/", "%2F")}`);
181-
182-
if (downloads) {
183-
const formattedNumber = new Intl.NumberFormat("de-DE").format(downloads);
184-
homeOverviewElement.appendChild(createOverviewDiv(
185-
"icon-chart-bar", window.i18n[this.lang].home.overview.downloadsLastWeek, formattedNumber
186-
));
187-
}
188-
}
189-
catch {
190-
// DO NOTHING
181+
if (window.settings.config.disableExternalRequests) {
182+
return;
191183
}
184+
185+
this.generateDownloads();
192186
}
193187

194188
generatePackagesToWatch() {
@@ -322,6 +316,29 @@ export class HomeView {
322316
.render();
323317
}
324318

319+
async generateDownloads() {
320+
const homeOverviewElement = document.querySelector(".home--overview");
321+
const { name } = this.secureDataSet.linker.get(0);
322+
323+
try {
324+
const { downloads } = await getJSON(`/downloads/${name.replaceAll("/", "%2F")}`);
325+
326+
if (downloads) {
327+
const downloadsElement = document.querySelector(".home--overview div:has(i.icon-chart-bar)");
328+
downloadsElement?.remove();
329+
const formattedNumber = new Intl.NumberFormat("de-DE").format(downloads);
330+
homeOverviewElement.appendChild(this.#createOverviewDiv(
331+
"icon-chart-bar",
332+
window.i18n[this.lang].home.overview.downloadsLastWeek,
333+
formattedNumber
334+
));
335+
}
336+
}
337+
catch {
338+
// DO NOTHING
339+
}
340+
}
341+
325342
handleReport() {
326343
document.querySelector(".home--header--report").addEventListener("click", async() => {
327344
window.popup.open(

public/components/views/settings/settings.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ export class Settings {
3838
shortcutsSection: document.querySelector(".shortcuts"),
3939
/** @type {HTMLInputElement} */
4040
showFriendlyDependenciesCheckbox: document.querySelector("#show-friendly"),
41-
themeSelector: document.querySelector("#theme_selector")
41+
themeSelector: document.querySelector("#theme_selector"),
42+
disableExternalRequestsCheckbox: document.querySelector("#disable-external")
4243
};
4344

4445
this.saveButton = document.querySelector(".save");
@@ -50,7 +51,8 @@ export class Settings {
5051
...this.dom.warningsCheckbox,
5152
...this.dom.flagsCheckbox,
5253
this.dom.showFriendlyDependenciesCheckbox,
53-
this.dom.themeSelector
54+
this.dom.themeSelector,
55+
this.dom.disableExternalRequestsCheckbox
5456
];
5557
for (const formField of formFields) {
5658
formField.addEventListener("change", () => this.enableSaveButton());
@@ -200,7 +202,8 @@ export class Settings {
200202
defaultPackageMenu: this.dom.defaultPackageMenu.value || Settings.defaultMenuName,
201203
ignore: { flags: new Set(), warnings: new Set() },
202204
showFriendlyDependencies: this.dom.showFriendlyDependenciesCheckbox.checked,
203-
theme: this.dom.themeSelector.value
205+
theme: this.dom.themeSelector.value,
206+
disableExternalRequests: this.dom.disableExternalRequestsCheckbox.checked
204207
};
205208

206209
for (const checkbox of this.dom.warningsCheckbox) {
@@ -247,5 +250,6 @@ export class Settings {
247250
}
248251

249252
this.dom.showFriendlyDependenciesCheckbox.checked = this.config.showFriendlyDependencies;
253+
this.dom.disableExternalRequestsCheckbox.checked = this.config.disableExternalRequests;
250254
}
251255
}

public/main.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import * as utils from "./common/utils.js";
1818

1919
let secureDataSet;
2020
let nsn;
21+
let homeView;
2122
let searchview;
2223
let packageInfoOpened = false;
2324

@@ -125,7 +126,7 @@ async function init(options = {}) {
125126
});
126127
window.locker = new Locker(nsn);
127128
window.legend = new Legend({ show: window.settings.config.showFriendlyDependencies });
128-
new HomeView(secureDataSet, nsn);
129+
homeView ??= new HomeView(secureDataSet, nsn);
129130
searchview ??= new SearchView(secureDataSet, nsn);
130131

131132
window.addEventListener("package-info-closed", () => {
@@ -217,6 +218,7 @@ function onSettingsSaved(defaultConfig = null) {
217218
window.settings.config.ignore.warnings = warningsToIgnore;
218219
window.settings.config.ignore.flags = flagsToIgnore;
219220
window.settings.config.theme = theme;
221+
window.settings.config.disableExternalRequests = config.disableExternalRequests;
220222

221223
if (theme === "dark") {
222224
document.body.classList.add("dark");
@@ -247,6 +249,10 @@ function onSettingsSaved(defaultConfig = null) {
247249
else {
248250
window.legend.hide();
249251
}
252+
253+
if (config.disableExternalRequests === false) {
254+
homeView.generateDownloads();
255+
}
250256
}
251257

252258
if (defaultConfig) {

src/http-server/config.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ const experimentalWarnings = Object.entries(warnings)
1111
// CONSTANTS
1212
const kDefaultConfig = {
1313
defaultPackageMenu: "info",
14-
ignore: { flags: [], warnings: experimentalWarnings }
14+
ignore: { flags: [], warnings: experimentalWarnings },
15+
disableExternalRequests: false
1516
};
1617

1718
export async function get() {
@@ -24,13 +25,23 @@ export async function get() {
2425
flags,
2526
warnings
2627
} = {},
27-
theme
28+
theme,
29+
disableExternalRequests = false
2830
} = config;
2931
logger.info(
30-
`[config|get](defaultPackageMenu: ${defaultPackageMenu}|ignore-flag: ${flags}|ignore-warnings: ${warnings}|theme: ${theme})`
32+
// eslint-disable-next-line @stylistic/max-len
33+
`[config|get](defaultPackageMenu: ${defaultPackageMenu}|ignore-flag: ${flags}|ignore-warnings: ${warnings}|theme: ${theme}|disableExternalRequests${disableExternalRequests})`
3134
);
3235

33-
return { defaultPackageMenu, ignore: { flags, warnings }, theme };
36+
return {
37+
defaultPackageMenu,
38+
ignore: {
39+
flags,
40+
warnings
41+
},
42+
theme,
43+
disableExternalRequests
44+
};
3445
}
3546
catch (err) {
3647
logger.error(`[config|get](error: ${err.message})`);

test/config.test.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ describe("config", { concurrency: 1 }, () => {
3232
defaultPackageMenu: "info",
3333
ignore: { flags: [], warnings: Object.entries(warnings)
3434
.filter(([_, { experimental }]) => experimental)
35-
.map(([warning]) => warning) }
35+
.map(([warning]) => warning) },
36+
disableExternalRequests: false
3637
});
3738
});
3839

@@ -43,7 +44,8 @@ describe("config", { concurrency: 1 }, () => {
4344
flags: ["foo"],
4445
warnings: ["bar"]
4546
},
46-
theme: "galaxy"
47+
theme: "galaxy",
48+
disableExternalRequests: true
4749
};
4850
await cacache.put(CACHE_PATH, kConfigKey, JSON.stringify(expectedConfig));
4951
const value = await get();
@@ -58,7 +60,8 @@ describe("config", { concurrency: 1 }, () => {
5860
flags: ["foz"],
5961
warnings: ["baz"]
6062
},
61-
theme: "galactic"
63+
theme: "galactic",
64+
disableExternalRequests: true
6265
};
6366
await set(expectedConfig);
6467
const value = await get();

0 commit comments

Comments
 (0)