devmap 0.3.4__py3-none-any.whl → 0.3.6__py3-none-any.whl

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.
devmap/_devmap.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  // @bun
3
3
 
4
4
  // src/version.ts
5
- var VERSION = "0.3.4";
5
+ var VERSION = "0.3.6";
6
6
 
7
7
  // src/install.ts
8
8
  function isIsolated(i) {
@@ -662,6 +662,138 @@ function runScaAudit(cwd) {
662
662
  return checks;
663
663
  }
664
664
 
665
+ // src/health/parse.ts
666
+ function parsePipCheck(text) {
667
+ const lines = (text || "").split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
668
+ const clean = lines.some((l) => /^no broken requirements found/i.test(l));
669
+ const conflicts = lines.filter((l) => !/^no broken requirements found/i.test(l));
670
+ if (clean || conflicts.length === 0) {
671
+ return { status: "ok", summary: "pip dependencies consistent" };
672
+ }
673
+ return {
674
+ status: "warn",
675
+ summary: `pip has ${conflicts.length} broken dependency requirement${conflicts.length === 1 ? "" : "s"}`,
676
+ detail: conflicts.join(`
677
+ `)
678
+ };
679
+ }
680
+ function parseNpmDoctor(text) {
681
+ const t = (text || "").trim();
682
+ if (!t)
683
+ return { status: "skipped", summary: "npm doctor produced no output (timed out or silent)" };
684
+ const lines = t.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
685
+ const NET_RE = /ECONNREFUSED|ETIMEDOUT|ENOTFOUND|getaddrinfo|EAI_|network request|registry\.npmjs\.org|request to https?:/i;
686
+ const BOILER_RE = /complete log of this run|^\s+at\s|node:internal|file:\/\//i;
687
+ const netLines = lines.filter((l) => NET_RE.test(l));
688
+ const failLines = lines.filter((l) => /npm error|✗|✖/i.test(l) && !BOILER_RE.test(l));
689
+ const realFails = failLines.filter((l) => !NET_RE.test(l));
690
+ if (realFails.length) {
691
+ return {
692
+ status: "warn",
693
+ summary: `npm doctor reported ${realFails.length} issue${realFails.length === 1 ? "" : "s"}`,
694
+ detail: realFails.join(`
695
+ `)
696
+ };
697
+ }
698
+ if (netLines.length) {
699
+ return { status: "skipped", summary: "npm doctor skipped (registry/network unreachable)" };
700
+ }
701
+ return { status: "ok", summary: "npm doctor passed" };
702
+ }
703
+ function parseRustupCheck(text) {
704
+ const t = (text || "").trim();
705
+ if (!t)
706
+ return { status: "skipped", summary: "rustup check produced no output (timed out or silent)" };
707
+ const lines = t.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
708
+ const updates = lines.filter((l) => /update available/i.test(l));
709
+ const upToDate = lines.filter((l) => /up to date/i.test(l));
710
+ if (updates.length) {
711
+ return {
712
+ status: "info",
713
+ summary: `rustup: ${updates.length} toolchain update${updates.length === 1 ? "" : "s"} available`,
714
+ detail: updates.join(`
715
+ `)
716
+ };
717
+ }
718
+ if (upToDate.length)
719
+ return { status: "ok", summary: "rustup toolchains up to date" };
720
+ return { status: "ok", summary: "rustup check passed" };
721
+ }
722
+
723
+ // src/health/scan.ts
724
+ var PROBES = [
725
+ {
726
+ id: "pip",
727
+ label: "pip",
728
+ kind: "conflict",
729
+ network: false,
730
+ candidates: [
731
+ ["pip", ["check"]],
732
+ ["pip3", ["check"]],
733
+ ["python", ["-m", "pip", "check"]],
734
+ ["python3", ["-m", "pip", "check"]]
735
+ ],
736
+ timeout: 15000,
737
+ parse: parsePipCheck
738
+ },
739
+ {
740
+ id: "npm",
741
+ label: "npm",
742
+ kind: "mismatch",
743
+ network: true,
744
+ candidates: [["npm", ["doctor"]]],
745
+ timeout: 20000,
746
+ parse: parseNpmDoctor
747
+ },
748
+ {
749
+ id: "rustup",
750
+ label: "rustup",
751
+ kind: "stale",
752
+ network: true,
753
+ candidates: [["rustup", ["check"]]],
754
+ timeout: 15000,
755
+ parse: parseRustupCheck
756
+ }
757
+ ];
758
+ function pickCandidate(p) {
759
+ const dirs = pathDirs();
760
+ for (const [cmd, args] of p.candidates) {
761
+ if (whichInDirs(cmd, dirs).length > 0)
762
+ return [cmd, args];
763
+ }
764
+ return null;
765
+ }
766
+ var SEV_OF = {
767
+ ok: "ok",
768
+ warn: "warn",
769
+ info: "info",
770
+ skipped: "info"
771
+ };
772
+ function toCheck(p, r) {
773
+ const sev = SEV_OF[r.status];
774
+ const id = `health.${p.id}.check`;
775
+ const realId = r.status === "skipped" ? `health.${p.id}.skipped` : id;
776
+ return makeCheck(realId, p.kind, sev, r.summary, r.detail || "", [], r.status === "ok" ? undefined : undefined);
777
+ }
778
+ async function computeHealth(opts = {}) {
779
+ const checks = [];
780
+ const network = opts.healthNetwork === true;
781
+ for (const p of PROBES) {
782
+ const picked = pickCandidate(p);
783
+ if (!picked)
784
+ continue;
785
+ if (p.network && !network) {
786
+ checks.push(makeCheck(`health.${p.id}.skipped`, p.kind, "info", `${p.label} doctor skipped (offline by default)`, `Run with --health-network to invoke ${p.label} self-checks (they require network).`));
787
+ continue;
788
+ }
789
+ const [cmd, args] = picked;
790
+ const out = await runAsync(cmd, args, p.timeout);
791
+ const result = p.parse(out);
792
+ checks.push(toCheck(p, result));
793
+ }
794
+ return checks;
795
+ }
796
+
665
797
  // src/output/json.ts
666
798
  function buildManifest(byName, conflicts, checks, environments, shells) {
667
799
  const sys = byName.system || {};
@@ -841,7 +973,8 @@ async function runScan(shells, disabled, opts = {}) {
841
973
  progress,
842
974
  checkOutdated: opts.checkOutdated,
843
975
  wslDeep: opts.wslDeep,
844
- auditDeps: opts.auditDeps
976
+ auditDeps: opts.auditDeps,
977
+ healthNetwork: opts.healthNetwork
845
978
  };
846
979
  const { byName, allChecks } = await runDetectors(ctx, progress);
847
980
  const groups = [
@@ -850,12 +983,13 @@ async function runScan(shells, disabled, opts = {}) {
850
983
  ...byName.ides || []
851
984
  ];
852
985
  const conflicts = computeConflicts(groups, shells, disabled);
986
+ const healthChecks = await computeHealth({ healthNetwork: opts.healthNetwork });
853
987
  const securityChecks = [
854
988
  ...computeSecurity(byName),
855
989
  ...computeScaInventory(),
856
990
  ...opts.auditDeps ? runScaAudit(process.cwd()) : []
857
991
  ];
858
- const collected = [...allChecks, ...conflicts.checks, ...securityChecks].filter((c) => !isCheckDisabled(c.ID, disabled));
992
+ const collected = [...allChecks, ...conflicts.checks, ...securityChecks, ...healthChecks].filter((c) => !isCheckDisabled(c.ID, disabled));
859
993
  const environments = {
860
994
  vcpkg: byName.vcpkg,
861
995
  pip: byName.pip,
@@ -1906,7 +2040,8 @@ async function cmdScan(opts, pos) {
1906
2040
  silent: opts.quiet === true,
1907
2041
  checkOutdated: opts.outdated === true,
1908
2042
  wslDeep: opts["wsl-deep"] === true,
1909
- auditDeps: opts["audit-deps"] === true
2043
+ auditDeps: opts["audit-deps"] === true,
2044
+ healthNetwork: opts["health-network"] === true
1910
2045
  });
1911
2046
  if (opts.json) {
1912
2047
  emitText(JSON.stringify(manifest, null, 2), opts.bom === true);
@@ -2193,6 +2328,7 @@ scan options:
2193
2328
  --wsl-deep probe inside stopped WSL distros (default probes only running ones to avoid waking distros)
2194
2329
  --ci CI gate: clean → exit 0; any warn → exit 2; any error → exit 1
2195
2330
  --audit-deps dependency CVE audit via OSV-Scanner/pip-audit/govulncheck/Trivy (opt-in, uses network)
2331
+ --health-network run network health probes too (npm doctor / rustup check; off by default to stay offline-fast)
2196
2332
  --quiet suppress scan progress feedback (for scripts/CI)
2197
2333
  --bom prepend UTF-8 BOM for viewing in Notepad etc. (only on redirect/pipe)
2198
2334
  --version / --help
@@ -0,0 +1,111 @@
1
+ Metadata-Version: 2.4
2
+ Name: devmap
3
+ Version: 0.3.6
4
+ Summary: Map your machine's dev environment and surface issues (PATH conflicts, ghost binaries, multi-version collisions). fastfetch-for-dev-tools. This PyPI package ships the real devmap CLI (a bundled JavaScript app launched via Node.js or Bun), so `pip install devmap && devmap` works standalone.
5
+ Author: devmap contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/StevenLOL/devmap
8
+ Project-URL: Repository, https://github.com/StevenLOL/devmap
9
+ Keywords: devmap,devtools,environment,scanner,fastfetch,diagnostics,dev-environment,path-conflict,ghost-binary
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Software Development :: Quality Assurance
16
+ Requires-Python: >=3.8
17
+ Description-Content-Type: text/markdown
18
+
19
+ # devmap
20
+
21
+ > A source-of-truth scanner and governance layer for your machine's development environment. One command maps the whole dev setup, draws the PATH-conflict graph, and surfaces ghost binaries and multi-version collisions.
22
+
23
+ `devmap` is the developer-focused spiritual successor to `fastfetch`: instead of only printing system specs, it scans the *development* surface of your machine — runtimes, package managers, IDEs, per-interpreter pip packages, conda/WSL/Docker environments, Visual Studio dev shells, and project-local virtual environments — and produces a single machine-readable manifest plus an actionable issue list.
24
+
25
+ ## Install
26
+
27
+ This PyPI package ships the **real devmap CLI**. It bundles the compiled devmap app and launches it via **Node.js** (or **Bun**, if present), so it works standalone — no need to install from npm or build from source:
28
+
29
+ ```bash
30
+ pip install devmap
31
+ devmap scan
32
+ ```
33
+
34
+ Requirements at runtime: a Node.js (or Bun) runtime available on `PATH`. Python itself is only used as the installer/launcher wrapper.
35
+
36
+ ## Features
37
+
38
+ - **One-command full scan** of the dev environment (runtimes, package managers, IDEs, and the environment layers below).
39
+ - **PATH conflict graph**: detects multi-version tools, shadowed binaries, and ghost/broken symlinks (e.g. Windows App Execution Aliases that look broken but aren't).
40
+ - **Off-PATH awareness**: reports installed-but-not-on-PATH tools, while correctly treating version-manager environments (conda envs, nvm versions) as by-design off-PATH.
41
+ - **Environment layers**: vcpkg packages, per-python pip packages (incl. upgradable), apt packages (Linux), conda environments, Docker (binary + daemon + images/containers), WSL distros, Visual Studio dev shells, and project-local environments (`.venv`, `node_modules`).
42
+ - **Dependency auditing (optional)**: with `--audit-deps`, devmap detects and invokes installed SCA tools (osv-scanner, govulncheck, pip-audit, Trivy), parses their JSON, and merges results into a unified view. devmap is a *scanner/orchestrator*, not a CVE database — for authoritative vulnerability data, use those tools directly.
43
+ - **Health layer**: converges official self-checks into one view — `pip check` (broken dependency requirements, **offline by default**) and, with `--health-network`, `npm doctor` / `rustup check`. Unavailable or offline probes degrade gracefully to `info`.
44
+ - **Three sub-commands**: `scan` (the fact source), `query` (ask the manifest), `devdiff` (compare two manifests — environment drift / cross-machine consistency).
45
+ - **Zero Python dependencies.** The bundled app is pure TypeScript compiled to JavaScript.
46
+
47
+ ## Usage
48
+
49
+ ```bash
50
+ devmap scan # pretty-print to terminal, write ~/.devmap/devmap.json
51
+ devmap scan --json # machine-readable JSON (devmap.json schema) to stdout
52
+ devmap scan --report # full markdown report
53
+ devmap scan --scan-root C:\src # also scan project-local envs under a root (comma-separated for many)
54
+ devmap scan --wsl-deep # also wake stopped WSL distros and probe their tools (slower)
55
+ devmap scan --outdated # hit PyPI to list upgradable pip/conda packages (slower, needs network)
56
+ devmap scan --ci # exit code 1 if any error-severity issue is found
57
+ devmap scan --audit-deps # invoke installed SCA tools and merge CVE findings
58
+ ```
59
+
60
+ Key `scan` flags:
61
+
62
+ | Flag | Description |
63
+ |------|-------------|
64
+ | `--json` | Emit machine-readable JSON (the `devmap.json` schema) to stdout. |
65
+ | `--report` | Emit a full markdown report. |
66
+ | `--no-manifest` | Do not persist the manifest to disk. |
67
+ | `--manifest <path>` | Read/write the manifest at a custom path (default `~/.devmap/devmap.json`). |
68
+ | `--disable <r1,r2>` | Disable check rules by ID prefix (e.g. `path.duplicate`, `pip.outdated`). |
69
+ | `--scan-root <dir>` | Root(s) to scan for project-local environments (comma-separated). Default: cwd. |
70
+ | `--outdated` | Network check for upgradable pip/conda packages (off by default). |
71
+ | `--wsl-deep` | Probe inside stopped WSL distros (off by default to avoid waking them). |
72
+ | `--audit-deps` | Invoke installed SCA tools and merge CVE findings into the report. |
73
+ | `--ci` | Exit non-zero on any error-severity issue. |
74
+ | `--quiet` | Suppress the live scan progress feedback (for scripts/CI). |
75
+ | `--bom` | Prefix output with a UTF-8 BOM so Notepad-like viewers render it correctly (stdout redirect/pipe only). |
76
+
77
+ ### `query` — ask the manifest
78
+
79
+ ```bash
80
+ devmap query # everything
81
+ devmap query node # tools whose id contains "node"
82
+ devmap query runtime.node # dot-form category.tool selector (runtime / pkg / ide)
83
+ devmap query --issues # only issues
84
+ devmap query --conflicts # only conflicts (multiVersion / path / ghost)
85
+ devmap query --off-path # only off-PATH installs
86
+ devmap query --kind runtime # filter by category
87
+ devmap query --where conda # filter by install path substring
88
+ ```
89
+
90
+ ### `devdiff` — compare two manifests
91
+
92
+ ```bash
93
+ devmap devdiff # stored manifest vs current live scan
94
+ devmap devdiff <file> # stored/before vs <file>
95
+ devmap devdiff <a> <b> # compare two manifest files
96
+ ```
97
+
98
+ Reports added/removed installs, version changes, and issues added/resolved.
99
+
100
+ ## Output
101
+
102
+ - The default `scan` writes the manifest to **`~/.devmap/devmap.json`** (pure UTF-8, no BOM — directly parseable by Bun/Node/Python/jq).
103
+ - Use `query` / `devdiff` against a stored manifest without re-scanning.
104
+
105
+ ## Repository
106
+
107
+ https://github.com/StevenLOL/devmap
108
+
109
+ ## License
110
+
111
+ [MIT](https://github.com/StevenLOL/devmap/blob/main/LICENSE)
@@ -0,0 +1,7 @@
1
+ devmap/__init__.py,sha256=4Ek7Di0FYYl76FKnHJ8VYiJPHlUTfoqyBB_hul_pFbk,1728
2
+ devmap/_devmap.mjs,sha256=kYiHodxsTRu90Anb1QtKk_llF1-Q21S4N9KrLuHgQsw,84108
3
+ devmap-0.3.6.dist-info/METADATA,sha256=J89bwvXkn1xoRuyarTu7e1LQgQyCohhgIVylFrS21nI,6796
4
+ devmap-0.3.6.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
5
+ devmap-0.3.6.dist-info/entry_points.txt,sha256=FOQKZCLz0WGWemrTw0suYRqKWrUB4_XJ2Gkrw60ZEcg,39
6
+ devmap-0.3.6.dist-info/top_level.txt,sha256=QeomiD_JKcjSd_jTZv0WJF3darUb2sUsxmocjgYJ6Qc,7
7
+ devmap-0.3.6.dist-info/RECORD,,
@@ -1,38 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: devmap
3
- Version: 0.3.4
4
- Summary: Map your machine's dev environment and surface issues (PATH conflicts, ghost binaries, multi-version collisions). fastfetch-for-dev-tools. This PyPI package ships the real devmap CLI (a bundled JavaScript app launched via Node.js or Bun), so `pip install devmap && devmap` works standalone.
5
- Author: devmap contributors
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/StevenLOL/devmap
8
- Project-URL: Repository, https://github.com/StevenLOL/devmap
9
- Keywords: devmap,devtools,environment,scanner,fastfetch,diagnostics,dev-environment,path-conflict,ghost-binary
10
- Classifier: Development Status :: 4 - Beta
11
- Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Operating System :: OS Independent
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Topic :: Software Development :: Quality Assurance
16
- Requires-Python: >=3.8
17
- Description-Content-Type: text/markdown
18
-
19
- # devmap (PyPI placeholder — name reserved)
20
-
21
- > **This is a placeholder package published only to reserve the `devmap`
22
- > name on PyPI.** The real implementation will replace it.
23
-
24
- ## What devmap will be
25
-
26
- A **fastfetch-for-dev-tools**: a single command that maps your machine's
27
- development environment — runtimes, package managers, version managers,
28
- containers, IDEs — and detects issues like PATH conflicts, ghost/zombie
29
- binaries, version mismatches, and stale configs.
30
-
31
- ## Status
32
-
33
- - Package name `devmap` reserved on PyPI ✅
34
- - Implementation: in progress
35
-
36
- ## Repository
37
-
38
- https://github.com/StevenLOL/devmap
@@ -1,7 +0,0 @@
1
- devmap/__init__.py,sha256=4Ek7Di0FYYl76FKnHJ8VYiJPHlUTfoqyBB_hul_pFbk,1728
2
- devmap/_devmap.mjs,sha256=CiAlcYxdruTFDH2BqFIulpEq1DQ0-HRZGKMg9zP4UQU,79539
3
- devmap-0.3.4.dist-info/METADATA,sha256=0VC6E7S2d6h97lFCi2_vc3mT6d20BqQXi0PJ1JJNwZA,1633
4
- devmap-0.3.4.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
5
- devmap-0.3.4.dist-info/entry_points.txt,sha256=FOQKZCLz0WGWemrTw0suYRqKWrUB4_XJ2Gkrw60ZEcg,39
6
- devmap-0.3.4.dist-info/top_level.txt,sha256=QeomiD_JKcjSd_jTZv0WJF3darUb2sUsxmocjgYJ6Qc,7
7
- devmap-0.3.4.dist-info/RECORD,,
File without changes