myceliumail 1.0.8 → 1.0.9
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/dist/bin/myceliumail.js +3 -0
- package/dist/bin/myceliumail.js.map +1 -1
- package/dist/lib/update-check.d.ts +11 -0
- package/dist/lib/update-check.d.ts.map +1 -0
- package/dist/lib/update-check.js +114 -0
- package/dist/lib/update-check.js.map +1 -0
- package/package.json +1 -1
- package/src/bin/myceliumail.ts +4 -0
- package/src/lib/update-check.ts +131 -0
package/dist/bin/myceliumail.js
CHANGED
|
@@ -22,6 +22,7 @@ import { createWatchCommand } from '../commands/watch.js';
|
|
|
22
22
|
import { createExportCommand } from '../commands/export.js';
|
|
23
23
|
import { createStatusCommand } from '../commands/status.js';
|
|
24
24
|
import { createActivateCommand, createLicenseStatusCommand } from '../commands/activate.js';
|
|
25
|
+
import { checkForUpdates } from '../lib/update-check.js';
|
|
25
26
|
const program = new Command();
|
|
26
27
|
program
|
|
27
28
|
.name('mycmail')
|
|
@@ -49,6 +50,8 @@ program.addCommand(createStatusCommand());
|
|
|
49
50
|
// License management
|
|
50
51
|
program.addCommand(createActivateCommand());
|
|
51
52
|
program.addCommand(createLicenseStatusCommand());
|
|
53
|
+
// Check for updates (non-blocking, runs in background)
|
|
54
|
+
checkForUpdates().catch(() => { });
|
|
52
55
|
// Parse and run
|
|
53
56
|
program.parse();
|
|
54
57
|
//# sourceMappingURL=myceliumail.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"myceliumail.js","sourceRoot":"","sources":["../../src/bin/myceliumail.ts"],"names":[],"mappings":";AAEA;;;;GAIG;AAEH,4CAA4C;AAC5C,OAAO,eAAe,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,kBAAkB;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"myceliumail.js","sourceRoot":"","sources":["../../src/bin/myceliumail.ts"],"names":[],"mappings":";AAEA;;;;GAIG;AAEH,4CAA4C;AAC5C,OAAO,eAAe,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,kBAAkB;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACF,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,+DAA+D,CAAC;KAC5E,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,6BAA6B;AAC7B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;AAC5B,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE;iBACZ,MAAM,CAAC,OAAO;;CAE9B,CAAC,CAAC;AAEH,oBAAoB;AACpB,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,sBAAsB,EAAE,CAAC,CAAC;AAC7C,OAAO,CAAC,UAAU,CAAC,wBAAwB,EAAE,CAAC,CAAC;AAC/C,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,sBAAsB,EAAE,CAAC,CAAC;AAC7C,OAAO,CAAC,UAAU,CAAC,sBAAsB,EAAE,CAAC,CAAC;AAC7C,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAE1C,qBAAqB;AACrB,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,0BAA0B,EAAE,CAAC,CAAC;AAEjD,uDAAuD;AACvD,eAAe,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAEnC,gBAAgB;AAChB,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update Check Module
|
|
3
|
+
*
|
|
4
|
+
* Checks npm registry for newer versions and displays update notification.
|
|
5
|
+
* Non-blocking, fails silently.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check for updates (non-blocking)
|
|
9
|
+
*/
|
|
10
|
+
export declare function checkForUpdates(): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=update-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../../src/lib/update-check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwEH;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAkCrD"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update Check Module
|
|
3
|
+
*
|
|
4
|
+
* Checks npm registry for newer versions and displays update notification.
|
|
5
|
+
* Non-blocking, fails silently.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
import { homedir } from 'os';
|
|
10
|
+
const CONFIG_DIR = join(homedir(), '.myceliumail');
|
|
11
|
+
const UPDATE_CACHE = join(CONFIG_DIR, 'update-cache.json');
|
|
12
|
+
const PACKAGE_NAME = 'myceliumail';
|
|
13
|
+
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
14
|
+
/**
|
|
15
|
+
* Get current installed version from package.json
|
|
16
|
+
*/
|
|
17
|
+
function getCurrentVersion() {
|
|
18
|
+
try {
|
|
19
|
+
// Read from the installed package
|
|
20
|
+
const packagePath = new URL('../package.json', import.meta.url);
|
|
21
|
+
const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
|
22
|
+
return pkg.version;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return '0.0.0';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Load update cache
|
|
30
|
+
*/
|
|
31
|
+
function loadCache() {
|
|
32
|
+
try {
|
|
33
|
+
if (existsSync(UPDATE_CACHE)) {
|
|
34
|
+
return JSON.parse(readFileSync(UPDATE_CACHE, 'utf-8'));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Ignore
|
|
39
|
+
}
|
|
40
|
+
return { lastCheck: 0, latestVersion: null };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Save update cache
|
|
44
|
+
*/
|
|
45
|
+
function saveCache(cache) {
|
|
46
|
+
try {
|
|
47
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
48
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
writeFileSync(UPDATE_CACHE, JSON.stringify(cache));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Ignore
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Compare semantic versions
|
|
58
|
+
*/
|
|
59
|
+
function isNewerVersion(current, latest) {
|
|
60
|
+
const currentParts = current.split('.').map(Number);
|
|
61
|
+
const latestParts = latest.split('.').map(Number);
|
|
62
|
+
for (let i = 0; i < 3; i++) {
|
|
63
|
+
if ((latestParts[i] || 0) > (currentParts[i] || 0))
|
|
64
|
+
return true;
|
|
65
|
+
if ((latestParts[i] || 0) < (currentParts[i] || 0))
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Check for updates (non-blocking)
|
|
72
|
+
*/
|
|
73
|
+
export async function checkForUpdates() {
|
|
74
|
+
try {
|
|
75
|
+
const cache = loadCache();
|
|
76
|
+
const now = Date.now();
|
|
77
|
+
// Only check once per day
|
|
78
|
+
if (now - cache.lastCheck < CHECK_INTERVAL_MS && cache.latestVersion) {
|
|
79
|
+
showUpdateNotification(cache.latestVersion);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Fetch latest version from npm (with timeout)
|
|
83
|
+
const controller = new AbortController();
|
|
84
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
85
|
+
const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, { signal: controller.signal });
|
|
86
|
+
clearTimeout(timeout);
|
|
87
|
+
if (!response.ok)
|
|
88
|
+
return;
|
|
89
|
+
const data = await response.json();
|
|
90
|
+
const latestVersion = data.version;
|
|
91
|
+
// Update cache
|
|
92
|
+
saveCache({ lastCheck: now, latestVersion });
|
|
93
|
+
// Show notification if newer
|
|
94
|
+
showUpdateNotification(latestVersion);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Silent fail - don't interrupt user
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Display update notification if newer version available
|
|
102
|
+
*/
|
|
103
|
+
function showUpdateNotification(latestVersion) {
|
|
104
|
+
const currentVersion = getCurrentVersion();
|
|
105
|
+
if (isNewerVersion(currentVersion, latestVersion)) {
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log('╭─────────────────────────────────────────────╮');
|
|
108
|
+
console.log(`│ 🍄 Update available: ${currentVersion} → ${latestVersion.padEnd(10)} │`);
|
|
109
|
+
console.log('│ Run: npm install -g myceliumail │');
|
|
110
|
+
console.log('╰─────────────────────────────────────────────╯');
|
|
111
|
+
console.log('');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=update-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-check.js","sourceRoot":"","sources":["../../src/lib/update-check.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/bin/myceliumail.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { createWatchCommand } from '../commands/watch.js';
|
|
|
26
26
|
import { createExportCommand } from '../commands/export.js';
|
|
27
27
|
import { createStatusCommand } from '../commands/status.js';
|
|
28
28
|
import { createActivateCommand, createLicenseStatusCommand } from '../commands/activate.js';
|
|
29
|
+
import { checkForUpdates } from '../lib/update-check.js';
|
|
29
30
|
|
|
30
31
|
const program = new Command();
|
|
31
32
|
|
|
@@ -59,6 +60,9 @@ program.addCommand(createStatusCommand());
|
|
|
59
60
|
program.addCommand(createActivateCommand());
|
|
60
61
|
program.addCommand(createLicenseStatusCommand());
|
|
61
62
|
|
|
63
|
+
// Check for updates (non-blocking, runs in background)
|
|
64
|
+
checkForUpdates().catch(() => { });
|
|
65
|
+
|
|
62
66
|
// Parse and run
|
|
63
67
|
program.parse();
|
|
64
68
|
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update Check Module
|
|
3
|
+
*
|
|
4
|
+
* Checks npm registry for newer versions and displays update notification.
|
|
5
|
+
* Non-blocking, fails silently.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
import { homedir } from 'os';
|
|
11
|
+
|
|
12
|
+
const CONFIG_DIR = join(homedir(), '.myceliumail');
|
|
13
|
+
const UPDATE_CACHE = join(CONFIG_DIR, 'update-cache.json');
|
|
14
|
+
const PACKAGE_NAME = 'myceliumail';
|
|
15
|
+
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
16
|
+
|
|
17
|
+
interface UpdateCache {
|
|
18
|
+
lastCheck: number;
|
|
19
|
+
latestVersion: string | null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get current installed version from package.json
|
|
24
|
+
*/
|
|
25
|
+
function getCurrentVersion(): string {
|
|
26
|
+
try {
|
|
27
|
+
// Read from the installed package
|
|
28
|
+
const packagePath = new URL('../package.json', import.meta.url);
|
|
29
|
+
const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
|
30
|
+
return pkg.version;
|
|
31
|
+
} catch {
|
|
32
|
+
return '0.0.0';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Load update cache
|
|
38
|
+
*/
|
|
39
|
+
function loadCache(): UpdateCache {
|
|
40
|
+
try {
|
|
41
|
+
if (existsSync(UPDATE_CACHE)) {
|
|
42
|
+
return JSON.parse(readFileSync(UPDATE_CACHE, 'utf-8'));
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
// Ignore
|
|
46
|
+
}
|
|
47
|
+
return { lastCheck: 0, latestVersion: null };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Save update cache
|
|
52
|
+
*/
|
|
53
|
+
function saveCache(cache: UpdateCache): void {
|
|
54
|
+
try {
|
|
55
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
56
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
57
|
+
}
|
|
58
|
+
writeFileSync(UPDATE_CACHE, JSON.stringify(cache));
|
|
59
|
+
} catch {
|
|
60
|
+
// Ignore
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Compare semantic versions
|
|
66
|
+
*/
|
|
67
|
+
function isNewerVersion(current: string, latest: string): boolean {
|
|
68
|
+
const currentParts = current.split('.').map(Number);
|
|
69
|
+
const latestParts = latest.split('.').map(Number);
|
|
70
|
+
|
|
71
|
+
for (let i = 0; i < 3; i++) {
|
|
72
|
+
if ((latestParts[i] || 0) > (currentParts[i] || 0)) return true;
|
|
73
|
+
if ((latestParts[i] || 0) < (currentParts[i] || 0)) return false;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Check for updates (non-blocking)
|
|
80
|
+
*/
|
|
81
|
+
export async function checkForUpdates(): Promise<void> {
|
|
82
|
+
try {
|
|
83
|
+
const cache = loadCache();
|
|
84
|
+
const now = Date.now();
|
|
85
|
+
|
|
86
|
+
// Only check once per day
|
|
87
|
+
if (now - cache.lastCheck < CHECK_INTERVAL_MS && cache.latestVersion) {
|
|
88
|
+
showUpdateNotification(cache.latestVersion);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Fetch latest version from npm (with timeout)
|
|
93
|
+
const controller = new AbortController();
|
|
94
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
95
|
+
|
|
96
|
+
const response = await fetch(
|
|
97
|
+
`https://registry.npmjs.org/${PACKAGE_NAME}/latest`,
|
|
98
|
+
{ signal: controller.signal }
|
|
99
|
+
);
|
|
100
|
+
clearTimeout(timeout);
|
|
101
|
+
|
|
102
|
+
if (!response.ok) return;
|
|
103
|
+
|
|
104
|
+
const data = await response.json() as { version: string };
|
|
105
|
+
const latestVersion = data.version;
|
|
106
|
+
|
|
107
|
+
// Update cache
|
|
108
|
+
saveCache({ lastCheck: now, latestVersion });
|
|
109
|
+
|
|
110
|
+
// Show notification if newer
|
|
111
|
+
showUpdateNotification(latestVersion);
|
|
112
|
+
} catch {
|
|
113
|
+
// Silent fail - don't interrupt user
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Display update notification if newer version available
|
|
119
|
+
*/
|
|
120
|
+
function showUpdateNotification(latestVersion: string): void {
|
|
121
|
+
const currentVersion = getCurrentVersion();
|
|
122
|
+
|
|
123
|
+
if (isNewerVersion(currentVersion, latestVersion)) {
|
|
124
|
+
console.log('');
|
|
125
|
+
console.log('╭─────────────────────────────────────────────╮');
|
|
126
|
+
console.log(`│ 🍄 Update available: ${currentVersion} → ${latestVersion.padEnd(10)} │`);
|
|
127
|
+
console.log('│ Run: npm install -g myceliumail │');
|
|
128
|
+
console.log('╰─────────────────────────────────────────────╯');
|
|
129
|
+
console.log('');
|
|
130
|
+
}
|
|
131
|
+
}
|