Skip to content

Commit a04147a

Browse files
committed
chore: Remove unrelated code, clean up all the things
1 parent 598cbf1 commit a04147a

File tree

5 files changed

+170
-10
lines changed

5 files changed

+170
-10
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## [3.1.3]
9+
10+
### Added
11+
- Added `debug_mode` configuration option to handle Node.js stdout/stderr messages
12+
- Implemented proper `handle_info/2` callback to handle messages from Node.js processes
13+
- Added safeguards to reset_terminal to prevent errors during termination with invalid ports
14+
15+
### Fixed
16+
- Fixed "unexpected message in handle_info/2" errors when Node.js emits debug messages
17+
- Fixed potential crashes during termination when a port becomes invalid
18+
19+
### Contributors
20+
- @francois-codes for the initial implementation
21+
- Revelry team for refinements
22+
823
## [3.1.2]
924

1025
### Changed

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,22 @@ directory containing your JavaScript modules.
3636
supervisor(NodeJS, [[path: "/node_app_root", pool_size: 4]])
3737
```
3838

39+
### Debug Mode
40+
41+
When working with Node.js applications, you may encounter debug messages or warnings from the Node.js runtime, especially when using inspector or debugging tools. To properly handle these messages:
42+
43+
```elixir
44+
# In your config/dev.exs or other appropriate config file
45+
config :nodejs, debug_mode: true
46+
```
47+
48+
When `debug_mode` is enabled:
49+
- Node.js stdout/stderr messages will be logged at the info level
50+
- Messages like "Debugger listening on..." will not cause errors
51+
- All Node.js processes will log their output through Elixir's Logger
52+
53+
This is particularly useful during development or when debugging Node.js integration issues.
54+
3955
### Calling JavaScript module functions with `NodeJS.call(module, args \\ [])`.
4056

4157
If the module exports a function directly, like this:
@@ -111,4 +127,4 @@ module.exports = async function echo(x, delay = 1000) {
111127
}
112128
```
113129

114-
https://github.com/revelrylabs/elixir-nodejs/blob/master/test/js/slow-async-echo.js
130+
https://github.com/revelrylabs/elixir-nodejs/blob/master/test/js/slow-async-echo.js

lib/nodejs/worker.ex

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,21 +124,28 @@ defmodule NodeJS.Worker do
124124
end
125125
end
126126

127-
defp env do
128-
Mix.env()
129-
rescue
130-
_ -> :release
127+
# Determines if debug mode is enabled via application configuration
128+
defp debug_mode? do
129+
Application.get_env(:nodejs, :debug_mode, false)
131130
end
132131

133-
def handle_info({_pid, data}, state) do
134-
with :dev <- env(),
135-
{_, {:eol, msg}} <- data do
132+
# Handles any messages from the Node.js process
133+
# When debug_mode is enabled, these messages (like Node.js debug info)
134+
# will be logged at info level
135+
@doc false
136+
def handle_info({_pid, {:data, {_flag, msg}} = data}, state) do
137+
if debug_mode?() do
136138
Logger.info("NodeJS: #{msg}")
137139
end
138140

139141
{:noreply, state}
140142
end
141143

144+
# Catch-all handler for other messages
145+
def handle_info(_message, state) do
146+
{:noreply, state}
147+
end
148+
142149
defp decode(data) do
143150
data
144151
|> to_string()
@@ -149,9 +156,16 @@ defmodule NodeJS.Worker do
149156
end
150157
end
151158

159+
# Safely resets the terminal, handling potential errors if
160+
# the port is already closed or invalid
152161
defp reset_terminal(port) do
153-
Port.command(port, "\x1b[0m\x1b[?7h\x1b[?25h\x1b[H\x1b[2J")
154-
Port.command(port, "\x1b[!p\x1b[?47l")
162+
try do
163+
Port.command(port, "\x1b[0m\x1b[?7h\x1b[?25h\x1b[H\x1b[2J")
164+
Port.command(port, "\x1b[!p\x1b[?47l")
165+
rescue
166+
_ ->
167+
Logger.debug("NodeJS: Could not reset terminal - port may be closed")
168+
end
155169
end
156170

