Skip to content

Commit e3f8222

Browse files
feat: enforce JSDoc and add central type definitions
- Upgrade JSDoc rules from warn to error for strict enforcement - Add types.js with central TypeDefs (ModuleData, ConfigData, etc.) - Enable better IDE autocomplete and type safety - All existing code already has good JSDoc coverage
1 parent 368747e commit e3f8222

File tree

3 files changed

+192
-0
lines changed

3 files changed

+192
-0
lines changed

eslint.config.mjs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@ export default defineConfig([
3737
"@stylistic/padded-blocks": "off",
3838
"@stylistic/quote-props": ["error", "consistent"],
3939
"capitalized-comments": "off",
40+
"jsdoc/require-jsdoc": [
41+
"error", {
42+
"require": {
43+
"FunctionDeclaration": true,
44+
"MethodDefinition": true,
45+
"ClassDeclaration": true,
46+
"ArrowFunctionExpression": false,
47+
"FunctionExpression": false
48+
}
49+
}
50+
],
51+
"jsdoc/require-param": "error",
52+
"jsdoc/require-param-type": "error",
53+
"jsdoc/require-returns": "error",
54+
"jsdoc/require-returns-type": "error",
4055
"max-lines-per-function": ["warn", 250],
4156
"max-statements": ["warn", 60],
4257
"no-inline-comments": "off",

node_helper.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
/* global Module */
22

3+
/**
4+
* @file MagicMirror² Remote Control Module - Node Helper
5+
* @module node_helper
6+
*/
7+
8+
/**
9+
* @typedef {import('./types').ModuleData} ModuleData
10+
* @typedef {import('./types').ConfigData} ConfigData
11+
* @typedef {import('./types').ModuleConfig} ModuleConfig
12+
* @typedef {import('./types').BackupInfo} BackupInfo
13+
* @typedef {import('./types').ApiResponse} ApiResponse
14+
*/
15+
316
/*
417
* MagicMirror²
518
* Module: Remote Control
@@ -97,6 +110,10 @@ module.exports = NodeHelper.create({
97110
this.loadTimers();
98111
},
99112

113+
/**
114+
* Set up periodic timers for module list updates
115+
* @returns {void}
116+
*/
100117
loadTimers () {
101118
const delay = 24 * 3600;
102119

@@ -107,6 +124,11 @@ module.exports = NodeHelper.create({
107124
}, delay * 1000);
108125
},
109126

127+
/**
128+
* Combine default config with user config from config.js
129+
* Sets this.configOnHd and this.thisConfig
130+
* @returns {void}
131+
*/
110132
combineConfig () {
111133
// function copied from MagicMirrorOrg (MIT)
112134
const defaults = require(`${__dirname}/../../js/defaults.js`);
@@ -140,6 +162,10 @@ module.exports = NodeHelper.create({
140162
this.loadTranslation(this.configOnHd.language);
141163
},
142164

165+
/**
166+
* Get the MagicMirror config file path
167+
* @returns {string} Absolute path to config.js
168+
*/
143169
getConfigPath () {
144170
let configPath = path.resolve(`${__dirname}/../../config/config.js`);
145171
if (globalThis.configuration_file !== undefined) {
@@ -194,6 +220,11 @@ module.exports = NodeHelper.create({
194220

195221
formatName (string) { return formatName(string); },
196222

223+
/**
224+
* Update the list of available modules from 3rd-party repository
225+
* @param {boolean} force - Force re-download even if cache exists
226+
* @returns {void}
227+
*/
197228
updateModuleList (force) {
198229
const downloadModules = require("./scripts/download_modules");
199230
downloadModules({
@@ -205,6 +236,11 @@ module.exports = NodeHelper.create({
205236
});
206237
},
207238

239+
/**
240+
* Read and parse modules.json file
241+
* Populates this.modulesAvailable with ModuleData[]
242+
* @returns {void}
243+
*/
208244
readModuleData () {
209245
fs.readFile(path.resolve(`${__dirname}/modules.json`), (error, data) => {
210246
this.modulesAvailable = JSON.parse(data.toString());
@@ -242,6 +278,10 @@ module.exports = NodeHelper.create({
242278
});
243279
},
244280

281+
/**
282+
* Get the modules directory path from config or use default
283+
* @returns {string} Modules directory path (relative or absolute)
284+
*/
245285
getModuleDir () {
246286
return this.configOnHd.foreignModulesDir || (this.configOnHd.paths
247287
? this.configOnHd.paths.modules
@@ -531,17 +571,36 @@ module.exports = NodeHelper.create({
531571
}
532572
},
533573

574+
/**
575+
* Handle POST API requests
576+
* @param {object} query - Query parameters
577+
* @param {object} request - Express request object
578+
* @param {object} res - Express response object
579+
* @returns {void}
580+
*/
534581
answerPost (query, request, res) {
535582
if (query.data === "config") {
536583
this.saveConfigWithBackup(request.body, res, query);
537584
}
538585
},
539586

587+
/**
588+
* Handle request for list of available modules
589+
* @param {object} query - Query parameters
590+
* @param {object} res - Express response object
591+
* @returns {void}
592+
*/
540593
handleGetModuleAvailable (query, res) {
541594
this.modulesAvailable.sort((a, b) => a.name.localeCompare(b.name));
542595
this.sendResponse(res, undefined, {query, data: this.modulesAvailable});
543596
},
544597

598+
/**
599+
* Handle request for list of installed modules
600+
* @param {object} query - Query parameters
601+
* @param {object} res - Express response object
602+
* @returns {void}
603+
*/
545604
handleGetModuleInstalled (query, res) {
546605

547606
// Wait for pending update checks to complete before sending response
@@ -653,6 +712,13 @@ module.exports = NodeHelper.create({
653712
};
654713
},
655714

715+
/**
716+
* Handle GET API requests
717+
* @param {object} query - Query parameters
718+
* @param {string} query.data - Data type requested
719+
* @param {object} res - Express response object
720+
* @returns {void}
721+
*/
656722
answerGet (query, res) {
657723
const handlers = this.getDataHandlers();
658724
const handler = handlers[query.data];
@@ -1100,6 +1166,13 @@ module.exports = NodeHelper.create({
11001166
return false;
11011167
},
11021168

1169+
/**
1170+
* Install a module from a git repository
1171+
* @param {string} url - Git repository URL
1172+
* @param {object} res - Express response object
1173+
* @param {object} data - Additional installation data
1174+
* @returns {void}
1175+
*/
11031176
installModule (url, res, data) {
11041177

11051178
simpleGit(path.resolve(`${__dirname}/..`)).clone(url, path.basename(url), (error) => {
@@ -1330,6 +1403,12 @@ module.exports = NodeHelper.create({
13301403
return addresses;
13311404
},
13321405

1406+
/**
1407+
* Handle socket notifications from the frontend module
1408+
* @param {string} notification - Notification type
1409+
* @param {object | ConfigData} payload - Notification payload (varies by type)
1410+
* @returns {void}
1411+
*/
13331412
socketNotificationReceived (notification, payload) {
13341413

13351414
if (notification === "CURRENT_STATUS") {

types.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/**
2+
* @file Central type definitions for MMM-Remote-Control
3+
* @module types
4+
* @description
5+
* This file contains JSDoc type definitions used throughout the codebase.
6+
* Import these types in your files with:
7+
* @example
8+
* // @typedef {import('./types').ModuleData} ModuleData
9+
*/
10+
11+
/**
12+
* Module metadata from 3rd-party-modules repository
13+
* @typedef {object} ModuleData
14+
* @property {string} name - Module display name
15+
* @property {string} id - GitHub repository identifier (e.g., "author/repo")
16+
* @property {string} url - GitHub repository URL
17+
* @property {string} maintainer - Module maintainer/author
18+
* @property {string} [description] - Module description
19+
* @property {string} [category] - Module category (e.g., "Weather", "Calendar")
20+
* @property {string[]} [keywords] - Search keywords
21+
* @property {number} [stars] - GitHub stars count
22+
* @property {string} [image] - Preview image URL
23+
* @property {string} [lastCommit] - Last commit date (ISO 8601)
24+
* @property {string} [license] - License type (e.g., "MIT", "GPL-3.0")
25+
* @property {boolean} [installed] - Whether module is installed locally
26+
* @property {boolean} [isDefaultModule] - Whether module is a MagicMirror default
27+
* @property {boolean} [hasChangelog] - Whether module has a changelog
28+
* @property {object} [defaultConfig] - Default configuration object
29+
*/
30+
31+
/**
32+
* MagicMirror configuration data
33+
* @typedef {object} ConfigData
34+
* @property {string} [address] - Server address
35+
* @property {number} [port] - Server port
36+
* @property {string} [language] - Display language
37+
* @property {string} [timeFormat] - Time format (12/24)
38+
* @property {string} [units] - Unit system (metric/imperial)
39+
* @property {ModuleConfig[]} modules - Module configurations
40+
* @property {object} [electronOptions] - Electron-specific options
41+
* @property {string[]} [ipWhitelist] - IP whitelist for access control
42+
*/
43+
44+
/**
45+
* Module configuration entry
46+
* @typedef {object} ModuleConfig
47+
* @property {string} module - Module name
48+
* @property {string} [position] - Display position
49+
* @property {string} [header] - Module header text
50+
* @property {object} [config] - Module-specific configuration
51+
* @property {string[]} [classes] - CSS classes
52+
* @property {boolean} [disabled] - Whether module is disabled
53+
*/
54+
55+
/**
56+
* Backup metadata
57+
* @typedef {object} BackupInfo
58+
* @property {string} timestamp - ISO 8601 timestamp
59+
* @property {string} filename - Backup filename
60+
* @property {number} size - File size in bytes
61+
* @property {string} [description] - Optional backup description
62+
*/
63+
64+
/**
65+
* API response structure
66+
* @typedef {object} ApiResponse
67+
* @property {boolean} success - Whether the operation succeeded
68+
* @property {object | Array | string | number | boolean} [data] - Response data (type varies by endpoint)
69+
* @property {string} [message] - Error or info message
70+
* @property {object} [query] - Original query parameters
71+
*/
72+
73+
/**
74+
* Socket notification payload
75+
* @typedef {object} NotificationPayload
76+
* @property {string} notification - Notification type
77+
* @property {object | Array | string | number | boolean | null} [payload] - Notification data
78+
*/
79+
80+
/**
81+
* Git operation result
82+
* @typedef {object} GitResult
83+
* @property {boolean} success - Whether git operation succeeded
84+
* @property {string} [stdout] - Command stdout
85+
* @property {string} [stderr] - Command stderr
86+
* @property {number} [code] - Exit code
87+
* @property {string} [error] - Error message
88+
*/
89+
90+
/**
91+
* Module installation options
92+
* @typedef {object} InstallOptions
93+
* @property {string} url - Git repository URL
94+
* @property {number} [index] - Installation index in modules array
95+
* @property {boolean} [skipNpmInstall] - Skip npm install after clone
96+
*/
97+
98+
module.exports = {};

0 commit comments

Comments
 (0)