litmus-cli 1.0.4 → 1.0.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.
@@ -1 +1 @@
1
- {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/lib/tracker.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAyBrD"}
1
+ {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/lib/tracker.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CA4BrD"}
@@ -1,5 +1,5 @@
1
1
  import { spawn } from "child_process";
2
- import { mkdirSync, writeFileSync } from "fs";
2
+ import { mkdirSync, openSync, writeFileSync } from "fs";
3
3
  import path from "path";
4
4
  import { fileURLToPath } from "url";
5
5
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -12,6 +12,7 @@ export function startTracker(projectDir) {
12
12
  const litmusDir = path.join(projectDir, ".litmus");
13
13
  const activityLog = path.join(litmusDir, "activity.jsonl");
14
14
  const pidFile = path.join(litmusDir, "tracker.pid");
15
+ const errLog = path.join(litmusDir, "tracker.log");
15
16
  const watcherScript = path.join(__dirname, "watcher.cjs");
16
17
  try {
17
18
  mkdirSync(litmusDir, { recursive: true });
@@ -19,9 +20,10 @@ export function startTracker(projectDir) {
19
20
  catch {
20
21
  // Non-critical
21
22
  }
23
+ const errFd = openSync(errLog, "a");
22
24
  const child = spawn("node", [watcherScript, projectDir, activityLog], {
23
25
  detached: true,
24
- stdio: "ignore",
26
+ stdio: ["ignore", "ignore", errFd],
25
27
  });
26
28
  if (child.pid) {
27
29
  child.unref();
@@ -1 +1 @@
1
- {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/lib/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACrC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAC7C,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAEnC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAE9D;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;IAClD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAA;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IACnD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAEzD,IAAI,CAAC;QACH,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,aAAa,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE;QACpE,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAA;IAEF,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,IAAI,CAAC;YACH,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAA;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/lib/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACrC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AACvD,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAEnC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAE9D;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;IAClD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAA;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAClD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAEzD,IAAI,CAAC;QACH,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAEnC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,aAAa,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE;QACpE,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC;KACnC,CAAC,CAAA;IAEF,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,IAAI,CAAC;YACH,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAA;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Litmus file activity watcher.
4
+ * Runs as a detached background process started by `litmus init`.
5
+ * Usage: node watcher.cjs <projectDir> <activityLogPath>
6
+ *
7
+ * Uses Node's built-in fs.watch (no external dependencies).
8
+ * Writes newline-delimited JSON to the activity log:
9
+ * { "ts": "ISO-8601", "type": "rename"|"change", "path": "relative/path" }
10
+ */
11
+
12
+ const fs = require("fs")
13
+ const path = require("path")
14
+
15
+ const [, , projectDir, activityLogPath] = process.argv
16
+
17
+ process.stderr.write(`[watcher] starting: projectDir=${projectDir} log=${activityLogPath}\n`)
18
+ process.stderr.write(`[watcher] node ${process.version}, platform=${process.platform}, arch=${process.arch}\n`)
19
+
20
+ if (!projectDir || !activityLogPath) {
21
+ process.stderr.write("[watcher] missing arguments\n")
22
+ process.exit(1)
23
+ }
24
+
25
+ if (!fs.existsSync(projectDir)) {
26
+ process.stderr.write(`[watcher] projectDir does not exist: ${projectDir}\n`)
27
+ process.exit(1)
28
+ }
29
+
30
+ // Ensure the log directory exists
31
+ fs.mkdirSync(path.dirname(activityLogPath), { recursive: true })
32
+
33
+ // Open the log file for appending
34
+ const log = fs.createWriteStream(activityLogPath, { flags: "a" })
35
+
36
+ const IGNORED = [
37
+ /[/\\]\./, // dotfiles and dotdirs (including .git, .litmus)
38
+ /node_modules/,
39
+ /__pycache__/,
40
+ /\.pyc$/,
41
+ /\.class$/,
42
+ /[/\\]venv[/\\]/,
43
+ /[/\\]\.venv[/\\]/,
44
+ ]
45
+
46
+ function shouldIgnore(relPath) {
47
+ return IGNORED.some((re) => re.test(relPath))
48
+ }
49
+
50
+ function write(type, relPath) {
51
+ const event = JSON.stringify({
52
+ ts: new Date().toISOString(),
53
+ type,
54
+ path: relPath,
55
+ })
56
+ log.write(event + "\n")
57
+ }
58
+
59
+ process.on("uncaughtException", (err) => {
60
+ process.stderr.write(`[watcher] uncaughtException: ${err.stack || err}\n`)
61
+ process.exit(1)
62
+ })
63
+
64
+ try {
65
+ const watcher = fs.watch(projectDir, { recursive: true }, (eventType, filename) => {
66
+ if (!filename) return
67
+ if (shouldIgnore(filename)) return
68
+ write(eventType, filename)
69
+ })
70
+
71
+ watcher.on("error", (err) => {
72
+ process.stderr.write(`[watcher] fs.watch error: ${err}\n`)
73
+ })
74
+
75
+ process.stderr.write("[watcher] started successfully\n")
76
+ } catch (err) {
77
+ process.stderr.write(`[watcher] failed to start: ${err.stack || err}\n`)
78
+ process.exit(1)
79
+ }
package/dist/watcher.cjs CHANGED
@@ -14,8 +14,16 @@ const path = require("path")
14
14
 
15
15
  const [, , projectDir, activityLogPath] = process.argv
16
16
 
17
+ process.stderr.write(`[watcher] starting: projectDir=${projectDir} log=${activityLogPath}\n`)
18
+ process.stderr.write(`[watcher] node ${process.version}, platform=${process.platform}, arch=${process.arch}\n`)
19
+
17
20
  if (!projectDir || !activityLogPath) {
18
- process.stderr.write("Usage: node watcher.cjs <projectDir> <activityLogPath>\n")
21
+ process.stderr.write("[watcher] missing arguments\n")
22
+ process.exit(1)
23
+ }
24
+
25
+ if (!fs.existsSync(projectDir)) {
26
+ process.stderr.write(`[watcher] projectDir does not exist: ${projectDir}\n`)
19
27
  process.exit(1)
20
28
  }
21
29
 
@@ -48,13 +56,24 @@ function write(type, relPath) {
48
56
  log.write(event + "\n")
49
57
  }
50
58
 
59
+ process.on("uncaughtException", (err) => {
60
+ process.stderr.write(`[watcher] uncaughtException: ${err.stack || err}\n`)
61
+ process.exit(1)
62
+ })
63
+
51
64
  try {
52
- fs.watch(projectDir, { recursive: true }, (eventType, filename) => {
65
+ const watcher = fs.watch(projectDir, { recursive: true }, (eventType, filename) => {
53
66
  if (!filename) return
54
67
  if (shouldIgnore(filename)) return
55
68
  write(eventType, filename)
56
69
  })
70
+
71
+ watcher.on("error", (err) => {
72
+ process.stderr.write(`[watcher] fs.watch error: ${err}\n`)
73
+ })
74
+
75
+ process.stderr.write("[watcher] started successfully\n")
57
76
  } catch (err) {
58
- process.stderr.write(`[watcher] failed to start: ${err}\n`)
77
+ process.stderr.write(`[watcher] failed to start: ${err.stack || err}\n`)
59
78
  process.exit(1)
60
79
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litmus-cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "CLI tool for Litmus engineering assessments",
5
5
  "license": "MIT",
6
6
  "author": "elenazhao",
@@ -10,7 +10,7 @@
10
10
  "litmus": "dist/index.js"
11
11
  },
12
12
  "scripts": {
13
- "build": "tsc && cp src/lib/watcher.cjs dist/watcher.cjs",
13
+ "build": "tsc && cp src/lib/watcher.cjs dist/lib/watcher.cjs",
14
14
  "dev": "tsc --watch",
15
15
  "start": "node dist/index.js",
16
16
  "prepublishOnly": "npm run build"
@@ -1,5 +1,5 @@
1
1
  import { spawn } from "child_process"
2
- import { mkdirSync, writeFileSync } from "fs"
2
+ import { mkdirSync, openSync, writeFileSync } from "fs"
3
3
  import path from "path"
4
4
  import { fileURLToPath } from "url"
5
5
 
@@ -14,6 +14,7 @@ export function startTracker(projectDir: string): void {
14
14
  const litmusDir = path.join(projectDir, ".litmus")
15
15
  const activityLog = path.join(litmusDir, "activity.jsonl")
16
16
  const pidFile = path.join(litmusDir, "tracker.pid")
17
+ const errLog = path.join(litmusDir, "tracker.log")
17
18
  const watcherScript = path.join(__dirname, "watcher.cjs")
18
19
 
19
20
  try {
@@ -22,9 +23,11 @@ export function startTracker(projectDir: string): void {
22
23
  // Non-critical
23
24
  }
24
25
 
26
+ const errFd = openSync(errLog, "a")
27
+
25
28
  const child = spawn("node", [watcherScript, projectDir, activityLog], {
26
29
  detached: true,
27
- stdio: "ignore",
30
+ stdio: ["ignore", "ignore", errFd],
28
31
  })
29
32
 
30
33
  if (child.pid) {
@@ -14,8 +14,16 @@ const path = require("path")
14
14
 
15
15
  const [, , projectDir, activityLogPath] = process.argv
16
16
 
17
+ process.stderr.write(`[watcher] starting: projectDir=${projectDir} log=${activityLogPath}\n`)
18
+ process.stderr.write(`[watcher] node ${process.version}, platform=${process.platform}, arch=${process.arch}\n`)
19
+
17
20
  if (!projectDir || !activityLogPath) {
18
- process.stderr.write("Usage: node watcher.cjs <projectDir> <activityLogPath>\n")
21
+ process.stderr.write("[watcher] missing arguments\n")
22
+ process.exit(1)
23
+ }
24
+
25
+ if (!fs.existsSync(projectDir)) {
26
+ process.stderr.write(`[watcher] projectDir does not exist: ${projectDir}\n`)
19
27
  process.exit(1)
20
28
  }
21
29
 
@@ -48,13 +56,24 @@ function write(type, relPath) {
48
56
  log.write(event + "\n")
49
57
  }
50
58
 
59
+ process.on("uncaughtException", (err) => {
60
+ process.stderr.write(`[watcher] uncaughtException: ${err.stack || err}\n`)
61
+ process.exit(1)
62
+ })
63
+
51
64
  try {
52
- fs.watch(projectDir, { recursive: true }, (eventType, filename) => {
65
+ const watcher = fs.watch(projectDir, { recursive: true }, (eventType, filename) => {
53
66
  if (!filename) return
54
67
  if (shouldIgnore(filename)) return
55
68
  write(eventType, filename)
56
69
  })
70
+
71
+ watcher.on("error", (err) => {
72
+ process.stderr.write(`[watcher] fs.watch error: ${err}\n`)
73
+ })
74
+
75
+ process.stderr.write("[watcher] started successfully\n")
57
76
  } catch (err) {
58
- process.stderr.write(`[watcher] failed to start: ${err}\n`)
77
+ process.stderr.write(`[watcher] failed to start: ${err.stack || err}\n`)
59
78
  process.exit(1)
60
79
  }