@controlfront/detect 0.0.1 → 0.0.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": "@controlfront/detect",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -17,6 +17,7 @@
17
17
  "src/config/",
18
18
  "src/engine/",
19
19
  "src/baseline/",
20
+ "src/fileCharacteristics/",
20
21
  "src/utils/",
21
22
  "src/rules/core/",
22
23
  "src/lib/",
@@ -14,6 +14,11 @@ dotenv.config({
14
14
  });
15
15
 
16
16
  export function getStoredEnvironment() {
17
+ // Explicit env var takes highest priority
18
+ if (process.env.CF_ENV) {
19
+ return process.env.CF_ENV === "prod" ? "prod" : "dev";
20
+ }
21
+
17
22
  try {
18
23
  const configPath = path.join(os.homedir(), ".cf", "config.json");
19
24
  if (fs.existsSync(configPath)) {
@@ -23,6 +28,12 @@ export function getStoredEnvironment() {
23
28
  } catch (e) {
24
29
  // ignore errors
25
30
  }
31
+
32
+ // In CI environments (e.g. GitHub Actions) with no local config, default to prod
33
+ if (process.env.CI) {
34
+ return "prod";
35
+ }
36
+
26
37
  return "dev";
27
38
  }
28
39
 
@@ -0,0 +1,71 @@
1
+ /**
2
+ * collectFileIndicators
3
+ *
4
+ * Single responsibility:
5
+ * Given a list of files, collect raw, per-file indicator facts.
6
+ *
7
+ * Indicators are low-level, observable facts.
8
+ * No characteristics, baselines, deltas, or aggregation live here.
9
+ */
10
+
11
+ import fs from "fs";
12
+ import path from "path";
13
+
14
+ /**
15
+ * @param {string[]} files - Repo-relative file paths
16
+ * @param {{ repoRoot?: string }} options
17
+ * @returns {Promise<Record<string, { indicators: Record<string, number | boolean> }>>}
18
+ */
19
+ export async function collectFileIndicators(files, options = {}) {
20
+ const { repoRoot = process.cwd() } = options;
21
+
22
+ const results = {};
23
+
24
+ for (const file of files) {
25
+ const absolutePath = path.isAbsolute(file)
26
+ ? file
27
+ : path.join(repoRoot, file);
28
+
29
+ const relativePath = path.relative(repoRoot, absolutePath);
30
+
31
+ const indicators = {};
32
+
33
+ // ---- Minimal v1 indicator set ----
34
+ try {
35
+ const source = fs.readFileSync(absolutePath, "utf8");
36
+
37
+ // LOC (lines of code)
38
+ indicators.loc = source.split("\n").length;
39
+
40
+ // Import statement count (ESM only)
41
+ const importMatches = source.match(/^\s*import\s+/gm);
42
+ indicators.import_statement_count = importMatches
43
+ ? importMatches.length
44
+ : 0;
45
+
46
+ // JSX node count
47
+ if (/\.(jsx|tsx)$/.test(absolutePath)) {
48
+ const jsxMatches = source.match(/<\s*[A-Za-z]/g);
49
+ indicators.jsx_node_count = jsxMatches ? jsxMatches.length : 0;
50
+ }
51
+ } catch (err) {
52
+ // If file cannot be read (binary, deleted, etc), skip gracefully
53
+ indicators.loc = 0;
54
+ indicators.import_statement_count = 0;
55
+ }
56
+
57
+ if (indicators.jsx_node_count === undefined) {
58
+ indicators.jsx_node_count = 0;
59
+ }
60
+
61
+ if (indicators.import_statement_count === undefined) {
62
+ indicators.import_statement_count = 0;
63
+ }
64
+
65
+ results[relativePath] = { indicators };
66
+ }
67
+
68
+ return results;
69
+ }
70
+
71
+ export default collectFileIndicators;