domsniper 0.1.1 → 0.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domsniper",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "All-in-one domain intelligence toolkit — availability checker, security recon, portfolio manager. Built with Bun.",
5
5
  "module": "src/index.tsx",
6
6
  "type": "module",
package/src/app.tsx CHANGED
@@ -90,7 +90,7 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
90
90
  const [showPortfolio, setShowPortfolio] = useState(false);
91
91
  const [filter, setFilter] = useState<FilterConfig>({ ...DEFAULT_FILTER });
92
92
  const [logs, setLogs] = useState<{ id: number; time: string; msg: string; fg: string }[]>([
93
- { id: 0, time: ts(), msg: "Domain Sniper v2.0 initialized", fg: theme.textMuted },
93
+ { id: 0, time: ts(), msg: "Domain Sniper v0.1.3 initialized", fg: theme.textMuted },
94
94
  { id: 1, time: ts(), msg: "Press ? for all commands", fg: theme.textMuted },
95
95
  ]);
96
96
  const [registrarConfig] = useState<RegistrarConfig | null>(loadConfigFromEnv());
@@ -424,7 +424,7 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
424
424
  if (showPortfolio && key === "escape") { setShowPortfolio(false); return; }
425
425
 
426
426
  // ── Marketplace toggle ──
427
- if (key === "M" && mode !== "input" && !showPortfolio) {
427
+ if (key === "M" && mode !== "input") {
428
428
  if (!showMarket) {
429
429
  setShowMarket(true);
430
430
  setMarketView("browse");
@@ -569,6 +569,35 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
569
569
  return;
570
570
  }
571
571
 
572
+ // ── Overlay toggles (work in any non-input mode) ──
573
+
574
+ // Toggle recon mode (already past input mode guard)
575
+ if (key === "n" && !ctrl) {
576
+ setReconMode((v) => {
577
+ const newVal = !v;
578
+ log(newVal ? "Recon mode ON (full pentest — rescan to apply)" : "Recon mode OFF (fast scan)", newVal ? theme.warning : theme.textMuted);
579
+ return newVal;
580
+ });
581
+ return;
582
+ }
583
+
584
+ // Snipe selected domain (already past input mode guard)
585
+ if (key === "S" && selected) {
586
+ if (selected.status === "taken" || selected.status === "expired") {
587
+ snipeDomain(selected.domain, {
588
+ expiryDate: selected.whois?.expiryDate || undefined,
589
+ });
590
+ const phase = selected.status === "expired" ? "frequent" : "hourly";
591
+ log(`Sniping ${selected.domain} — ${selected.status === "expired" ? "expired, checking every 5 min" : "watching for expiry"}`, theme.warning);
592
+ log(`Run 'domain-sniper snipe run' to start the engine`, theme.textDisabled);
593
+ } else if (selected.status === "available") {
594
+ log(`${selected.domain} is already available — press r to register now`, theme.primary);
595
+ } else {
596
+ log(`Cannot snipe ${selected.domain} (status: ${selected.status})`, theme.textMuted);
597
+ }
598
+ return;
599
+ }
600
+
572
601
  // ── Navigation ──
573
602
  if (mode === "scanning" || mode === "done" || mode === "watching") {
574
603
  if (key === "up" || key === "k" || (ctrl && key === "p")) setSelectedIndex((i: number) => Math.max(0, i - 1));
@@ -696,15 +725,6 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
696
725
  }
697
726
  }
698
727
 
699
- // Toggle recon mode (Issue 4: fix inverted message)
700
- else if (key === "n") {
701
- setReconMode((v) => {
702
- const newVal = !v;
703
- log(newVal ? "Recon mode ON (full pentest — rescan to apply)" : "Recon mode OFF (fast scan)", newVal ? theme.warning : theme.textMuted);
704
- return newVal;
705
- });
706
- }
707
-
708
728
  // Add to portfolio
709
729
  else if (key === "p" && selected) {
710
730
  try {
@@ -719,22 +739,6 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
719
739
  }
720
740
  }
721
741
 
722
- // Snipe selected domain
723
- else if (key === "S" && selected) {
724
- if (selected.status === "taken" || selected.status === "expired") {
725
- snipeDomain(selected.domain, {
726
- expiryDate: selected.whois?.expiryDate || undefined,
727
- });
728
- const phase = selected.status === "expired" ? "frequent" : "hourly";
729
- log(`Sniping ${selected.domain} — ${selected.status === "expired" ? "expired, checking every 5 min" : "watching for expiry"}`, theme.warning);
730
- log(`Run 'domain-sniper snipe run' to start the engine`, theme.textDisabled);
731
- } else if (selected.status === "available") {
732
- log(`${selected.domain} is already available — press r to register now`, theme.primary);
733
- } else {
734
- log(`Cannot snipe ${selected.domain} (status: ${selected.status})`, theme.textMuted);
735
- }
736
- }
737
-
738
742
  // Clear cache for selected domain
739
743
  else if (key === "c" && selected) {
740
744
  const count = clearCache(selected.domain);
@@ -1057,7 +1061,7 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
1057
1061
  const status = item.status || "—";
1058
1062
  const verified = item.verified ? "✓" : " ";
1059
1063
  return (
1060
- <box key={item.id || i} flexDirection="row" backgroundColor={active ? theme.secondaryDim : "transparent"} paddingLeft={1} gap={1}>
1064
+ <box key={item.id || i} flexDirection="row" backgroundColor={active ? theme.secondaryDim : "transparent"} paddingLeft={1} gap={1} onMouseDown={() => setMarketSelectedIdx(i)}>
1061
1065
  <text content={verified} fg={theme.primary} />
1062
1066
  <text content={pad(domain, 28)} fg={active ? theme.text : theme.textSecondary} />
1063
1067
  <text content={`$${price}`} fg={theme.warning} />
@@ -1237,7 +1241,7 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
1237
1241
  const cached = domainScores.get(entry.domain);
1238
1242
  const gr = cached?.grade ?? scoreGrade(0);
1239
1243
  return (
1240
- <box key={entry.domain} flexDirection="row" backgroundColor={active ? theme.primaryDim : "transparent"} paddingLeft={1} gap={1}>
1244
+ <box key={entry.domain} flexDirection="row" backgroundColor={active ? theme.primaryDim : "transparent"} paddingLeft={1} gap={1} onMouseDown={() => setSelectedIndex(i)}>
1241
1245
  <text content={entry.tagged ? "◉" : " "} fg={entry.tagged ? theme.info : "transparent"} />
1242
1246
  <text content={ss.icon} fg={ss.fg} />
1243
1247
  <text content={entry.domain} fg={active ? theme.text : theme.textSecondary} />
@@ -1282,7 +1286,7 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
1282
1286
  {selected && !showHelp && (
1283
1287
  <box flexDirection="row" paddingLeft={1} gap={1} flexShrink={0}>
1284
1288
  {(["overview", "dns", "security", "recon"] as IntelTab[]).map((tab) => (
1285
- <box key={tab} backgroundColor={intelTab === tab ? theme.primaryDim : "transparent"}>
1289
+ <box key={tab} backgroundColor={intelTab === tab ? theme.primaryDim : "transparent"} onMouseDown={() => setIntelTab(tab)}>
1286
1290
  <text content={` ${tab.toUpperCase()} `} fg={intelTab === tab ? theme.primary : theme.textDisabled} />
1287
1291
  </box>
1288
1292
  ))}
@@ -1876,7 +1880,7 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
1876
1880
  <text content="" />
1877
1881
  <box flexDirection="row" gap={1} justifyContent="center">
1878
1882
  <text content="◆" fg={theme.primary} />
1879
- <text content="DOMAIN SNIPER" fg={theme.primary} />
1883
+ <text content="DOMAIN SNIPER v0.1.3" fg={theme.primary} />
1880
1884
  </box>
1881
1885
  <box justifyContent="center">
1882
1886
  <text content="Domain Intelligence & Security Recon" fg={theme.textDisabled} />
@@ -2020,18 +2024,18 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
2020
2024
  <box flexDirection="row" gap={1}>
2021
2025
  {mode !== "input" ? (
2022
2026
  (() => {
2023
- const footerHints: { key: string; label: string; priority: number }[] = [
2024
- { key: "/", label: "scan", priority: 1 },
2027
+ const footerHints: { key: string; label: string; priority: number; onClick?: () => void }[] = [
2028
+ { key: "/", label: "scan", priority: 1, onClick: () => { setInputMode("domain"); setMode("input"); setInputValue(""); } },
2025
2029
  { key: "␣", label: "tag", priority: 2 },
2026
- { key: "?", label: "help", priority: 3 },
2027
- { key: "n", label: reconMode ? "recon:ON" : "recon", priority: 4 },
2028
- { key: "M", label: "market", priority: 5 },
2030
+ { key: "?", label: "help", priority: 3, onClick: () => setShowHelp((v) => !v) },
2031
+ { key: "n", label: reconMode ? "recon:ON" : "recon", priority: 4, onClick: () => setReconMode((v) => !v) },
2032
+ { key: "M", label: "market", priority: 5, onClick: () => { if (!showMarket) { setShowMarket(true); setMarketView("browse"); setMarketSelectedIdx(0); void loadMarketListings(); } else { setShowMarket(false); } } },
2029
2033
  { key: "S", label: "snipe", priority: 6 },
2030
- { key: "e", label: "expand", priority: 7 },
2034
+ { key: "e", label: "expand", priority: 7, onClick: () => { setInputMode("expand"); setMode("input"); setInputValue(""); } },
2031
2035
  { key: "Tab", label: "tabs", priority: 8 },
2032
2036
  ...(registrarConfig?.apiKey ? [{ key: "r", label: "reg", priority: 9 }] : []),
2033
2037
  { key: "d", label: "suggest", priority: 10 },
2034
- { key: "P", label: showPortfolio ? "close" : "dash", priority: 11 },
2038
+ { key: "P", label: showPortfolio ? "close" : "dash", priority: 11, onClick: () => setShowPortfolio((v) => !v) },
2035
2039
  { key: "p", label: "portfolio", priority: 12 },
2036
2040
  ];
2037
2041
  const maxHints = Math.floor((width - 20) / 10);
@@ -2039,7 +2043,7 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
2039
2043
  return (
2040
2044
  <>
2041
2045
  {visibleHints.map((h) => (
2042
- <box key={h.key} flexDirection="row" gap={0}>
2046
+ <box key={h.key} flexDirection="row" gap={0} onMouseDown={h.onClick}>
2043
2047
  <box backgroundColor={theme.textDisabled}><text content={` ${h.key} `} fg={theme.background} /></box>
2044
2048
  <text content={h.label} fg={h.key === "n" && reconMode ? theme.error : h.key === "P" && showPortfolio ? theme.primary : h.key === "M" && showMarket ? theme.secondary : theme.textMuted} />
2045
2049
  </box>
@@ -2054,7 +2058,7 @@ export function App({ initialDomains, batchFile, autoRegister = false }: AppProp
2054
2058
  </>
2055
2059
  )}
2056
2060
  </box>
2057
- <text content={stats.total > 0 ? `${stats.available + stats.expired}/${stats.total} actionable` : "v2.0"} fg={theme.textDisabled} />
2061
+ <text content={stats.total > 0 ? `${stats.available + stats.expired}/${stats.total} actionable` : "v0.1.3"} fg={theme.textDisabled} />
2058
2062
  </box>
2059
2063
  </box>
2060
2064
  </box>
package/src/index.tsx CHANGED
@@ -43,7 +43,7 @@ const program = new Command();
43
43
  program
44
44
  .name("dsniper")
45
45
  .description("All-in-one domain intelligence toolkit — availability checker, security recon, portfolio manager")
46
- .version("0.1.1")
46
+ .version("0.1.3")
47
47
  .argument("[domains...]", "Domain(s) to check")
48
48
  .option("-f, --file <path>", "Path to file with domains (one per line)")
49
49
  .option("-a, --auto-register", "Automatically register available domains", false)
@@ -72,6 +72,7 @@ program
72
72
  const renderer = await createCliRenderer({
73
73
  exitOnCtrlC: true,
74
74
  screenMode: "alternate-screen",
75
+ useMouse: true,
75
76
  });
76
77
 
77
78
  createRoot(renderer).render(
@@ -873,7 +874,15 @@ program
873
874
  .option("--port <port>", "Port number", "3000")
874
875
  .action(async (opts: { port: string }) => {
875
876
  process.env.MARKET_PORT = opts.port;
876
- await import("../marketplace/index.js");
877
+ const marketPath = "../marketplace/index.js";
878
+ try {
879
+ await import(/* @vite-ignore */ marketPath);
880
+ } catch {
881
+ console.error("Marketplace server not found. Clone the private marketplace repo:");
882
+ console.error(" git clone https://github.com/t-rhex/domain-sniper-marketplace marketplace/");
883
+ console.error(" bun run serve");
884
+ process.exit(1);
885
+ }
877
886
  });
878
887
 
879
888
  // ─── Market subcommand ─────────────────────────────────