coffee-time 1.2.0-beta.1 → 1.2.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,13 +34,22 @@ Start a continuous break loop with a required interval (minutes):
34
34
  coffee-time start --interval 45
35
35
  ```
36
36
 
37
+ Add a lightweight countdown ping every minute:
38
+
39
+ ```bash
40
+ coffee-time start --interval 45 --status
41
+ ```
42
+
37
43
  ---
38
44
 
39
45
  ## What happens
40
46
 
41
47
  * Prints a single startup line:
42
48
  `Coffee breaks scheduled every 45 minutes. Press Ctrl+C to stop.`
49
+ * Optional status flag (`--status`) prints a countdown update every minute:
50
+ `⏳ Next break in 44:00`
43
51
  * Waits 45 minutes, then triggers a break notification.
52
+ * After each break, countdown updates continue when `--status` is enabled.
44
53
  * Immediately schedules the next interval and repeats until you stop it (`Ctrl+C`).
45
54
 
46
55
  ---
@@ -24,11 +24,14 @@ function parseArgs(argv) {
24
24
  }
25
25
 
26
26
  let intervalMinutes;
27
+ let showStatus = false;
27
28
  for (let i = 0; i < rest.length; i += 1) {
28
29
  const token = rest[i];
29
30
  if (token === '--interval') {
30
31
  intervalMinutes = rest[i + 1];
31
32
  i += 1;
33
+ } else if (token === '--status') {
34
+ showStatus = true;
32
35
  } else {
33
36
  console.error(`Unknown option: ${token}`);
34
37
  printUsage();
@@ -48,7 +51,7 @@ function parseArgs(argv) {
48
51
  process.exit(USAGE_ERROR);
49
52
  }
50
53
 
51
- return parsedInterval;
54
+ return { intervalMinutes: parsedInterval, showStatus };
52
55
  }
53
56
 
54
57
  function sendDesktopNotification(message) {
@@ -86,35 +89,99 @@ function attemptNotification(command, args) {
86
89
  });
87
90
  }
88
91
 
89
- function notify(intervalMinutes) {
92
+ function notify(intervalMinutes, logLine = console.log) {
90
93
  const message = `Time for a coffee break! (${intervalMinutes} min interval)`;
91
- console.log(`☕ ${message}`);
94
+ logLine(`☕ ${message}`);
92
95
  sendDesktopNotification(message).catch(() => {});
93
96
  }
94
97
 
95
- function startLoop(intervalMinutes) {
98
+ function formatRemaining(remainingMs) {
99
+ const totalSeconds = Math.max(0, Math.ceil(remainingMs / 1000));
100
+ const minutes = Math.floor(totalSeconds / 60);
101
+ const seconds = totalSeconds % 60;
102
+ return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
103
+ }
104
+
105
+ function printCoffeeArt() {
106
+ const artLines = [
107
+ ' ( (',
108
+ ' ) )',
109
+ ' ........',
110
+ ' | |]',
111
+ ' \\ /',
112
+ " '----'",
113
+ ];
114
+ console.log(artLines.join('\n'));
115
+ }
116
+
117
+ function startLoop(intervalMinutes, options = {}) {
118
+ const { showStatus = false } = options;
119
+ let statusLength = 0;
120
+ let statusActive = false;
121
+
122
+ const logLine = (message) => {
123
+ if (statusActive) {
124
+ process.stdout.write('\n');
125
+ statusActive = false;
126
+ statusLength = 0;
127
+ }
128
+ console.log(message);
129
+ };
130
+
96
131
  console.log(`Coffee breaks scheduled every ${intervalMinutes} minutes. Press Ctrl+C to stop.`);
132
+ printCoffeeArt();
97
133
 
134
+ const startedAt = Date.now();
98
135
  const intervalMs = intervalMinutes * 60 * 1000;
99
- let nextTime = Date.now() + intervalMs;
136
+ let nextTime = startedAt + intervalMs;
100
137
  let timeoutId = null;
138
+ let statusIntervalId = null;
139
+ let statusTimeoutId = null;
140
+
141
+ const logStatus = () => {
142
+ const remaining = nextTime - Date.now();
143
+ const message = `⏳ Next break in ${formatRemaining(remaining)}`;
144
+ const paddedMessage = message.padEnd(statusLength, ' ');
145
+ process.stdout.write(`\r${paddedMessage}`);
146
+ statusLength = message.length;
147
+ statusActive = true;
148
+ };
101
149
 
102
150
  function scheduleNext() {
103
151
  const delay = Math.max(0, nextTime - Date.now());
104
152
  timeoutId = setTimeout(() => {
105
- notify(intervalMinutes);
153
+ notify(intervalMinutes, logLine);
106
154
  nextTime += intervalMs;
155
+ if (showStatus) {
156
+ logStatus();
157
+ }
107
158
  scheduleNext();
108
159
  }, delay);
109
160
  }
110
161
 
111
162
  scheduleNext();
112
163
 
164
+ if (showStatus) {
165
+ const elapsed = Date.now() - startedAt;
166
+ const firstDelay = Math.max(0, 60 * 1000 - (elapsed % (60 * 1000)));
167
+
168
+ statusTimeoutId = setTimeout(() => {
169
+ logStatus();
170
+ statusIntervalId = setInterval(logStatus, 60 * 1000);
171
+ }, firstDelay);
172
+ }
173
+
113
174
  const handleExit = () => {
114
175
  if (timeoutId) {
115
176
  clearTimeout(timeoutId);
116
177
  }
117
- console.log('\nStopped. Stay fresh ☕');
178
+ if (statusTimeoutId) {
179
+ clearTimeout(statusTimeoutId);
180
+ }
181
+ if (statusIntervalId) {
182
+ clearInterval(statusIntervalId);
183
+ }
184
+ logLine('\nStopped. Stay fresh ☕');
118
185
  process.exit(0);
119
186
  };
120
187
 
@@ -124,8 +191,8 @@ function startLoop(intervalMinutes) {
124
191
 
125
192
  function main() {
126
193
  try {
127
- const intervalMinutes = parseArgs(process.argv);
128
- startLoop(intervalMinutes);
194
+ const { intervalMinutes, showStatus } = parseArgs(process.argv);
195
+ startLoop(intervalMinutes, { showStatus });
129
196
  } catch (error) {
130
197
  console.error('Unexpected error:', error.message);
131
198
  process.exit(1);
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.2.0-beta.1",
6
+ "version": "1.2.0-beta.3",
7
7
  "description": "Lightweight CLI to schedule coffee breaks at a fixed interval.",
8
8
  "bin": {
9
9
  "coffee-time": "./bin/coffee-time.js"
@@ -12,6 +12,10 @@
12
12
  "type": "commonjs",
13
13
  "scripts": {
14
14
  "start": "node ./bin/coffee-time.js"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/tborges/coffee-time"
15
19
  },
16
20
  "keywords": [
17
21
  "Coffee Time",