java-caller 4.3.3 → 4.4.0

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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Version](https://img.shields.io/npm/v/java-caller.svg)](https://www.npmjs.com/package/java-caller)
5
5
  [![Downloads/week](https://img.shields.io/npm/dw/java-caller.svg)](https://npmjs.org/package/java-caller)
6
6
  [![Downloads/total](https://img.shields.io/npm/dt/java-caller.svg)](https://npmjs.org/package/java-caller)<!-- gh-dependents-info-used-by-start -->
7
- [![Generated by github-dependents-info](https://img.shields.io/static/v1?label=Used%20by&message=159&color=informational&logo=slickpic)](https://github.com/nvuillam/node-java-caller/blob/main/docs/github-dependents-info.md)<!-- gh-dependents-info-used-by-end -->
7
+ [![Generated by github-dependents-info](https://img.shields.io/static/v1?label=Used%20by&message=162&color=informational&logo=slickpic)](https://github.com/nvuillam/node-java-caller/blob/main/docs/github-dependents-info.md)<!-- gh-dependents-info-used-by-end -->
8
8
  [![Mega-Linter](https://github.com/nvuillam/node-java-caller/workflows/Mega-Linter/badge.svg)](https://github.com/nvuillam/mega-linter#readme)
9
9
  [![codecov](https://codecov.io/gh/nvuillam/node-java-caller/branch/master/graph/badge.svg)](https://codecov.io/gh/nvuillam/node-java-caller)
10
10
  [![GitHub contributors](https://img.shields.io/github/contributors/nvuillam/node-java-caller.svg)](https://gitHub.com/nvuillam/node-java-caller/graphs/contributors/)
@@ -65,13 +65,16 @@ Example: `["-Xms256m", "--someflagwithvalue myVal", "-c"]`
65
65
 
66
66
  | Parameter | Description | Default | Example |
67
67
  |-----------|-------------|---------|---------|
68
- | [detached](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | If set to true, node will node wait for the java command to be completed.<br/>In that case, `childJavaProcess` property will be returned, but `stdout` and `stderr` may be empty, except if an error is triggered at command execution | `false` | `true`
68
+ | [detached](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | If set to true, node will not wait for the java command to be completed.<br/>In that case, `childJavaProcess` property will be returned, but `stdout` and `stderr` may be empty, except if an error is triggered at command execution | `false` | `true`
69
69
  | [stdoutEncoding](https://nodejs.org/api/stream.html#readablesetencodingencoding) | Adds control on spawn process stdout | `utf8` | `ucs2` |
70
70
  | waitForErrorMs | If detached is true, number of milliseconds to wait to detect an error before exiting JavaCaller run | `500` | `2000` |
71
71
  | [cwd](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | You can override cwd of spawn called by JavaCaller runner | `process.cwd()` | `some/other/cwd/folder` |
72
72
  | javaArgs | List of arguments for JVM only, not the JAR or the class | `[]` | `['--add-opens=java.base/java.lang=ALL-UNNAMED']` |
73
73
  | [windowsVerbatimArguments](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | No quoting or escaping of arguments is done on Windows. Ignored on Unix. This is set to true automatically when shell is specified and is CMD. | `true` | `false` |
74
74
  | [windowless](https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html#:~:text=main()%20method.-,javaw,information%20if%20a%20launch%20fails.) | If windowless is true, JavaCaller calls javaw instead of java to not create any windows, useful when using detached on Windows. Ignored on Unix. | false | true
75
+ | [windowsHide](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | On Windows, hide the subprocess console window that would normally be created. Set to `false` if you need Java UI dialogs to be visible (e.g., print dialogs). Ignored on Unix. | `true` | `false`
76
+ | [timeout](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | In milliseconds the maximum amount of time the process is allowed to run. | `undefined` | `1000`
77
+ | [killSignal](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | The signal value to be used when the spawned process will be killed by timeout or abort signal. | `SIGTERM` | `SIGINT`
75
78
 
76
79
  ## Examples
77
80
 
@@ -147,6 +150,23 @@ const java = new JavaCaller({
147
150
  const { status, stdout, stderr } = await java.run(['--sleep'], { windowless: true });
148
151
  ```
149
152
 
153
+ Call java process with visible windows (e.g., for print dialogs)
154
+
155
+ ```javascript
156
+ const java = new JavaCaller({
157
+ classPath: 'test/java/dist',
158
+ mainClass: 'com.nvuillam.javacaller.JavaCallerTester'
159
+ });
160
+ // Set windowsHide to false to allow Java UI dialogs to be visible
161
+ const { status, stdout, stderr } = await java.run([], { windowsHide: false });
162
+ ```
163
+
164
+ When using CLI mode with `--no-windows-hide` flag:
165
+
166
+ ```bash
167
+ node index.js --no-windows-hide
168
+ ```
169
+
150
170
  You can see **more examples in** [**test methods**](https://github.com/nvuillam/node-java-caller/blob/master/test/java-caller.test.js)
151
171
 
152
172
  ## TROUBLESHOOTING
package/lib/cli.js CHANGED
@@ -26,7 +26,18 @@ class JavaCallerCli {
26
26
  const java = new JavaCaller(this.javaCallerOptions);
27
27
  const args = [...process.argv];
28
28
  args.splice(0, 2);
29
- const { status } = await java.run(args);
29
+
30
+ // Parse --no-windows-hide flag (remove all occurrences)
31
+ const runOptions = {};
32
+ const filteredArgs = args.filter(arg => {
33
+ if (arg === '--no-windows-hide') {
34
+ runOptions.windowsHide = false;
35
+ return false; // Remove from args
36
+ }
37
+ return true; // Keep in args
38
+ });
39
+
40
+ const { status } = await java.run(filteredArgs, runOptions);
30
41
  process.exitCode = status;
31
42
  }
32
43
  }
package/lib/index.d.ts CHANGED
@@ -117,6 +117,27 @@ export interface JavaCallerRunOptions {
117
117
  * @default false
118
118
  */
119
119
  windowless?: boolean;
120
+
121
+ /**
122
+ * The number of milliseconds to wait before the Java process will time out. When this occurs,
123
+ * killSignal will ben
124
+ * @default undefined
125
+ */
126
+ timeout?: number;
127
+
128
+ /**
129
+ * If windowless is true, JavaCaller calls javaw instead of java to not create any windows,
130
+ * useful when using detached on Windows. Ignored on Unix.
131
+ * @default "SIGTERM"
132
+ */
133
+ killSignal?: number | NodeJS.Signals;
134
+
135
+ /**
136
+ * On Windows, hide the subprocess console window that would normally be created.
137
+ * This option is ignored on Unix.
138
+ * @default true
139
+ */
140
+ windowsHide?: boolean;
120
141
  }
121
142
 
122
143
  /**
@@ -69,12 +69,14 @@ class JavaCaller {
69
69
  * Runs java command of a JavaCaller instance
70
70
  * @param {string[]} [userArguments] - Java command line arguments
71
71
  * @param {object} [runOptions] - Run options
72
- * @param {boolean} [runOptions.detached = false] - If set to true, node will node wait for the java command to be completed. In that case, childJavaProcess property will be returned, but stdout and stderr may be empty
72
+ * @param {boolean} [runOptions.detached = false] - If set to true, node will not wait for the java command to be completed. In that case, childJavaProcess property will be returned, but stdout and stderr may be empty
73
73
  * @param {string} [runOptions.stdoutEncoding = 'utf8'] - Adds control on spawn process stdout
74
74
  * @param {number} [runOptions.waitForErrorMs = 500] - If detached is true, number of milliseconds to wait to detect an error before exiting JavaCaller run
75
75
  * @param {string} [runOptions.cwd = .] - You can override cwd of spawn called by JavaCaller runner
76
76
  * @param {string} [runOptions.javaArgs = []] - You can override cwd of spawn called by JavaCaller runner
77
77
  * @param {string} [runOptions.windowsVerbatimArguments = true] - No quoting or escaping of arguments is done on Windows. Ignored on Unix. This is set to true automatically when shell is specified and is CMD.
78
+ * @param {number} [runOptions.timeout] - In milliseconds the maximum amount of time the process is allowed to run
79
+ * @param {NodeJS.Signals | number} [runOptions.killSignal = "SIGTERM"] - The signal value to be used when the spawned process will be killed by timeout or abort signal.
78
80
  * @return {Promise<{status:number, stdout:string, stderr:string, childJavaProcess:ChildProcess}>} - Command result (status, stdout, stderr, childJavaProcess)
79
81
  */
80
82
  async run(userArguments, runOptions = {}) {
@@ -84,6 +86,7 @@ class JavaCaller {
84
86
  runOptions.stdoutEncoding = typeof runOptions.stdoutEncoding === "undefined" ? "utf8" : runOptions.stdoutEncoding;
85
87
  runOptions.windowsVerbatimArguments = typeof runOptions.windowsVerbatimArguments === "undefined" ? true : runOptions.windowsVerbatimArguments;
86
88
  runOptions.windowless = typeof runOptions.windowless === "undefined" ? false : os.platform() !== "win32" ? false : runOptions.windowless;
89
+ runOptions.killSignal = typeof runOptions.killSignal === "undefined" ? "SIGTERM" : runOptions.killSignal;
87
90
  this.commandJavaArgs = (runOptions.javaArgs || []).concat(this.additionalJavaArgs);
88
91
 
89
92
  let javaExe = runOptions.windowless ? this.javaExecutableWindowless : this.javaExecutable;
@@ -97,10 +100,13 @@ class JavaCaller {
97
100
 
98
101
  const javaExeToUse = this.javaExecutableFromNodeJavaCaller ?? javaExe;
99
102
  const classPathStr = this.buildClasspathStr();
100
- const javaArgs = this.buildArguments(classPathStr, (userArguments || []).concat(this.commandJavaArgs));
103
+ const javaArgs = this.buildArguments(classPathStr, (userArguments || []).concat(this.commandJavaArgs), runOptions.windowsVerbatimArguments);
101
104
  let stdout = "";
102
105
  let stderr = "";
103
106
  let child;
107
+ let timeoutId;
108
+ let killedByTimeout = false;
109
+
104
110
  const prom = new Promise((resolve) => {
105
111
  // Spawn java command line
106
112
  debug(`Java command: ${javaExeToUse} ${javaArgs.join(" ")}`);
@@ -109,7 +115,7 @@ class JavaCaller {
109
115
  cwd: javaExeToUse === "java" || javaExeToUse === "javaw" ? runOptions.cwd : undefined,
110
116
  env: Object.assign({}, process.env),
111
117
  stdio: this.output === "console" ? "inherit" : runOptions.detached ? "ignore" : "pipe",
112
- windowsHide: true,
118
+ windowsHide: runOptions.windowsHide !== undefined ? runOptions.windowsHide : true,
113
119
  windowsVerbatimArguments: runOptions.windowsVerbatimArguments,
114
120
  };
115
121
  if (javaExeToUse.includes(" ")) {
@@ -117,6 +123,19 @@ class JavaCaller {
117
123
  }
118
124
  child = spawn(javaExeToUse, javaArgs, spawnOptions);
119
125
 
126
+ if (runOptions.timeout) {
127
+ timeoutId = setTimeout(() => {
128
+ if (!child.killed) {
129
+ try {
130
+ child.kill(runOptions.killSignal);
131
+ killedByTimeout = true;
132
+ } catch (err) {
133
+ stderr += `Failed to kill process after ${runOptions.timeout}ms: ${err.message}`;
134
+ }
135
+ }
136
+ }, runOptions.timeout);
137
+ }
138
+
120
139
  // Gather stdout and stderr if they must be returned
121
140
  if (spawnOptions.stdio === "pipe") {
122
141
  child.stdout.setEncoding(`${runOptions.stdoutEncoding}`);
@@ -132,12 +151,28 @@ class JavaCaller {
132
151
  child.on("error", (data) => {
133
152
  this.status = 666;
134
153
  stderr += "Java spawn error: " + data;
154
+
155
+ if (timeoutId) {
156
+ clearTimeout(timeoutId);
157
+ }
158
+
135
159
  resolve();
136
160
  });
137
161
 
138
162
  // Catch status code
139
163
  child.on("close", (code) => {
140
- this.status = code;
164
+ if (timeoutId) {
165
+ clearTimeout(timeoutId);
166
+ }
167
+
168
+ if (killedByTimeout) {
169
+ // Process was terminated because of the timeout
170
+ this.status = 666;
171
+ stderr += `Process timed out with ${runOptions.killSignal} after ${runOptions.timeout}ms.`;
172
+ } else {
173
+ this.status = code;
174
+ }
175
+
141
176
  resolve();
142
177
  });
143
178
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "java-caller",
3
- "version": "4.3.3",
3
+ "version": "4.4.0",
4
4
  "description": "Library to easily call java from node sources. Automatically installs java if not present",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -9,7 +9,7 @@
9
9
  ],
10
10
  "scripts": {
11
11
  "lint:fix": "eslint **/*.js --fix && prettier --write \"./lib/**/*.{js,jsx,json}\" --tab-width 4 --print-width 150",
12
- "java:compile": "javac -d test/java/dist -source 8 -target 1.8 test/java/src/com/nvuillam/javacaller/JavaCallerTester.java",
12
+ "java:compile": "javac -d test/java/dist --release 8 test/java/src/com/nvuillam/javacaller/JavaCallerTester.java",
13
13
  "java:jar": "cd test/java/dist && jar -cvfm ./../jar/JavaCallerTester.jar ./../jar/manifest/Manifest.txt com/nvuillam/javacaller/*.class && jar -cvfm ./../jar/JavaCallerTesterRunnable.jar ./../jar/manifest-runnable/Manifest.txt com/nvuillam/javacaller/*.class",
14
14
  "test": "mocha \"test/**/*.test.js\"",
15
15
  "test:coverage": "nyc npm run test",