termsearch 0.3.4 → 0.3.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/bin/termsearch.js CHANGED
@@ -209,7 +209,7 @@ async function cmdStart(flags) {
209
209
  }
210
210
 
211
211
  writeFileSync(paths.pid, String(child.pid));
212
- ok(`Started (PID ${child.pid})`);
212
+ ok(`TermSearch v${VERSION} started (PID ${child.pid})`);
213
213
  info(`${BOLD}${getUrl()}${RESET}`);
214
214
  info(`Logs: ${paths.log}`);
215
215
  }
@@ -242,10 +242,11 @@ async function cmdRestart(flags) {
242
242
  await cmdStart(flags);
243
243
  }
244
244
 
245
- function cmdStatus() {
245
+ async function cmdStatus() {
246
246
  const { running, pid } = getStatus();
247
247
  const paths = getPaths();
248
248
  console.log('');
249
+ console.log(` ${BOLD}TermSearch v${VERSION}${RESET}`);
249
250
  if (running) {
250
251
  ok(`${BOLD}Running${RESET} (PID ${pid})`);
251
252
  info(`${getUrl()}`);
@@ -255,6 +256,7 @@ function cmdStatus() {
255
256
  warn('Stopped');
256
257
  info(`Run ${BOLD}termsearch start${RESET} to start`);
257
258
  }
259
+ await printUpdateHint();
258
260
  console.log('');
259
261
  }
260
262
 
@@ -333,6 +335,9 @@ async function cmdDoctor() {
333
335
  } catch (e) { err(`HTTP: cannot reach ${getUrl()} — ${e.message}`); allOk = false; }
334
336
  }
335
337
 
338
+ // npm update check
339
+ await printUpdateHint();
340
+
336
341
  console.log('');
337
342
  if (allOk) { ok(`${GREEN}All checks passed${RESET}`); }
338
343
  else { warn('Some checks failed — see above'); }
@@ -371,7 +376,7 @@ async function cmdAutostart(sub) {
371
376
  async function cmdDefault(flags) {
372
377
  const { running, pid } = getStatus();
373
378
  if (running) {
374
- cmdStatus();
379
+ await cmdStatus();
375
380
  } else {
376
381
  await cmdStart(flags);
377
382
  if (getStatus().running) {
@@ -428,6 +433,39 @@ ${BOLD}URL:${RESET} http://localhost:3000
428
433
  `);
429
434
  }
430
435
 
436
+ // ─── Update check ─────────────────────────────────────────────────────────
437
+
438
+ async function checkNpmUpdate() {
439
+ try {
440
+ const ac = new AbortController();
441
+ setTimeout(() => ac.abort(), 4000);
442
+ const r = await fetch('https://registry.npmjs.org/termsearch/latest', { signal: ac.signal });
443
+ if (!r.ok) return null;
444
+ const data = await r.json();
445
+ const latest = data.version;
446
+ if (!latest) return null;
447
+ if (latest === VERSION) return { upToDate: true, latest };
448
+ // Simple semver compare: split, compare numerically
449
+ const cur = VERSION.split('.').map(Number);
450
+ const lat = latest.split('.').map(Number);
451
+ const newer = lat[0] > cur[0] || (lat[0] === cur[0] && lat[1] > cur[1]) || (lat[0] === cur[0] && lat[1] === cur[1] && lat[2] > cur[2]);
452
+ return { upToDate: !newer, latest };
453
+ } catch {
454
+ return null;
455
+ }
456
+ }
457
+
458
+ async function printUpdateHint() {
459
+ const update = await checkNpmUpdate();
460
+ if (!update) return;
461
+ if (update.upToDate) {
462
+ ok(`Up to date (v${VERSION})`);
463
+ } else {
464
+ warn(`Update available: v${VERSION} → v${update.latest}`);
465
+ info(`Run ${BOLD}npm install -g termsearch${RESET} to update`);
466
+ }
467
+ }
468
+
431
469
  // ─── Utilities ────────────────────────────────────────────────────────────
432
470
 
433
471
  function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
@@ -282,7 +282,7 @@ const ENGINE_GROUPS = [
282
282
 
283
283
  const ENGINE_PRESETS = [
284
284
  { id: 'all', label: 'All', engines: [] },
285
- { id: 'balanced', label: 'Balanced', engines: ['duckduckgo', 'wikipedia', 'bing', 'startpage', 'github', 'reddit', 'youtube'] },
285
+ { id: 'balanced', label: 'Balanced', engines: ['duckduckgo', 'wikipedia', 'bing', 'brave', 'github', 'reddit', 'youtube'] },
286
286
  { id: 'github', label: 'GitHub Focus', engines: ['github-api', 'github', 'duckduckgo', 'wikipedia'] },
287
287
  ];
288
288
 
@@ -1161,6 +1161,9 @@ async function renderSettings() {
1161
1161
  const brave = cfg.brave || {};
1162
1162
  const mojeek = cfg.mojeek || {};
1163
1163
  const searxng = cfg.searxng || {};
1164
+ const yandexCfg = cfg.yandex || {};
1165
+ const ahmiaCfg = cfg.ahmia || {};
1166
+ const marginaliaCfg = cfg.marginalia || {};
1164
1167
  const detectedPreset = detectPresetFromBase(ai.api_base);
1165
1168
 
1166
1169
  const header = el('div', { className: 'header' },
@@ -1338,6 +1341,9 @@ async function renderSettings() {
1338
1341
  brave: { enabled: isChecked('brave-enabled') },
1339
1342
  mojeek: { enabled: isChecked('mojeek-enabled') },
1340
1343
  searxng:{ url: val('searxng-url'), enabled: isChecked('searxng-enabled') },
1344
+ yandex: { enabled: isChecked('yandex-enabled') },
1345
+ ahmia: { enabled: isChecked('ahmia-enabled') },
1346
+ marginalia: { enabled: isChecked('marginalia-enabled') },
1341
1347
  };
1342
1348
  if (aiKey) update.ai.api_key = aiKey;
1343
1349
  if (braveKey) update.brave.api_key = braveKey;
@@ -1563,7 +1569,7 @@ async function renderSettings() {
1563
1569
  ),
1564
1570
 
1565
1571
  // SearXNG
1566
- el('div', { style: 'padding:10px 0' },
1572
+ el('div', { style: 'padding:10px 0;border-bottom:1px solid var(--border2)' },
1567
1573
  el('div', { className: 'toggle-row' },
1568
1574
  el('span', { className: 'toggle-label' }, 'SearXNG (self-hosted)'),
1569
1575
  el('label', { className: 'toggle' },
@@ -1578,6 +1584,33 @@ async function renderSettings() {
1578
1584
  el('div', { id: 'provider-test-searxng', style: 'display:none' }),
1579
1585
  ),
1580
1586
 
1587
+ // Uncensored / Alternative
1588
+ el('div', { style: 'padding:10px 0' },
1589
+ el('div', { style: 'font-size:11px;color:var(--text2);margin-bottom:8px;letter-spacing:0.04em;text-transform:uppercase' }, 'Uncensored / Alternative'),
1590
+ el('div', { className: 'toggle-row' },
1591
+ el('span', { className: 'toggle-label' }, 'Yandex (HTML scraper, no key)'),
1592
+ el('label', { className: 'toggle' },
1593
+ el('input', { type: 'checkbox', id: 'yandex-enabled', ...(yandexCfg.enabled !== false ? { checked: '' } : {}) }),
1594
+ el('span', { className: 'toggle-slider' }),
1595
+ ),
1596
+ ),
1597
+ el('div', { className: 'toggle-row', style: 'margin-top:6px' },
1598
+ el('span', { className: 'toggle-label' }, 'Ahmia (Tor index, no key)'),
1599
+ el('label', { className: 'toggle' },
1600
+ el('input', { type: 'checkbox', id: 'ahmia-enabled', ...(ahmiaCfg.enabled !== false ? { checked: '' } : {}) }),
1601
+ el('span', { className: 'toggle-slider' }),
1602
+ ),
1603
+ ),
1604
+ el('div', { className: 'toggle-row', style: 'margin-top:6px' },
1605
+ el('span', { className: 'toggle-label' }, 'Marginalia (indie index, no key)'),
1606
+ el('label', { className: 'toggle' },
1607
+ el('input', { type: 'checkbox', id: 'marginalia-enabled', ...(marginaliaCfg.enabled !== false ? { checked: '' } : {}) }),
1608
+ el('span', { className: 'toggle-slider' }),
1609
+ ),
1610
+ ),
1611
+ el('div', { className: 'form-hint', style: 'margin-top:6px' }, 'Zero-config scraper engines. May be blocked by CAPTCHA under heavy use.'),
1612
+ ),
1613
+
1581
1614
  el('div', { style: 'margin-top:12px;display:flex;align-items:center;gap:8px' },
1582
1615
  el('button', { className: 'btn btn-primary', onClick: saveSettings }, 'Save All'),
1583
1616
  saveAlertEl,
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "termsearch",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "Personal search engine for Termux/Linux/macOS — zero-config, privacy-first, AI-optional",
5
5
  "type": "module",
6
6
  "bin": {
7
- "termsearch": "./bin/termsearch.js"
7
+ "termsearch": "bin/termsearch.js"
8
8
  },
9
9
  "main": "./src/server.js",
10
10
  "files": [
@@ -43,6 +43,6 @@
43
43
  "license": "MIT",
44
44
  "repository": {
45
45
  "type": "git",
46
- "url": "https://github.com/DioNanos/termsearch"
46
+ "url": "git+https://github.com/DioNanos/termsearch.git"
47
47
  }
48
48
  }
@@ -17,9 +17,15 @@ function ok(msg) { console.log(` ${GREEN}✓${RESET} ${msg}`); }
17
17
  function warn(msg) { console.log(` ${YELLOW}⚠${RESET} ${msg}`); }
18
18
  function info(msg) { console.log(` ${CYAN}→${RESET} ${msg}`); }
19
19
 
20
+ let VERSION = '0.0.0';
21
+ try {
22
+ const pkgPath = new URL('../package.json', import.meta.url);
23
+ VERSION = JSON.parse(fs.readFileSync(pkgPath, 'utf8')).version || VERSION;
24
+ } catch { /* ignore */ }
25
+
20
26
  try {
21
27
  console.log('');
22
- console.log(`${BOLD} TermSearch — post-install check${RESET}`);
28
+ console.log(`${BOLD} TermSearch v${VERSION}${RESET} — post-install check`);
23
29
  console.log('');
24
30
 
25
31
  // ── Node.js version ──────────────────────────────────────────────────────
@@ -76,7 +82,7 @@ try {
76
82
  }
77
83
 
78
84
  console.log('');
79
- info(`Run ${BOLD}termsearch${RESET}${CYAN} then open http://localhost:3000`);
85
+ info(`Run ${BOLD}termsearch${RESET}${CYAN} to start v${VERSION} → http://localhost:3000`);
80
86
  console.log('');
81
87
 
82
88
  } catch {