node-thermal-printer-js 1.2.0 → 1.2.1

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/app.js CHANGED
@@ -22,25 +22,30 @@ let bleServerPort = null;
22
22
 
23
23
  /**
24
24
  * Find an available Python 3.9+ executable on the system.
25
- * Tries: py, python3, python (platform-aware)
26
- * @returns {string|null} Command name if found, null otherwise
25
+ * Tries local venv first, then versioned launcher probes on Windows, then system Python.
26
+ * @returns {{ cmd: string, args: string[] }|null} Command descriptor if found, null otherwise
27
27
  */
28
28
  const findPythonCmd = () => {
29
29
  const candidates = getPythonLaunchCandidates();
30
30
 
31
- for (const cmd of candidates) {
31
+ for (const candidate of candidates) {
32
32
  try {
33
- const result = spawnSync(cmd, ["--version"], {
33
+ const result = spawnSync(candidate.cmd, [...candidate.args, "--version"], {
34
34
  encoding: "utf8",
35
35
  timeout: 2000,
36
36
  shell: false,
37
37
  });
38
38
 
39
39
  const output = `${result.stdout || ""}${result.stderr || ""}`.trim();
40
- const match = output.match(/Python (\d+\.\d+)/);
41
- if (match && parseFloat(match[1]) >= 3.9) {
42
- console.log(`[BLE] ✓ Detected Python: ${cmd} (${output})`);
43
- return cmd;
40
+ const match = output.match(/Python (\d+)\.(\d+)/);
41
+ if (match) {
42
+ const major = parseInt(match[1], 10);
43
+ const minor = parseInt(match[2], 10);
44
+ // Check if Python 3.9+
45
+ if (major > 3 || (major === 3 && minor >= 9)) {
46
+ console.log(`[BLE] ✓ Detected Python: ${candidate.cmd} ${candidate.args.join(" ")} (${output})`);
47
+ return candidate;
48
+ }
44
49
  }
45
50
  } catch {
46
51
  // Continue to next candidate
@@ -52,20 +57,30 @@ const findPythonCmd = () => {
52
57
  const getPythonLaunchCandidates = () => {
53
58
  const localVenvCandidates = process.platform === "win32"
54
59
  ? [
55
- path.join(scriptDir, ".venv", "Scripts", "python.exe"),
56
- path.join(scriptDir, ".venv", "Scripts", "python"),
60
+ { cmd: path.join(scriptDir, ".venv", "Scripts", "python.exe"), args: [] },
61
+ { cmd: path.join(scriptDir, ".venv", "Scripts", "python"), args: [] },
57
62
  ]
58
63
  : [
59
- path.join(scriptDir, ".venv", "bin", "python"),
60
- path.join(scriptDir, ".venv", "bin", "python3"),
64
+ { cmd: path.join(scriptDir, ".venv", "bin", "python"), args: [] },
65
+ { cmd: path.join(scriptDir, ".venv", "bin", "python3"), args: [] },
61
66
  ];
62
67
 
63
68
  const systemCandidates = process.platform === "win32"
64
- ? ["py", "python3", "python"]
65
- : ["python3", "python", "py"];
69
+ ? [
70
+ { cmd: "py", args: ["-3.11"] },
71
+ { cmd: "py", args: ["-3"] },
72
+ { cmd: "py", args: [] },
73
+ { cmd: "python3", args: [] },
74
+ { cmd: "python", args: [] },
75
+ ]
76
+ : [
77
+ { cmd: "python3", args: [] },
78
+ { cmd: "python", args: [] },
79
+ { cmd: "py", args: [] },
80
+ ];
66
81
 
67
82
  return [
68
- ...localVenvCandidates.filter((candidate) => existsSync(candidate)),
83
+ ...localVenvCandidates.filter((candidate) => existsSync(candidate.cmd)),
69
84
  ...systemCandidates,
70
85
  ];
71
86
  };
@@ -327,7 +342,7 @@ const startBleServer = async (options = {}) => {
327
342
  const candidates = envCmd
328
343
  ? [{ cmd: envCmd, cmdArgs: ["-u"] }] // -u for unbuffered output
329
344
  : [
330
- ...(detectedPythonCmd ? [{ cmd: detectedPythonCmd, cmdArgs: ["-u"] }] : []),
345
+ ...(detectedPythonCmd ? [{ cmd: detectedPythonCmd.cmd, cmdArgs: [...detectedPythonCmd.args, "-u"] }] : []),
331
346
  ...getPythonLaunchCandidates().map((cmd) => ({ cmd, cmdArgs: ["-u"] })),
332
347
  ];
333
348
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-thermal-printer-js",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "ESC/POS printer helper for PSF588 Bluetooth and COM printing.",
5
5
  "main": "app.js",
6
6
  "exports": {
@@ -15,35 +15,67 @@ const findPythonCmd = () => {
15
15
  const localVenvCandidates =
16
16
  process.platform === "win32"
17
17
  ? [
18
- path.join(scriptDir, ".venv", "Scripts", "python.exe"),
19
- path.join(scriptDir, ".venv", "Scripts", "python"),
18
+ {
19
+ cmd: path.join(scriptDir, ".venv", "Scripts", "python.exe"),
20
+ args: [],
21
+ },
22
+ { cmd: path.join(scriptDir, ".venv", "Scripts", "python"), args: [] },
20
23
  ]
21
24
  : [
22
- path.join(scriptDir, ".venv", "bin", "python"),
23
- path.join(scriptDir, ".venv", "bin", "python3"),
25
+ { cmd: path.join(scriptDir, ".venv", "bin", "python"), args: [] },
26
+ { cmd: path.join(scriptDir, ".venv", "bin", "python3"), args: [] },
27
+ ];
28
+
29
+ const systemCandidates =
30
+ process.platform === "win32"
31
+ ? [
32
+ { cmd: "py", args: ["-3.11"] },
33
+ { cmd: "py", args: ["-3"] },
34
+ { cmd: "py", args: [] },
35
+ { cmd: "python3", args: [] },
36
+ { cmd: "python", args: [] },
37
+ ]
38
+ : [
39
+ { cmd: "python3", args: [] },
40
+ { cmd: "python", args: [] },
41
+ { cmd: "py", args: [] },
24
42
  ];
25
43
 
26
44
  const candidates = [
27
- ...localVenvCandidates.filter((candidate) => existsSync(candidate)),
28
- ...(process.platform === "win32"
29
- ? ["py", "python3", "python"]
30
- : ["python3", "python", "py"]),
45
+ ...localVenvCandidates.filter((candidate) => existsSync(candidate.cmd)),
46
+ ...systemCandidates,
31
47
  ];
32
48
 
33
- for (const cmd of candidates) {
49
+ for (const candidate of candidates) {
34
50
  try {
35
- const result = spawnSync(cmd, ["--version"], {
36
- encoding: "utf8",
37
- stdio: "pipe",
38
- timeout: 2000,
39
- shell: false,
40
- });
51
+ const result = spawnSync(
52
+ candidate.cmd,
53
+ [...candidate.args, "--version"],
54
+ {
55
+ encoding: "utf8",
56
+ stdio: "pipe",
57
+ timeout: 2000,
58
+ shell: false,
59
+ },
60
+ );
61
+
62
+ // Skip if command failed or timed out
63
+ if (result.status !== 0 || result.error) {
64
+ continue;
65
+ }
66
+
41
67
  const version = `${result.stdout || ""}${result.stderr || ""}`.trim();
42
68
  // Check if Python 3.9+
43
- const match = version.match(/Python (\d+\.\d+)/);
44
- if (match && parseFloat(match[1]) >= 3.9) {
45
- console.log(`✓ Found ${cmd} (${version})`);
46
- return cmd;
69
+ const match = version.match(/Python (\d+)\.(\d+)/);
70
+ if (match) {
71
+ const major = parseInt(match[1], 10);
72
+ const minor = parseInt(match[2], 10);
73
+ if (major > 3 || (major === 3 && minor >= 9)) {
74
+ console.log(
75
+ `✓ Found ${candidate.cmd} ${candidate.args.join(" ")} (${version})`,
76
+ );
77
+ return candidate;
78
+ }
47
79
  }
48
80
  } catch {
49
81
  // Continue to next candidate
@@ -56,12 +88,16 @@ const findPythonCmd = () => {
56
88
  const installBleak = (pythonCmd) => {
57
89
  console.log(`\n📦 Installing bleak Python package...`);
58
90
  try {
59
- const result = spawnSync(pythonCmd, ["-m", "pip", "install", "bleak"], {
60
- encoding: "utf8",
61
- stdio: "inherit",
62
- timeout: 120000,
63
- shell: false,
64
- });
91
+ const result = spawnSync(
92
+ pythonCmd.cmd,
93
+ [...pythonCmd.args, "-m", "pip", "install", "bleak"],
94
+ {
95
+ encoding: "utf8",
96
+ stdio: "inherit",
97
+ timeout: 120000,
98
+ shell: false,
99
+ },
100
+ );
65
101
  if (result.status !== 0) {
66
102
  throw new Error(`pip exited with code ${result.status ?? "unknown"}`);
67
103
  }
@@ -94,11 +130,15 @@ const main = async () => {
94
130
  // Step 2: Install bleak
95
131
  console.log("2️⃣ Checking bleak dependency...");
96
132
  try {
97
- const importCheck = spawnSync(pythonCmd, ["-c", "import bleak"], {
98
- stdio: "pipe",
99
- timeout: 2000,
100
- shell: false,
101
- });
133
+ const importCheck = spawnSync(
134
+ pythonCmd.cmd,
135
+ [...pythonCmd.args, "-c", "import bleak"],
136
+ {
137
+ stdio: "pipe",
138
+ timeout: 2000,
139
+ shell: false,
140
+ },
141
+ );
102
142
  if (importCheck.status !== 0) {
103
143
  throw new Error("bleak import check failed");
104
144
  }
@@ -107,7 +147,9 @@ const main = async () => {
107
147
  const installed = installBleak(pythonCmd);
108
148
  if (!installed) {
109
149
  console.error("\n⚠ Manual installation required:");
110
- console.error(` ${pythonCmd} -m pip install bleak\n`);
150
+ console.error(
151
+ ` ${pythonCmd.cmd} ${pythonCmd.args.join(" ")} -m pip install bleak\n`,
152
+ );
111
153
  }
112
154
  }
113
155