Skip to content

Commit 5c3a0b3

Browse files
authored
refactor(front-end): enable checkJs, add missing JSDoc and fix all applications errors (#781)
1 parent 3286213 commit 5c3a0b3

52 files changed

Lines changed: 1822 additions & 689 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/easy-schools-unite.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@nodesecure/cli": major
3+
---
4+
5+
Enable checkJS and add missing JSDoc and fix all application errors

eslint.config.mjs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ export default [
1010
jsdoc
1111
},
1212
rules: {
13-
"jsdoc/no-undefined-types": ["warn", {
14-
disableReporting: true,
15-
markVariablesAsUsed: true
16-
}]
13+
"jsdoc/no-undefined-types": [
14+
"warn", {
15+
disableReporting: true,
16+
markVariablesAsUsed: true
17+
}
18+
],
19+
"no-inline-comments": "off"
1720
}
1821
},
1922
{

workspaces/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"@openally/httpie": "1.1.2",
7070
"@playwright/test": "1.61.1",
7171
"@stylistic/stylelint-plugin": "5.1.0",
72+
"@types/semver": "7.7.1",
7273
"esbuild": "0.28.1",
7374
"highlight.js": "11.11.1",
7475
"postcss-lit": "1.4.1",

workspaces/cli/public/common/utils.js

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export function extractEmojis(strWithEmojis) {
3131
* @param {keyof HTMLElementTagNameMap} kind
3232
* @param {object} [options]
3333
* @param {string[]} [options.classList]
34-
* @param {HTMLElement[]} [options.childs]
34+
* @param {(Node | null)[]} [options.childs]
3535
* @param {Record<string, any>} [options.attributes]
3636
* @param {Record<string, any>} [options.styles]
3737
* @param {string | null} [options.text]
@@ -136,7 +136,7 @@ export function parseRepositoryUrl(repository = {}, defaultValue = null) {
136136

137137
/**
138138
* @param {string} title
139-
* @param {string} value
139+
* @param {string | number} value
140140
* @param {Record<string, any>} options
141141
* @returns {HTMLElement}
142142
*/
@@ -148,11 +148,12 @@ export function createLiField(title, value, options = {}) {
148148
let elementToAppend;
149149

150150
if (isLink) {
151-
const textValue = value.length > 26 ? `${value.slice(0, 26)}...` : value;
152-
elementToAppend = createLink(value, textValue);
151+
const href = /** @type {string} */ (value);
152+
const textValue = href.length > 26 ? `${href.slice(0, 26)}...` : href;
153+
elementToAppend = createLink(href, textValue);
153154
}
154155
else {
155-
elementToAppend = createDOMElement("p", { text: value });
156+
elementToAppend = createDOMElement("p", { text: String(value) });
156157
}
157158
liElement.appendChild(elementToAppend);
158159

@@ -163,7 +164,7 @@ export function createLiField(title, value, options = {}) {
163164
* @param {HTMLElement} node - The parent DOM element.
164165
* @param {string[]} items - Array of strings to display.
165166
* @param {Object} [options] - Optional configuration options.
166-
* @param {Function} [options.onclick] - Callback function (event, item).
167+
* @param {(event: Event, item: string) => void} [options.onclick] - Callback function (event, item).
167168
* @param {boolean} [options.hideItems] - Hide items if needed.
168169
* @param {number} [options.hideItemsLength] - Number of visible elements before masking.
169170
* @returns {void}
@@ -307,6 +308,48 @@ export function hideOnClickOutside(
307308
return outsideClickListener;
308309
}
309310

311+
/**
312+
* Returns the i18n dictionary for the given language (defaults to the current language).
313+
*
314+
* Works around `window.i18n`'s declared type being widened to `Record<string, unknown>`
315+
* by a third-party ambient declaration (`@nodesecure/vis-network`'s `utils.d.ts`).
316+
*
317+
* @param {string} [lang]
318+
* @returns {Record<string, Record<string, string>>}
319+
*/
320+
export function getI18n(lang = currentLang()) {
321+
return /** @type {Record<string, Record<string, string>>} */ (
322+
window.i18n[lang]
323+
);
324+
}
325+
326+
/**
327+
* Returns the application settings config.
328+
*
329+
* Works around `window.settings`'s declared type being unreliably shadowed by a
330+
* conflicting third-party ambient declaration (`@nodesecure/vis-network`'s
331+
* `dataset.d.ts` declares `Window.settings: { config: { showFriendlyDependencies } }`).
332+
*
333+
* @returns {import("../types.js").AppConfig}
334+
*/
335+
export function getSettingsConfig() {
336+
return /** @type {import("../types.js").AppConfig} */ (/** @type {unknown} */ (
337+
window.settings.config
338+
));
339+
}
340+
341+
/**
342+
* `window.navigation` collides with the browser's native, read-only Navigation API.
343+
* The app intentionally shadows it with its own `ViewNavigation` controller.
344+
*
345+
* @returns {import("../components/navigation/navigation.js").ViewNavigation}
346+
*/
347+
export function getNavigation() {
348+
return /** @type {import("../components/navigation/navigation.js").ViewNavigation} */ (/** @type {unknown} */ (
349+
window.navigation
350+
));
351+
}
352+
310353
/** @returns {string} */
311354
export function currentLang() {
312355
const detectedLang = document.getElementById("lang")?.dataset.lang;

workspaces/cli/public/components/bundlephobia/bundlephobia.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,21 @@ class Bundlephobia extends LitElement {
8484
version: { type: String }
8585
};
8686

87+
constructor() {
88+
super();
89+
/** @type {string} */
90+
this.name = "";
91+
/** @type {string} */
92+
this.version = "";
93+
}
94+
8795
#bunldeTask = new Task(this, {
8896
task: async([name, version]) => {
8997
const {
9098
gzip, size, dependencySizes
91-
} = await getJSON(`/bundle/${this.#httpName(name)}/${version}`);
99+
} = /** @type {{ gzip: number, size: number, dependencySizes: { approximateSize: number }[] }} */ (
100+
await getJSON(`/bundle/${this.#httpName(name)}/${version}`)
101+
);
92102
const fullSize = dependencySizes.reduce((prev, curr) => prev + curr.approximateSize, 0);
93103

94104
return {
@@ -100,6 +110,9 @@ class Bundlephobia extends LitElement {
100110
args: () => [this.name, this.version]
101111
});
102112

113+
/**
114+
* @param {string} name
115+
*/
103116
#httpName(name) {
104117
return name.replaceAll("/", "%2F");
105118
}

workspaces/cli/public/components/command-palette/command-palette-panels.js

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { repeat } from "lit/directives/repeat.js";
44
import { classMap } from "lit/directives/class-map.js";
55

66
// Import Internal Dependencies
7-
import { currentLang } from "../../common/utils.js";
7+
import * as utils from "../../common/utils.js";
88
import {
99
FLAG_LIST,
1010
SIZE_PRESETS,
@@ -23,10 +23,29 @@ const kListTitleKeys = {
2323
};
2424

2525
/**
26-
* @param {{ linker: Map, queries: Array, inputValue: string, onAdd: Function, onRemove: Function }} props
26+
* @returns {Record<string, string>}
27+
*/
28+
function getSearchCommandI18n() {
29+
return /** @type {Record<string, string>} */ (/** @type {unknown} */ (utils.getI18n().search_command));
30+
}
31+
32+
/**
33+
* @typedef {import("@nodesecure/vis-network").LinkerEntry} LinkerEntry
34+
* @typedef {{ filter: string, value: string }} SearchQuery
35+
* @typedef {{ display: string, value: string, hint?: string }} HelperValue
36+
*/
37+
38+
/**
39+
* @param {{
40+
* linker: Map<number, LinkerEntry>,
41+
* queries: SearchQuery[],
42+
* inputValue: string,
43+
* onAdd: (filter: string, value: string) => void,
44+
* onRemove: (filter: string, value: string) => void
45+
* }} props
2746
*/
2847
export function renderFlagPanel({ linker, queries, inputValue, onAdd, onRemove }) {
29-
const i18n = window.i18n[currentLang()].search_command;
48+
const i18n = getSearchCommandI18n();
3049
const flagCounts = getFlagCounts(linker);
3150
const activeFlags = new Set(
3251
queries
@@ -65,10 +84,10 @@ export function renderFlagPanel({ linker, queries, inputValue, onAdd, onRemove }
6584
}
6685

6786
/**
68-
* @param {{ activeFilter: string, onAdd: Function }} props
87+
* @param {{ activeFilter: string, onAdd: (filter: string, value: string) => void }} props
6988
*/
7089
export function renderRangePanel({ activeFilter, onAdd }) {
71-
const i18n = window.i18n[currentLang()].search_command;
90+
const i18n = getSearchCommandI18n();
7291
const isSizeFilter = activeFilter === "size";
7392
const presets = isSizeFilter ? SIZE_PRESETS : VERSION_PRESETS;
7493
const title = isSizeFilter ? i18n.section_size : i18n.section_version;
@@ -93,12 +112,19 @@ export function renderRangePanel({ activeFilter, onAdd }) {
93112
}
94113

95114
/**
96-
* @param {{ linker: Map, activeFilter: string, helpers: Array, selectedIndex: number, onAdd: Function }} props
115+
* @param {{
116+
* linker: Map<number, LinkerEntry>,
117+
* activeFilter: string,
118+
* helpers: HelperValue[],
119+
* selectedIndex: number,
120+
* onAdd: (filter: string, value: string) => void
121+
* }} props
97122
*/
98123
export function renderListPanel({ linker, activeFilter, helpers, selectedIndex, onAdd }) {
99-
const i18n = window.i18n[currentLang()].search_command;
124+
const i18n = getSearchCommandI18n();
100125
const counts = getFilterValueCounts(linker, activeFilter);
101-
const title = i18n[kListTitleKeys[activeFilter]] ?? activeFilter;
126+
const titleI18nKey = /** @type {Record<string, string>} */ (kListTitleKeys)[activeFilter];
127+
const title = i18n[titleI18nKey] ?? activeFilter;
102128

103129
return html`
104130
<div class="section">
@@ -117,10 +143,10 @@ export function renderListPanel({ linker, activeFilter, helpers, selectedIndex,
117143
}
118144

119145
/**
120-
* @param {{ helpers: Array, selectedIndex: number, onSelect: Function }} props
146+
* @param {{ helpers: HelperValue[], selectedIndex: number, onSelect: (helper: HelperValue) => void }} props
121147
*/
122148
export function renderFilterList({ helpers, selectedIndex, onSelect }) {
123-
const i18n = window.i18n[currentLang()].search_command;
149+
const i18n = getSearchCommandI18n();
124150

125151
return html`
126152
<div class="section">
@@ -138,10 +164,13 @@ export function renderFilterList({ helpers, selectedIndex, onSelect }) {
138164
}
139165

140166
/**
141-
* @param {{ presets: Array, onApply: Function }} props
167+
* @param {{
168+
* presets: { id: string, filter: string, value: string }[],
169+
* onApply: (preset: { id: string, filter: string, value: string }) => void
170+
* }} props
142171
*/
143172
export function renderPresets({ presets, onApply }) {
144-
const i18n = window.i18n[currentLang()].search_command;
173+
const i18n = getSearchCommandI18n();
145174

146175
return html`
147176
<div class="section">
@@ -161,10 +190,13 @@ export function renderPresets({ presets, onApply }) {
161190
}
162191

163192
/**
164-
* @param {{ actions: Array<{ id: string, label: string, kbd: string|null }>, onExecute: Function }} props
193+
* @param {{
194+
* actions: { id: string, label: string, kbd: string|null }[],
195+
* onExecute: (action: { id: string, label: string, kbd: string|null }) => void
196+
* }} props
165197
*/
166198
export function renderActions({ actions, onExecute }) {
167-
const i18n = window.i18n[currentLang()].search_command;
199+
const i18n = getSearchCommandI18n();
168200

169201
return html`
170202
<div class="section">
@@ -214,14 +246,19 @@ export function renderIgnorePanel({ title, items, ignored, onToggle }) {
214246
}
215247

216248
/**
217-
* @param {{ results: Array, selectedIndex: number, helperCount: number, onFocus: Function }} props
249+
* @param {{
250+
* results: { id: string, flags: string, name: string, version: string }[],
251+
* selectedIndex: number,
252+
* helperCount: number,
253+
* onFocus: (id: string) => void
254+
* }} props
218255
*/
219256
export function renderResults({ results, selectedIndex, helperCount, onFocus }) {
220257
if (results.length === 0) {
221258
return nothing;
222259
}
223260

224-
const i18n = window.i18n[currentLang()].search_command;
261+
const i18n = getSearchCommandI18n();
225262

226263
return html`
227264
<div class="section">

0 commit comments

Comments
 (0)