aem-ext-daemon 0.3.6 → 0.3.8

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.
@@ -5,6 +5,7 @@
5
5
  * shell:exec runs a command and returns the full output.
6
6
  */
7
7
  import { execSync, spawn } from "node:child_process";
8
+ import fs from "node:fs";
8
9
  import os from "node:os";
9
10
  const EXEC_TIMEOUT = 120_000; // 2 minutes
10
11
  const MAX_BUFFER = 5 * 1024 * 1024; // 5MB
@@ -39,6 +40,11 @@ function getEnhancedEnv() {
39
40
  export function exec(command, cwd) {
40
41
  if (!command)
41
42
  throw new Error("command is required");
43
+ // Ensure the working directory exists locally — the server may have
44
+ // computed the path but only created it on its own filesystem.
45
+ if (!fs.existsSync(cwd)) {
46
+ fs.mkdirSync(cwd, { recursive: true });
47
+ }
42
48
  // Redirect stderr to stdout so we capture everything, and ensure
43
49
  // no interactive prompts leak to the daemon terminal.
44
50
  // Also set CI=true and TERM=dumb so CLIs skip interactive prompts.
@@ -84,6 +90,9 @@ export function checkAio() {
84
90
  */
85
91
  export function runAio(args, cwd, requestId, connection) {
86
92
  return new Promise((resolve, reject) => {
93
+ if (!fs.existsSync(cwd)) {
94
+ fs.mkdirSync(cwd, { recursive: true });
95
+ }
87
96
  const child = spawn("aio", args, {
88
97
  cwd,
89
98
  shell: getUserShell(),
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import path from "node:path";
8
8
  import { getWorkspaceRoot, setWorkspaceRoot } from "./identity.js";
9
+ import { logCommand, logResult, logError } from "./logger.js";
9
10
  import * as fsCap from "./capabilities/fs.js";
10
11
  import * as gitCap from "./capabilities/git.js";
11
12
  import * as shellCap from "./capabilities/shell.js";
@@ -29,6 +30,21 @@ function validatePath(targetPath) {
29
30
  * Dispatch a command to the appropriate capability handler.
30
31
  */
31
32
  export async function dispatch(command, payload, connection) {
33
+ logCommand(command, payload);
34
+ const start = Date.now();
35
+ try {
36
+ const result = await dispatchInner(command, payload, connection);
37
+ const resultStr = typeof result === "string" ? result : JSON.stringify(result);
38
+ logResult(command, resultStr, Date.now() - start);
39
+ return result;
40
+ }
41
+ catch (err) {
42
+ const message = err instanceof Error ? err.message : String(err);
43
+ logError(command, message, Date.now() - start);
44
+ throw err;
45
+ }
46
+ }
47
+ async function dispatchInner(command, payload, connection) {
32
48
  switch (command) {
33
49
  // ─── Filesystem ─────────────────────────────────────
34
50
  case "fs:roots": {
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Daemon logger — writes timestamped entries to a log file in the project directory.
3
+ *
4
+ * Log file location: <workspaceRoot>/.daemon.log
5
+ * Also prints key events to the daemon terminal (stdout).
6
+ */
7
+ /** Log a command being dispatched. */
8
+ export declare function logCommand(command: string, payload: Record<string, unknown>): void;
9
+ /** Log a command result (success). */
10
+ export declare function logResult(command: string, result: string, durationMs: number): void;
11
+ /** Log a command error. */
12
+ export declare function logError(command: string, error: string, durationMs: number): void;
13
+ /** Log a general info message. */
14
+ export declare function logInfo(message: string): void;
package/dist/logger.js ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Daemon logger — writes timestamped entries to a log file in the project directory.
3
+ *
4
+ * Log file location: <workspaceRoot>/.daemon.log
5
+ * Also prints key events to the daemon terminal (stdout).
6
+ */
7
+ import fs from "node:fs";
8
+ import path from "node:path";
9
+ import { getWorkspaceRoot } from "./identity.js";
10
+ let logStream = null;
11
+ let currentLogPath = null;
12
+ function getLogPath() {
13
+ const root = getWorkspaceRoot();
14
+ if (!root)
15
+ return null;
16
+ return path.join(root, ".daemon.log");
17
+ }
18
+ function ensureStream() {
19
+ const logPath = getLogPath();
20
+ if (!logPath)
21
+ return null;
22
+ // Re-open if workspace changed
23
+ if (logPath !== currentLogPath) {
24
+ logStream?.end();
25
+ logStream = null;
26
+ currentLogPath = null;
27
+ }
28
+ if (!logStream) {
29
+ try {
30
+ fs.mkdirSync(path.dirname(logPath), { recursive: true });
31
+ logStream = fs.createWriteStream(logPath, { flags: "a" });
32
+ currentLogPath = logPath;
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ return logStream;
39
+ }
40
+ function ts() {
41
+ return new Date().toISOString();
42
+ }
43
+ /** Log a command being dispatched. */
44
+ export function logCommand(command, payload) {
45
+ const line = `[${ts()}] CMD ${command} ${JSON.stringify(payload)}`;
46
+ const stream = ensureStream();
47
+ stream?.write(line + "\n");
48
+ console.log(` ▶ ${command}`);
49
+ }
50
+ /** Log a command result (success). */
51
+ export function logResult(command, result, durationMs) {
52
+ const preview = result.length > 200 ? result.slice(0, 200) + "..." : result;
53
+ const line = `[${ts()}] OK ${command} (${durationMs}ms) ${preview}`;
54
+ const stream = ensureStream();
55
+ stream?.write(line + "\n");
56
+ console.log(` ✓ ${command} (${durationMs}ms)`);
57
+ }
58
+ /** Log a command error. */
59
+ export function logError(command, error, durationMs) {
60
+ const line = `[${ts()}] ERR ${command} (${durationMs}ms) ${error}`;
61
+ const stream = ensureStream();
62
+ stream?.write(line + "\n");
63
+ console.log(` ✗ ${command} (${durationMs}ms): ${error.slice(0, 100)}`);
64
+ }
65
+ /** Log a general info message. */
66
+ export function logInfo(message) {
67
+ const line = `[${ts()}] INFO ${message}`;
68
+ const stream = ensureStream();
69
+ stream?.write(line + "\n");
70
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aem-ext-daemon",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Local daemon for AEM Extension Builder — connects your machine to the cloud UI",
5
5
  "type": "module",
6
6
  "bin": {