@tongil_kim/clautunnel 1.6.0 → 1.6.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/dist/index.js +43 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3000,9 +3000,24 @@ var MobileServerManager = class {
|
|
|
3000
3000
|
let needsInstall = false;
|
|
3001
3001
|
try {
|
|
3002
3002
|
execSync2("which ngrok", { stdio: "pipe" });
|
|
3003
|
+
try {
|
|
3004
|
+
const configOutput = execSync2("ngrok config check", {
|
|
3005
|
+
stdio: "pipe",
|
|
3006
|
+
timeout: 5e3
|
|
3007
|
+
}).toString();
|
|
3008
|
+
if (!configOutput.toLowerCase().includes("valid")) {
|
|
3009
|
+
issues.push(
|
|
3010
|
+
"ngrok authtoken is not configured.\n 1. Sign up at https://ngrok.com\n 2. Copy your authtoken from https://dashboard.ngrok.com/get-started/your-authtoken\n 3. Run: ngrok config add-authtoken <your-token>"
|
|
3011
|
+
);
|
|
3012
|
+
}
|
|
3013
|
+
} catch {
|
|
3014
|
+
issues.push(
|
|
3015
|
+
"ngrok authtoken is not configured.\n 1. Sign up at https://ngrok.com\n 2. Copy your authtoken from https://dashboard.ngrok.com/get-started/your-authtoken\n 3. Run: ngrok config add-authtoken <your-token>"
|
|
3016
|
+
);
|
|
3017
|
+
}
|
|
3003
3018
|
} catch {
|
|
3004
3019
|
issues.push(
|
|
3005
|
-
"ngrok is not installed.\n Install: brew install ngrok\n Sign up
|
|
3020
|
+
"ngrok is not installed.\n Install: brew install ngrok\n Then configure your account:\n 1. Sign up at https://ngrok.com\n 2. Copy your authtoken from https://dashboard.ngrok.com/get-started/your-authtoken\n 3. Run: ngrok config add-authtoken <your-token>"
|
|
3006
3021
|
);
|
|
3007
3022
|
}
|
|
3008
3023
|
const nodeModulesPath = join5(this.mobileProjectPath, "node_modules");
|
|
@@ -3109,26 +3124,51 @@ var MobileServerManager = class {
|
|
|
3109
3124
|
async startNgrok() {
|
|
3110
3125
|
this.ensureLogDir();
|
|
3111
3126
|
this.ngrokLogStream = createWriteStream(join5(this.logDir, "ngrok.log"));
|
|
3127
|
+
let stderrData = "";
|
|
3112
3128
|
this.ngrokProcess = spawn2("ngrok", ["http", String(this.expoPort)], {
|
|
3113
3129
|
stdio: ["ignore", "pipe", "pipe"],
|
|
3114
3130
|
detached: false
|
|
3115
3131
|
});
|
|
3116
3132
|
this.ngrokProcess.stdout?.pipe(this.ngrokLogStream);
|
|
3117
|
-
this.ngrokProcess.stderr?.
|
|
3133
|
+
this.ngrokProcess.stderr?.on("data", (chunk) => {
|
|
3134
|
+
stderrData += chunk.toString();
|
|
3135
|
+
this.ngrokLogStream?.write(chunk);
|
|
3136
|
+
});
|
|
3118
3137
|
this.ngrokProcess.on("error", () => {
|
|
3119
3138
|
});
|
|
3120
3139
|
for (let i = 0; i < 10; i++) {
|
|
3121
3140
|
await this.sleep(1e3);
|
|
3141
|
+
if (this.ngrokProcess.exitCode !== null) {
|
|
3142
|
+
break;
|
|
3143
|
+
}
|
|
3122
3144
|
const url = await this.getNgrokTunnelUrl();
|
|
3123
3145
|
if (url) {
|
|
3124
3146
|
this.tunnelUrl = url;
|
|
3125
3147
|
return url;
|
|
3126
3148
|
}
|
|
3127
3149
|
}
|
|
3150
|
+
this.ngrokError = this.diagnoseNgrokFailure(stderrData);
|
|
3128
3151
|
this.killProcess(this.ngrokProcess);
|
|
3129
3152
|
this.ngrokProcess = null;
|
|
3130
3153
|
return null;
|
|
3131
3154
|
}
|
|
3155
|
+
/** Last ngrok error diagnosis (available after startNgrok fails) */
|
|
3156
|
+
ngrokError = null;
|
|
3157
|
+
diagnoseNgrokFailure(stderr) {
|
|
3158
|
+
const lower = stderr.toLowerCase();
|
|
3159
|
+
if (lower.includes("authtoken") || lower.includes("err_ngrok_105") || lower.includes("authentication")) {
|
|
3160
|
+
return "ngrok authentication failed.\n Your authtoken may be invalid or expired.\n 1. Get a new token at https://dashboard.ngrok.com/get-started/your-authtoken\n 2. Run: ngrok config add-authtoken <your-token>";
|
|
3161
|
+
}
|
|
3162
|
+
if (lower.includes("tunnel session limit") || lower.includes("err_ngrok_108")) {
|
|
3163
|
+
return "ngrok free plan session limit reached.\n Free accounts allow 1 tunnel at a time.\n Close other ngrok tunnels or upgrade your plan at https://ngrok.com/pricing";
|
|
3164
|
+
}
|
|
3165
|
+
if (lower.includes("tcp dial") || lower.includes("connection refused")) {
|
|
3166
|
+
return `ngrok could not connect to localhost:${this.expoPort}.
|
|
3167
|
+
This is usually a timing issue \u2014 the tunnel started before Expo was ready.`;
|
|
3168
|
+
}
|
|
3169
|
+
return `ngrok tunnel failed to start.
|
|
3170
|
+
Check logs for details: ${join5(this.logDir, "ngrok.log")}`;
|
|
3171
|
+
}
|
|
3132
3172
|
async startExpo(tunnelUrl) {
|
|
3133
3173
|
this.ensureLogDir();
|
|
3134
3174
|
this.expoLogStream = createWriteStream(join5(this.logDir, "expo.log"));
|
|
@@ -3219,7 +3259,7 @@ var MobileServerManager = class {
|
|
|
3219
3259
|
this.onProgress("Starting ngrok tunnel...");
|
|
3220
3260
|
const tunnelUrl = await this.startNgrok();
|
|
3221
3261
|
if (!tunnelUrl) {
|
|
3222
|
-
return { started: false, error: "Failed to start ngrok tunnel" };
|
|
3262
|
+
return { started: false, error: this.ngrokError ?? "Failed to start ngrok tunnel" };
|
|
3223
3263
|
}
|
|
3224
3264
|
this.onProgress("Starting Expo server...");
|
|
3225
3265
|
const expoStarted = await this.startExpo(tunnelUrl);
|