157171
@doc false

test/js/debug_test/debug_logger.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// This file outputs debugging information to stdout
2+
console.log("Debug message: Module loading");
3+
console.debug("Debug message: Initializing module");
4+
5+
module.exports = function testFunction(input) {
6+
console.log(`Debug message: Function called with input: ${input}`);
7+
console.debug("Debug message: Processing input");
8+
9+
return `Processed: ${input}`;
10+
};

test/nodejs_debug_mode_test.exs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
defmodule NodeJS.DebugModeTest do
2+
use ExUnit.Case
3+
import ExUnit.CaptureLog
4+
5+
describe "debug_mode functionality" do
6+
test "logs Node.js stdout messages when debug_mode is enabled" do
7+
defmodule TestDebugHandler do
8+
use GenServer
9+
require Logger
10+
11+
def start_link do
12+
GenServer.start_link(__MODULE__, nil)
13+
end
14+
15+
def init(_) do
16+
{:ok, nil}
17+
end
18+
19+
def debug_mode? do
20+
Application.get_env(:nodejs, :debug_mode, false)
21+
end
22+
23+
# The implementation from worker.ex
24+
def handle_info({_pid, {:data, {_flag, msg}} = _data}, state) do
25+
if debug_mode?() do
26+
Logger.info("NodeJS: #{msg}")
27+
end
28+
29+
{:noreply, state}
30+
end
31+
end
32+
33+
# Start the test process
34+
{:ok, pid} = TestDebugHandler.start_link()
35+
36+
# Test with debug_mode disabled (default)
37+
log_without_debug =
38+
capture_log(fn ->
39+
# Simulate debugger message from Node.js
40+
send(pid, {self(), {:data, {:eol, "Debugger listening on ws://127.0.0.1:9229/abc123"}}})
41+
# Wait for any potential logging
42+
Process.sleep(50)
43+
end)
44+
45+
# Verify no logging occurred
46+
refute log_without_debug =~ "NodeJS: Debugger listening"
47+
48+
# Enable debug_mode
49+
Application.put_env(:nodejs, :debug_mode, true)
50+
51+
# Test with debug_mode enabled
52+
log_with_debug =
53+
capture_log(fn ->
54+
# Simulate debugger message from Node.js
55+
send(pid, {self(), {:data, {:eol, "Debugger listening on ws://127.0.0.1:9229/abc123"}}})
56+
# Wait for any potential logging
57+
Process.sleep(50)
58+
end)
59+
60+
# Clean up
61+
Application.delete_env(:nodejs, :debug_mode)
62+
63+
# Verify logging occurred
64+
assert log_with_debug =~ "NodeJS: Debugger listening"
65+
end
66+
end
67+
68+
describe "port safety" do
69+
test "reset_terminal handles invalid ports gracefully" do
70+
defmodule TestPortHandler do
71+
use GenServer
72+
require Logger
73+
74+
def start_link do
75+
GenServer.start_link(__MODULE__, nil)
76+
end
77+
78+
def init(_) do
79+
{:ok, nil}
80+
end
81+
82+
# The implementation from worker.ex
83+
def reset_terminal(port) do
84+
try do
85+
Port.command(port, "\x1b[0m\x1b[?7h\x1b[?25h\x1b[H\x1b[2J")
86+
Port.command(port, "\x1b[!p\x1b[?47l")
87+
rescue
88+
_ ->
89+
Logger.debug("NodeJS: Could not reset terminal - port may be closed")
90+
end
91+
end
92+
end
93+
94+
log =
95+
capture_log(fn ->
96+
# Try to reset an invalid port
97+
TestPortHandler.reset_terminal(:invalid_port)
98+
Process.sleep(50)
99+
end)
100+
101+
# Verify proper error handling
102+
assert log =~ "NodeJS: Could not reset terminal"
103+
end
104+
end
105+
end

0 commit comments

Comments
 (0)