Skip to content

Commit 1402493

Browse files
committed
Version 2.0:
- Switched to ES Module - Allow service parameters to be specified in settings
1 parent 90d3e48 commit 1402493

7 files changed

Lines changed: 202 additions & 85 deletions

File tree

README.md

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Disk-Space-Monitor
1+
# disk-space-monitor
22
[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-yellow)](https://raw.githubusercontent.com/blu3mania/disk-space-monitor/main/LICENSE)
33
[![node.js 10+](https://img.shields.io/badge/node.js-10.16.3-blue?logo=node.js)](https://nodejs.org/en/)
44
[![Latest Release](https://img.shields.io/github/v/release/blu3mania/disk-space-monitor)](https://github.com/blu3mania/disk-space-monitor/releases/latest)
@@ -7,9 +7,8 @@ Monitor disk space usage and notify user by email or system notification.
77

88
It can be run as a standalone application or as a system service.
99

10-
**Note**, the instructions below uses yarn as package manager so it can install the latest minimist package
11-
that doesn't have [Prototype Pollution vulnerability](https://www.npmjs.com/advisories/1179). Though, if you
12-
prefer you can use npm as well, just replace "yarn" with "npm" in any command.
10+
**Note**, this package is written as ES Module starting with 2.0. For CommonJS version, use version 1.x from
11+
CommonJS branch.
1312

1413
## Run these steps first:
1514

@@ -18,6 +17,25 @@ prefer you can use npm as well, just replace "yarn" with "npm" in any command.
1817
instructions](https://github.com/nodejs/node-gyp#installation).
1918

2019
2. Edit src/settings.json.
20+
* service defines service parameters when installed as a system service:
21+
* name is the service name to be used.
22+
* account info is optional. If provided, the service will be running as the specified account. These properties
23+
can be provided:
24+
* name is account's name, when running on Windows
25+
* password is account's password, when running on Windows
26+
* domain is optional, and should be provided if the account is a domain account when running on Windows
27+
* user is the user name, when running on Linux
28+
* group is the group name, when running on Linux
29+
```
30+
"service": {
31+
"name": "Disk Space Monitor",
32+
"account": {
33+
"name": "{account name}",
34+
"password": "{account password}",
35+
"domain": "{account domain}"
36+
}
37+
},
38+
```
2139
* disks lists all the disks this script needs to montior.
2240
* path is the path to the disk. On Windows it's usaully the drive letter followed by a colon, e.g. "C:".
2341
On Linux it is usually the mounted file system path, e.g. "/dev".
@@ -54,20 +72,20 @@ prefer you can use npm as well, just replace "yarn" with "npm" in any command.
5472
* to, cc, bcc are the email recipient. Multiple email addresses can be used with comma as delimiter.
5573
* smtp defines the SMTP server options used by nodemailer. Please refer to [nodemail's SMTP Transport
5674
page](https://nodemailer.com/smtp/) for details.
57-
3. Run "yarn install". If running on Windows, accept UAC prompts if any (there could be up to 4).
75+
3. Run "npm install". If running on Windows, accept UAC prompts if any (there could be up to 4).
5876

59-
**Note**, this step installs the script as a system service. If it's not desired, run "yarn run uninstall" afterwards.
77+
**Note**, this step installs the script as a system service. If it's not desired, run "npm run uninstall" afterwards.
6078

6179
## To run the script manually:
6280

63-
Run "yarn start" or "node src/app.js".
81+
Run "npm start" or "node src/app.js".
6482

6583
## To install and run the script as a system service:
6684

67-
Run "yarn run install" or "node src/install-service.js". If running on Windows, accept UAC prompts if any (there could be up to 4).
85+
Run "npm run install" or "node src/install-service.js". If running on Windows, accept UAC prompts if any (there could be up to 4).
6886

6987
**Note**, if settings.json is updated when service is running, restart the server (on Windows, this can be done from Services control panel).
7088

7189
## To uninstall the system service:
7290

73-
Run "yarn run uninstall" or "node src/uninstall-service.js". If running on Windows, accept UAC prompts if any (there could be up to 4).
91+
Run "npm run uninstall" or "node src/uninstall-service.js". If running on Windows, accept UAC prompts if any (there could be up to 4).

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{
22
"name": "disk-space-monitor",
3-
"version": "1.1.0",
3+
"type": "module",
4+
"version": "2.0.0",
45
"description": "Monitor disk space usage and notify user by email or system notification",
5-
"main": "src/app.js",
6+
"exports": "src/app.js",
67
"scripts": {
78
"start": "node src/app.js",
89
"preinstall": "npm install npm-platform-dependencies && npmpd",
@@ -11,8 +12,7 @@
1112
},
1213
"keywords": [
1314
"disk space",
14-
"disk monitor",
15-
"disk space monitor"
15+
"monitor"
1616
],
1717
"author": "blu3mania <blu3mania@hotmail.com>",
1818
"license": "Apache-2.0",
@@ -25,7 +25,7 @@
2525
"url": "https://github.com/blu3mania/disk-space-monitor.git"
2626
},
2727
"dependencies": {
28-
"chalk": "^4.1.2",
28+
"chalk": "^5.0.1",
2929
"diskusage": "^1.1.3",
3030
"node-notifier": "^10.0.1",
3131
"nodemailer": "^6.7.8"

src/app.js

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
'use strict';
2-
3-
const os = require('os');
4-
const path = require('path');
5-
const notifier = require('node-notifier');
6-
const diskusage = require('diskusage');
7-
const nodemailer = require('nodemailer');
8-
const {
1+
import os from 'os';
2+
import path from 'path';
3+
import url from 'url';
4+
5+
import diskusage from 'diskusage';
6+
import mailer from 'nodemailer';
7+
import notifier from 'node-notifier';
8+
9+
import {
910
error,
1011
warning,
1112
info,
12-
verbose } = require('./print.js');
13-
const settings = require('./settings.json');
13+
verbose } from './print.js';
14+
import settings from './settings.json' assert {type: 'json'};
1415

1516
const NotificationType = {
1617
Email: 'email',
@@ -22,14 +23,20 @@ const EmailFormat = {
2223
Text: 'text',
2324
};
2425

25-
const prefixes = [
26+
// Supported unit prefixes
27+
const UnitPrefix = [
2628
'k',
2729
'm',
2830
'g',
2931
't',
3032
'p',
33+
'e',
34+
'z',
35+
'y',
3136
];
3237

38+
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
39+
3340
let emailTransporter = null;
3441

3542
main();
@@ -38,7 +45,7 @@ function main() {
3845
verbose('Starting...');
3946

4047
if (settings.notificationTypes.find(type => type.toLowerCase() === NotificationType.Email)) {
41-
emailTransporter = nodemailer.createTransport(settings.email.smtp);
48+
emailTransporter = mailer.createTransport(settings.email.smtp);
4249
}
4350

4451
checkDiskUsage();
@@ -58,7 +65,7 @@ function checkDiskUsage() {
5865
return Promise.reject(`Invalid configuration "${disk.threshold}" for disk "${disk.path}".`);
5966
}
6067
disk.notificationTriggered = false;
61-
verbose(`Disk "${disk.path}" threshold "${disk.threshold}", which is ${disk.thresholdInBytes} bytes.`);
68+
verbose(`Disk "${disk.path}" threshold "${disk.threshold}", which is ${disk.thresholdInBytes.toLocaleString()} bytes.`);
6269
}
6370
checkDiskFreeSpace(disk, diskInfo);
6471
})
@@ -106,7 +113,7 @@ function calculateThresholdInBytes(disk, diskInfo) {
106113
base = 1024;
107114
prefixToCheck = disk.threshold.slice(-3, -2).toLowerCase();
108115
} else {
109-
// SI prefix
116+
// Decimal (SI) prefix
110117
base = 1000;
111118
}
112119
} else {
@@ -115,7 +122,7 @@ function calculateThresholdInBytes(disk, diskInfo) {
115122
}
116123

117124
if (prefixToCheck !== null) {
118-
const exponent = prefixes.findIndex(prefix => prefix === prefixToCheck) + 1;
125+
const exponent = UnitPrefix.findIndex(prefix => prefix === prefixToCheck) + 1;
119126
if (exponent === 0) {
120127
invalidConfig = true;
121128
} else {

src/install-service.js

Lines changed: 79 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,82 @@
1-
'use strict';
1+
import path from 'path';
2+
import url from 'url';
23

3-
const path = require('path');
4-
const Service = require(process.platform === 'win32' ? 'node-windows' : process.platform === 'darwin' ? 'node-mac' : 'node-linux').Service;
5-
const {
4+
import {
65
warning,
76
info,
8-
verbose } = require('./print.js');
9-
10-
// Create a new service object.
11-
const svc = new Service({
12-
name: 'Disk Space Monitor',
13-
description: 'Monotr disk space usage and notify user by email or Windows Toast.',
14-
script: `${path.join(__dirname, 'app.js')}`,
15-
nodeOptions: [
16-
'--harmony',
17-
'--max_old_space_size=4096'
18-
]
19-
});
20-
21-
// Listen for the "install" event, which indicates the process is available as a service.
22-
svc.on('install', () => {
23-
verbose('Service installed.');
24-
info('Starting service, please accept UAC prompts if any...');
25-
svc.start();
26-
});
27-
28-
svc.on('start', () => {
29-
verbose('Service started.');
30-
});
31-
32-
svc.on('alreadyinstalled', () => {
33-
warning('Service is already installed!');
34-
info('Starting the service in case it is not running, please accept UAC prompts if any...');
35-
svc.start();
36-
});
37-
38-
info('Installing service, please accept UAC prompts if any...');
39-
svc.install();
7+
verbose } from './print.js';
8+
import settings from './settings.json' assert {type: 'json'};
9+
10+
main();
11+
12+
function main() {
13+
// Dynamically import the module we need depending on current OS
14+
switch (process.platform) {
15+
case 'win32':
16+
import('node-windows')
17+
.then(module => installService(module.Service));
18+
break;
19+
20+
case 'darwin':
21+
import('node-mac')
22+
.then(module => installService(module.Service));
23+
break;
24+
25+
default:
26+
import('node-linux')
27+
.then(module => installService(module.Service));
28+
break;
29+
}
30+
}
31+
32+
function installService(Service) {
33+
// Create a new service object.
34+
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
35+
const svc = new Service({
36+
name: settings.service?.name ?? 'Disk Space Monitor',
37+
description: 'Monotr disk space usage and notify user by email or Windows Toast.',
38+
script: `${path.join(__dirname, 'app.js')}`,
39+
nodeOptions: [
40+
'--harmony',
41+
'--max_old_space_size=4096'
42+
]
43+
});
44+
45+
if (process.platform === 'win32') {
46+
if (settings.service?.account?.name && settings.service?.account?.password) {
47+
svc.logOnAs.account = settings.service.account.name;
48+
svc.logOnAs.password = settings.service.account.password;
49+
if (settings.service?.account?.domain) {
50+
svc.logOnAs.domain = settings.service.account.domain;
51+
}
52+
}
53+
} else if (process.platform !== 'darwin') {
54+
if (settings.service?.account?.user) {
55+
svc.user = settings.service.account.user;
56+
}
57+
58+
if (settings.service?.account?.group) {
59+
svc.group = settings.service.account.group;
60+
}
61+
}
62+
63+
// Listen for the "install" event, which indicates the process is available as a service.
64+
svc.on('install', () => {
65+
verbose('Service installed.');
66+
info('Starting service, please accept UAC prompts if any...');
67+
svc.start();
68+
});
69+
70+
svc.on('start', () => {
71+
verbose('Service started.');
72+
});
73+
74+
svc.on('alreadyinstalled', () => {
75+
warning('Service is already installed!');
76+
info('Starting the service in case it is not running, please accept UAC prompts if any...');
77+
svc.start();
78+
});
79+
80+
info('Installing service, please accept UAC prompts if any...');
81+
svc.install();
82+
}

src/print.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
'use strict';
2-
3-
const chalk = require('chalk');
1+
import chalk from 'chalk';
42

53
const dateTimeFormatOprions = {
64
year: 'numeric',
@@ -12,31 +10,54 @@ const dateTimeFormatOprions = {
1210
hour12: false
1311
};
1412

13+
/** Internal method: format a message so it shows with timestamp. */
1514
function formatMessage(msg) {
1615
return `[${new Intl.DateTimeFormat('en-US', dateTimeFormatOprions).format(new Date())}] ${typeof msg === 'string' ? msg : JSON.stringify(msg, null, 2)}`;
1716
}
1817

18+
/**
19+
* Prints a message in console.
20+
* @param {string|Object} msg - The message to be printed. It can be a non-string type, in which case it will be serialized before printing.
21+
* @param {Chalk} color - (Optional) The color of the message to be printed.
22+
* If not provided, default color white is used.
23+
*/
1924
function print(msg, color = chalk.white) {
2025
console.log(color(formatMessage(msg)));
2126
}
2227

28+
/**
29+
* Prints an error message in console.
30+
* @param {string|Object} msg - The error message to be printed. It can be a non-string type, in which case it will be serialized before printing.
31+
*/
2332
function error(msg) {
2433
console.log(chalk.red(formatMessage(msg)));
2534
}
2635

36+
/**
37+
* Prints a warning message in console.
38+
* @param {string|Object} msg - The warning message to be printed. It can be a non-string type, in which case it will be serialized before printing.
39+
*/
2740
function warning(msg) {
2841
console.log(chalk.yellow(formatMessage(msg)));
2942
}
3043

44+
/**
45+
* Prints an infomation message in console.
46+
* @param {string|Object} msg - The information message to be printed. It can be a non-string type, in which case it will be serialized before printing.
47+
*/
3148
function info(msg) {
3249
console.log(chalk.cyan(formatMessage(msg)));
3350
}
3451

52+
/**
53+
* Prints a verbose message in console.
54+
* @param {string|Object} msg - The verbose message to be printed. It can be a non-string type, in which case it will be serialized before printing.
55+
*/
3556
function verbose(msg) {
3657
console.log(chalk.green(formatMessage(msg)));
3758
}
3859

39-
module.exports = {
60+
export {
4061
print,
4162
error,
4263
warning,

src/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
{
2+
"service": {
3+
"name": "Disk Space Monitor"
4+
},
25
"disks": [
36
{
47
"path": "C:",

0 commit comments

Comments
 (0)