@deerdesign/deertools 1.2.5 → 1.2.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deerdesign/deertools",
3
- "version": "1.2.5",
3
+ "version": "1.2.6",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org/"
package/src/cli.js CHANGED
@@ -35,6 +35,7 @@ async function main(argv) {
35
35
  mcp: c.cmdMcp, doctor: c.cmdDoctor, audit: c.cmdAudit, profile: c.cmdProfile,
36
36
  completion: c.cmdCompletion, catalog: c.cmdCatalog, deliveries: c.cmdDeliveries,
37
37
  supplier: c.cmdSupplier, rendermind: c.cmdRendermind, baselinker: c.cmdBaseLinker,
38
+ update: require('./updater').cmdUpdate,
38
39
  };
39
40
 
40
41
  if (pos.length === 0 && !flags.help && !flags.version && process.stdout.isTTY) {
@@ -48,15 +49,28 @@ async function main(argv) {
48
49
 
49
50
  const cmd = pos.shift() || 'help';
50
51
 
51
- if (cmd === 'help' || cmd === '--help' || flags.help) { process.stdout.write(c.HELP); return 0; }
52
- if (cmd === '--version' || cmd === 'version' || flags.version) { process.stdout.write(`${require('../package.json').version}\n`); return 0; }
53
- if (!table[cmd]) { process.stderr.write(`Nieznana komenda „${cmd}”.\n${c.HELP}`); return 2; }
52
+ const shouldCheck = !flags.json && cmd !== 'update' && process.env.NODE_ENV !== 'test';
53
+ const updatePromise = shouldCheck ? require('./updater').checkUpdate().catch(() => null) : null;
54
+
55
+ const finish = async (code = 0) => {
56
+ if (updatePromise) {
57
+ try {
58
+ const info = await updatePromise;
59
+ if (info && info.hasUpdate) require('./updater').printUpdateNotice(info);
60
+ } catch (_) {}
61
+ }
62
+ return code;
63
+ };
64
+
65
+ if (cmd === 'help' || cmd === '--help' || flags.help) { process.stdout.write(c.HELP); return finish(0); }
66
+ if (cmd === '--version' || cmd === 'version' || flags.version) { process.stdout.write(`${require('../package.json').version}\n`); return finish(0); }
67
+ if (!table[cmd]) { process.stderr.write(`Nieznana komenda „${cmd}”.\n${c.HELP}`); return finish(2); }
54
68
  try {
55
69
  await table[cmd](pos, flags);
56
- return 0;
70
+ return finish(0);
57
71
  } catch (e) {
58
72
  if (!e.silent) process.stderr.write(`Błąd: ${e.message}\n`);
59
- return e.exitCode || 1;
73
+ return finish(e.exitCode || 1);
60
74
  }
61
75
  }
62
76
 
package/src/commands.js CHANGED
@@ -543,6 +543,7 @@ Integracje MCP i Agenci AI (DeerSkills Hub):
543
543
  deertools api <produkt> <METODA> </ścieżka> Wywołuje bezpośrednio API produktu.
544
544
 
545
545
  Narzędzia systemowe:
546
+ deertools update Sprawdza i podpowiada aktualizację CLI.
546
547
  deertools doctor [--json] Pełna diagnostyka połączeń, portów i kluczy.
547
548
  deertools audit [--limit 25] [--clear] [--json] Historia operacji i wywołań API.
548
549
  deertools completion [install|zsh|bash] Autouzupełnianie w powłoce po wciśnięciu Tab.
package/src/updater.js ADDED
@@ -0,0 +1,128 @@
1
+ 'use strict';
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const os = require('os');
5
+
6
+ const CACHE_TTL_MS = 12 * 60 * 60 * 1000; // 12 hours
7
+ const REGISTRY_URL = 'https://registry.npmjs.org/@deerdesign/deertools/latest';
8
+ const PKG = require('../package.json');
9
+
10
+ function getCachePath() {
11
+ const dir = path.join(os.homedir(), '.deertools');
12
+ try {
13
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
14
+ } catch (_) {}
15
+ return path.join(dir, 'update-check.json');
16
+ }
17
+
18
+ function compareSemver(a, b) {
19
+ const pa = String(a).replace(/^v/, '').split('.').map(Number);
20
+ const pb = String(b).replace(/^v/, '').split('.').map(Number);
21
+ for (let i = 0; i < 3; i++) {
22
+ const na = pa[i] || 0;
23
+ const nb = pb[i] || 0;
24
+ if (na > nb) return 1;
25
+ if (na < nb) return -1;
26
+ }
27
+ return 0;
28
+ }
29
+
30
+ async function fetchLatestVersion() {
31
+ const ctrl = new AbortController();
32
+ const t = setTimeout(() => ctrl.abort(), 2500);
33
+ try {
34
+ const res = await fetch(REGISTRY_URL, {
35
+ headers: { 'Accept': 'application/json', 'User-Agent': 'deertools-cli' },
36
+ signal: ctrl.signal,
37
+ });
38
+ if (!res.ok) return null;
39
+ const json = await res.json();
40
+ return json.version || null;
41
+ } catch (_) {
42
+ return null;
43
+ } finally {
44
+ clearTimeout(t);
45
+ }
46
+ }
47
+
48
+ async function checkUpdate() {
49
+ const cacheFile = getCachePath();
50
+ const now = Date.now();
51
+ let cached = null;
52
+
53
+ try {
54
+ if (fs.existsSync(cacheFile)) {
55
+ cached = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
56
+ }
57
+ } catch (_) {}
58
+
59
+ let latestVersion = cached && cached.latestVersion ? cached.latestVersion : null;
60
+
61
+ if (!cached || !cached.lastChecked || (now - cached.lastChecked > CACHE_TTL_MS)) {
62
+ const fetched = await fetchLatestVersion();
63
+ if (fetched) {
64
+ latestVersion = fetched;
65
+ try {
66
+ fs.writeFileSync(cacheFile, JSON.stringify({ lastChecked: now, latestVersion }), 'utf8');
67
+ } catch (_) {}
68
+ }
69
+ }
70
+
71
+ if (latestVersion && compareSemver(latestVersion, PKG.version) > 0) {
72
+ return {
73
+ hasUpdate: true,
74
+ current: PKG.version,
75
+ latest: latestVersion,
76
+ };
77
+ }
78
+
79
+ return { hasUpdate: false, current: PKG.version, latest: latestVersion };
80
+ }
81
+
82
+ function printUpdateNotice(updateInfo) {
83
+ if (!updateInfo || !updateInfo.hasUpdate) return;
84
+ const { current, latest } = updateInfo;
85
+ const line1 = `Dostępna nowa wersja DeerTools CLI: ${current} → ${latest}`;
86
+ const line2 = `Zaktualizuj: npm install -g @deerdesign/deertools@latest`;
87
+ const line3 = `lub użyj: npx -y @deerdesign/deertools@latest <komenda>`;
88
+ const len = Math.max(line1.length, line2.length, line3.length) + 4;
89
+ const border = '─'.repeat(len);
90
+
91
+ process.stderr.write(`\n\x1b[33m┌${border}┐\x1b[0m\n`);
92
+ process.stderr.write(`\x1b[33m│ ${line1.padEnd(len - 2)}│\x1b[0m\n`);
93
+ process.stderr.write(`\x1b[33m│ ${line2.padEnd(len - 2)}│\x1b[0m\n`);
94
+ process.stderr.write(`\x1b[33m│ ${line3.padEnd(len - 2)}│\x1b[0m\n`);
95
+ process.stderr.write(`\x1b[33m└${border}┘\x1b[0m\n\n`);
96
+ }
97
+
98
+ async function cmdUpdate(pos, flags) {
99
+ process.stdout.write(`Sprawdzam aktualizacje w rejestrze npm...\n`);
100
+ const latest = await fetchLatestVersion();
101
+ if (!latest) {
102
+ process.stdout.write(`Nie udało się połączyć z rejestrem npm. Sprawdź połączenie z internetem.\n`);
103
+ return 1;
104
+ }
105
+
106
+ const cmp = compareSemver(latest, PKG.version);
107
+ if (cmp <= 0) {
108
+ process.stdout.write(`✓ DeerTools CLI jest w najnowszej wersji (${PKG.version}).\n`);
109
+ return 0;
110
+ }
111
+
112
+ process.stdout.write(`\nZnaleziono nowszą wersję: ${PKG.version} → \x1b[32m${latest}\x1b[0m\n\n`);
113
+ process.stdout.write(`Aby zaktualizować instalację globalną, uruchom:\n`);
114
+ process.stdout.write(` \x1b[36mnpm install -g @deerdesign/deertools@latest\x1b[0m\n\n`);
115
+ process.stdout.write(`Jeśli instalacja wymaga uprawnień administratora:\n`);
116
+ process.stdout.write(` \x1b[36msudo npm install -g @deerdesign/deertools@latest\x1b[0m\n\n`);
117
+ process.stdout.write(`A jeśli korzystasz z npx, każda komenda zawsze pobiera najnowszą wersję z tagiem @latest:\n`);
118
+ process.stdout.write(` \x1b[36mnpx -y @deerdesign/deertools@latest <komenda>\x1b[0m\n\n`);
119
+ return 0;
120
+ }
121
+
122
+ module.exports = {
123
+ checkUpdate,
124
+ printUpdateNotice,
125
+ cmdUpdate,
126
+ compareSemver,
127
+ fetchLatestVersion,
128
+ };