1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//! Detect project roots and technology stacks from generic process metadata.
//!
//! `what-stack` is a small standalone library. It does not depend on Docker,
//! socket collection, async runtimes, logging, serialization, CLI parsing, or
//! any application-specific types. Callers pass ordinary strings and paths:
//! image names, project directories, process names, executable paths, working
//! directories, and command-line arguments.
//!
//! # Detection Model
//!
//! The crate exposes focused single-purpose functions plus [`StackDetector`]
//! for repeated lookups with caching:
//!
//! - [`detect_from_image`] parses container or artifact image names.
//! - [`detect_from_config`] scans one project-root directory for known project
//! files.
//! - [`detect_from_process`] maps known runtime, server, database, and tool
//! executable names; [`detect_from_process_names`] adds an executable-name
//! fallback.
//! - [`find_project_root`] walks upward from one directory until it finds a
//! project marker.
//! - [`resolve_project_root`] applies the project-root fallback order used by
//! process collectors: current working directory, executable parent, then
//! absolute command-line argument parents.
//! - [`StackDetector`] combines those rules and caches filesystem results.
//!
//! Every detected [`StackLabel`] carries a [`StackKind`] (runtime, framework,
//! tool, database, or service).
//!
//! High-level stack detection in [`StackDetector::detect_stack`] uses this
//! priority:
//!
//! 1. Image label.
//! 2. Process label, when it is final (framework, database, or service).
//! 3. Project config label.
//! 4. Process label (runtime or tool).
//!
//! Config labels are guarded: a project config is used only when the process
//! is a known runtime or tool, or when the process is unknown but its
//! executable belongs to the project. This keeps a `postgres` or
//! `nginx` process started from a Next.js folder labeled as itself, and keeps
//! unrelated helper shells from inheriting a project's framework label just
//! because their working directory happens to be inside that project.
//!
//! Config labels are also ecosystem-aware: a known runtime or tool accepts
//! only config labels from its own ecosystem. In a Laravel project with
//! `vite.config.js`, `php` is `Laravel` and `node` is `Vite`; a `python`
//! process in a Next.js folder stays `Python`.
//!
//! # Scope
//!
//! This crate only detects labels. It does not discover running processes,
//! inspect network ports, query container engines, kill processes, read custom
//! rule files, or format user-facing output.
//!
//! # Examples
//!
//! Direct image and process detection:
//!
//! ```
//! use what_stack::{StackKind, detect_from_image, detect_from_process};
//!
//! let nginx = detect_from_image("ghcr.io/org/nginx:latest").expect("known image");
//! assert_eq!(nginx, "Nginx");
//! assert_eq!(nginx.kind(), StackKind::Service);
//! assert_eq!(detect_from_process("node.exe").expect("known process"), "Node.js");
//! ```
//!
//! Cached high-level detection:
//!
//! ```
//! use what_stack::{StackDetector, StackInput};
//!
//! let mut detector = StackDetector::new();
//! let label = detector.detect_stack(StackInput::new("").image("redis:7-alpine"));
//!
//! assert_eq!(label.expect("known image"), "Redis");
//! ```
pub use detect_from_config;
pub use StackDetector;
pub use detect_from_image;
pub use ;
pub use ;
pub use ;
/// Compiles the README examples as doctests.
;