devtunnel-cli 3.1.2 → 3.1.4

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,140 +1,160 @@
1
- import { spawn } from "child_process";
2
- import { platform } from "os";
3
- import { writeFileSync, readFileSync, unlinkSync, existsSync } from "fs";
4
- import { join } from "path";
5
- import { tmpdir } from "os";
6
-
7
- // Cross-platform native folder picker
8
- export async function selectFolder() {
9
- const os = platform();
10
- const tempFile = join(tmpdir(), `folder-picker-${Date.now()}.txt`);
11
-
12
- try {
13
- if (os === "win32") {
14
- // Windows - Use MODERN OpenFileDialog (like website file uploads)
15
- const script = `
16
- Add-Type -AssemblyName System.Windows.Forms
17
- [System.Windows.Forms.Application]::EnableVisualStyles()
18
-
19
- $dialog = New-Object System.Windows.Forms.OpenFileDialog
20
- $dialog.Title = "Select your project folder"
21
- $dialog.Filter = "All files (*.*)|*.*"
22
- $dialog.CheckFileExists = $false
23
- $dialog.CheckPathExists = $true
24
- $dialog.ValidateNames = $false
25
- $dialog.FileName = "Folder Selection"
26
- $dialog.Multiselect = $false
27
- $dialog.InitialDirectory = [Environment]::GetFolderPath("UserProfile")
28
-
29
- $result = $dialog.ShowDialog()
30
- if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
31
- $folderPath = Split-Path -Parent $dialog.FileName
32
- if (-not $folderPath) {
33
- $folderPath = $dialog.FileName
34
- }
35
- $folderPath | Out-File -FilePath "${tempFile.replace(/\\/g, '\\\\')}" -Encoding UTF8 -NoNewline
36
- }
37
- `;
38
-
39
- await runPowerShell(script);
40
-
41
- } else if (os === "darwin") {
42
- // macOS - Use osascript
43
- const script = `
44
- set folderPath to choose folder with prompt "Select your project folder"
45
- set posixPath to POSIX path of folderPath
46
- do shell script "echo " & quoted form of posixPath & " > '${tempFile}'"
47
- `;
48
-
49
- await runCommand("osascript", ["-e", script]);
50
-
51
- } else {
52
- // Linux - Try zenity first, then kdialog
53
- try {
54
- await runCommand("zenity", [
55
- "--file-selection",
56
- "--directory",
57
- "--title=Select your project folder"
58
- ], tempFile);
59
- } catch {
60
- await runCommand("kdialog", [
61
- "--getexistingdirectory",
62
- process.env.HOME || "/",
63
- "--title", "Select your project folder"
64
- ], tempFile);
65
- }
66
- }
67
-
68
- // Read the selected folder
69
- if (existsSync(tempFile)) {
70
- const folderPath = readFileSync(tempFile, "utf8").trim();
71
- unlinkSync(tempFile);
72
- return folderPath;
73
- }
74
-
75
- return null;
76
-
77
- } catch (error) {
78
- console.error("Folder picker error:", error.message);
79
- return null;
80
- }
81
- }
82
-
83
- // Run PowerShell command
84
- function runPowerShell(script) {
85
- return new Promise((resolve, reject) => {
86
- const proc = spawn("powershell", [
87
- "-NoProfile",
88
- "-NonInteractive",
89
- "-ExecutionPolicy", "Bypass",
90
- "-Command", script
91
- ], {
92
- stdio: ["ignore", "pipe", "pipe"],
93
- shell: false
94
- });
95
-
96
- let stderr = "";
97
- proc.stderr?.on("data", (data) => stderr += data.toString());
98
-
99
- proc.on("close", (code) => {
100
- if (code === 0) {
101
- resolve();
102
- } else {
103
- reject(new Error(stderr || `PowerShell exited with code ${code}`));
104
- }
105
- });
106
-
107
- proc.on("error", reject);
108
- });
109
- }
110
-
111
- // Run generic command
112
- function runCommand(command, args, outputFile) {
113
- return new Promise((resolve, reject) => {
114
- const proc = spawn(command, args, {
115
- stdio: outputFile ? ["ignore", "pipe", "pipe"] : "pipe",
116
- shell: true
117
- });
118
-
119
- let stdout = "";
120
-
121
- if (outputFile) {
122
- proc.stdout?.on("data", (data) => {
123
- stdout += data.toString();
124
- });
125
- }
126
-
127
- proc.on("close", (code) => {
128
- if (code === 0) {
129
- if (outputFile && stdout) {
130
- writeFileSync(outputFile, stdout.trim());
131
- }
132
- resolve();
133
- } else {
134
- reject(new Error(`Command failed with code ${code}`));
135
- }
136
- });
137
-
138
- proc.on("error", reject);
139
- });
140
- }
1
+ import { spawn } from "child_process";
2
+ import { platform } from "os";
3
+ import { writeFileSync, readFileSync, unlinkSync, existsSync } from "fs";
4
+ import { join } from "path";
5
+ import { tmpdir } from "os";
6
+
7
+ // Cross-platform native folder picker
8
+ export async function selectFolder() {
9
+ const os = platform();
10
+ const tempFile = join(tmpdir(), `folder-picker-${Date.now()}.txt`);
11
+
12
+ try {
13
+ if (os === "win32") {
14
+ // Windows - Use MODERN OpenFileDialog (like website file uploads)
15
+ const script = `
16
+ Add-Type -AssemblyName System.Windows.Forms
17
+ [System.Windows.Forms.Application]::EnableVisualStyles()
18
+
19
+ $dialog = New-Object System.Windows.Forms.OpenFileDialog
20
+ $dialog.Title = "Select your project folder"
21
+ $dialog.Filter = "All files (*.*)|*.*"
22
+ $dialog.CheckFileExists = $false
23
+ $dialog.CheckPathExists = $true
24
+ $dialog.ValidateNames = $false
25
+ $dialog.FileName = "Folder Selection"
26
+ $dialog.Multiselect = $false
27
+ $dialog.InitialDirectory = [Environment]::GetFolderPath("UserProfile")
28
+
29
+ $result = $dialog.ShowDialog()
30
+ if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
31
+ $folderPath = Split-Path -Parent $dialog.FileName
32
+ if (-not $folderPath) {
33
+ $folderPath = $dialog.FileName
34
+ }
35
+ $folderPath | Out-File -FilePath "${tempFile.replace(/\\/g, '\\\\')}" -Encoding UTF8 -NoNewline
36
+ }
37
+ `;
38
+
39
+ await runPowerShell(script);
40
+
41
+ } else if (os === "darwin") {
42
+ // macOS - Use osascript
43
+ const script = `
44
+ set folderPath to choose folder with prompt "Select your project folder"
45
+ set posixPath to POSIX path of folderPath
46
+ do shell script "echo " & quoted form of posixPath & " > '${tempFile}'"
47
+ `;
48
+
49
+ await runCommand("osascript", ["-e", script]);
50
+
51
+ } else {
52
+ // Linux - Try zenity first, then kdialog
53
+ try {
54
+ await runCommand("zenity", [
55
+ "--file-selection",
56
+ "--directory",
57
+ "--title=Select your project folder"
58
+ ], tempFile);
59
+ } catch {
60
+ await runCommand("kdialog", [
61
+ "--getexistingdirectory",
62
+ process.env.HOME || "/",
63
+ "--title", "Select your project folder"
64
+ ], tempFile);
65
+ }
66
+ }
67
+
68
+ // Read the selected folder
69
+ if (existsSync(tempFile)) {
70
+ const folderPath = readFileSync(tempFile, "utf8").trim();
71
+ unlinkSync(tempFile);
72
+ return folderPath;
73
+ }
74
+
75
+ return null;
76
+
77
+ } catch (error) {
78
+ const msg = error && error.message ? error.message : String(error);
79
+ if (os === "win32" && (msg.includes("ENOENT") || msg.includes("spawn powershell"))) {
80
+ console.error("Folder picker: PowerShell not found. Run from a path or pass the project path as an argument.");
81
+ } else if (os !== "win32" && os !== "darwin" && (msg.includes("ENOENT") || msg.includes("spawn"))) {
82
+ console.error("Folder picker: zenity or kdialog not found. Install one (e.g. apt install zenity) or pass the project path as an argument.");
83
+ } else {
84
+ console.error("Folder picker error:", msg);
85
+ }
86
+ return null;
87
+ }
88
+ }
89
+
90
+ // Run PowerShell command
91
+ function runPowerShell(script) {
92
+ return new Promise((resolve, reject) => {
93
+ const proc = spawn("powershell", [
94
+ "-NoProfile",
95
+ "-NonInteractive",
96
+ "-ExecutionPolicy", "Bypass",
97
+ "-Command", script
98
+ ], {
99
+ stdio: ["ignore", "pipe", "pipe"],
100
+ shell: false
101
+ });
102
+
103
+ let stderr = "";
104
+ proc.stderr?.on("data", (data) => stderr += data.toString());
105
+
106
+ proc.on("close", (code, signal) => {
107
+ if (code === 0) {
108
+ resolve();
109
+ } else {
110
+ reject(new Error(stderr || `PowerShell exited with code ${code ?? signal ?? 1}`));
111
+ }
112
+ });
113
+
114
+ proc.on("error", (err) => {
115
+ if (err.code === "ENOENT") {
116
+ reject(new Error("PowerShell not found. Install it or use a different method to select the folder."));
117
+ } else {
118
+ reject(err);
119
+ }
120
+ });
121
+ });
122
+ }
123
+
124
+ // Run generic command
125
+ function runCommand(command, args, outputFile) {
126
+ return new Promise((resolve, reject) => {
127
+ const proc = spawn(command, args, {
128
+ stdio: outputFile ? ["ignore", "pipe", "pipe"] : "pipe",
129
+ shell: true
130
+ });
131
+
132
+ let stdout = "";
133
+
134
+ if (outputFile) {
135
+ proc.stdout?.on("data", (data) => {
136
+ stdout += data.toString();
137
+ });
138
+ }
139
+
140
+ proc.on("close", (code, signal) => {
141
+ const exitCode = code ?? (signal ? 1 : 0);
142
+ if (exitCode === 0) {
143
+ if (outputFile && stdout) {
144
+ try { writeFileSync(outputFile, stdout.trim()); } catch (_) {}
145
+ }
146
+ resolve();
147
+ } else {
148
+ reject(new Error(`Command failed with code ${exitCode}`));
149
+ }
150
+ });
151
+
152
+ proc.on("error", (err) => {
153
+ if (err.code === "ENOENT") {
154
+ reject(new Error(`Command not found: ${command}`));
155
+ } else {
156
+ reject(err);
157
+ }
158
+ });
159
+ });
160
+ }