@ggcode-cli/ggcode 1.1.33 → 1.1.35

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.
Files changed (2) hide show
  1. package/lib/install.js +124 -32
  2. package/package.json +1 -1
package/lib/install.js CHANGED
@@ -1,9 +1,11 @@
1
1
  const crypto = require("crypto");
2
2
  const fs = require("fs");
3
+ const http = require("http");
3
4
  const https = require("https");
4
5
  const os = require("os");
5
6
  const path = require("path");
6
7
  const { execFileSync } = require("child_process");
8
+ const { URL } = require("url");
7
9
 
8
10
  const OWNER = "topcheer";
9
11
  const REPO = "ggcode";
@@ -108,11 +110,16 @@ function findInstalledBinary(requestedVersion, target) {
108
110
  if (!fs.existsSync(binary)) {
109
111
  continue;
110
112
  }
113
+ const metadata = readMetadata(dir);
114
+ if (!metadata) {
115
+ // No .ggcode-wrapper.json means this binary was not installed by the wrapper
116
+ // (e.g. a Python pip entry point script with the same name). Skip it.
117
+ continue;
118
+ }
111
119
  if (requestedVersion === "latest") {
112
- return { dir, binary, version: readMetadata(dir)?.version || "unknown" };
120
+ return { dir, binary, version: metadata.version || "unknown" };
113
121
  }
114
- const metadata = readMetadata(dir);
115
- if (metadata && metadata.version === requestedVersion) {
122
+ if (metadata.version === requestedVersion) {
116
123
  return { dir, binary, version: metadata.version };
117
124
  }
118
125
  }
@@ -358,24 +365,101 @@ async function downloadText(url) {
358
365
  return (await downloadBuffer(url)).toString("utf8");
359
366
  }
360
367
 
368
+ function getProxyURL() {
369
+ return (
370
+ process.env.https_proxy ||
371
+ process.env.HTTPS_PROXY ||
372
+ process.env.http_proxy ||
373
+ process.env.HTTP_PROXY ||
374
+ ""
375
+ );
376
+ }
377
+
378
+ function httpsGetViaProxy(targetUrl, callback) {
379
+ const proxyURL = getProxyURL();
380
+ if (!proxyURL) {
381
+ return https.get(targetUrl, { rejectUnauthorized: false }, callback);
382
+ }
383
+
384
+ const parsed = new URL(targetUrl);
385
+ const proxy = new URL(proxyURL);
386
+ const tls = require("tls");
387
+
388
+ const connectReq = http.request({
389
+ host: proxy.hostname,
390
+ port: proxy.port || 80,
391
+ method: "CONNECT",
392
+ path: `${parsed.hostname}:443`,
393
+ });
394
+
395
+ connectReq.on("connect", (res, socket) => {
396
+ if (res.statusCode !== 200) {
397
+ socket.destroy();
398
+ callback(new Error(`Proxy CONNECT failed: ${res.statusCode}`));
399
+ return;
400
+ }
401
+ const tlsSocket = tls.connect({
402
+ socket: socket,
403
+ servername: parsed.hostname,
404
+ rejectUnauthorized: false,
405
+ }, () => {
406
+ const req = https.request(
407
+ {
408
+ host: parsed.hostname,
409
+ port: 443,
410
+ path: parsed.pathname + (parsed.search || ""),
411
+ method: "GET",
412
+ rejectUnauthorized: false,
413
+ createConnection: () => tlsSocket,
414
+ },
415
+ callback,
416
+ );
417
+ req.on("error", (err) => callback(err));
418
+ req.end();
419
+ });
420
+ tlsSocket.on("error", (err) => callback(err));
421
+ });
422
+
423
+ connectReq.on("error", (err) => callback(err));
424
+ connectReq.end();
425
+
426
+ return connectReq;
427
+ }
428
+
429
+ function httpGetGeneric(targetUrl, callback) {
430
+ const parsed = new URL(targetUrl);
431
+ if (parsed.protocol === "https:") {
432
+ return httpsGetViaProxy(targetUrl, callback);
433
+ }
434
+ return http.get(targetUrl, callback);
435
+ }
436
+
361
437
  function downloadBuffer(url) {
362
438
  return new Promise((resolve, reject) => {
363
439
  const get = (target) => {
364
- https
365
- .get(target, (res) => {
366
- if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
367
- get(new URL(res.headers.location, target).toString());
368
- return;
369
- }
370
- if (res.statusCode !== 200) {
371
- reject(new Error(`${target} returned ${res.statusCode}`));
372
- return;
373
- }
374
- const chunks = [];
375
- res.on("data", (chunk) => chunks.push(chunk));
376
- res.on("end", () => resolve(Buffer.concat(chunks)));
377
- })
378
- .on("error", reject);
440
+ let handled = false;
441
+ const cb = (res) => {
442
+ if (handled) return;
443
+ if (res instanceof Error) {
444
+ handled = true;
445
+ reject(res);
446
+ return;
447
+ }
448
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
449
+ get(new URL(res.headers.location, target).toString());
450
+ return;
451
+ }
452
+ if (res.statusCode !== 200) {
453
+ handled = true;
454
+ reject(new Error(`${target} returned ${res.statusCode}`));
455
+ return;
456
+ }
457
+ handled = true;
458
+ const chunks = [];
459
+ res.on("data", (chunk) => chunks.push(chunk));
460
+ res.on("end", () => resolve(Buffer.concat(chunks)));
461
+ };
462
+ httpGetGeneric(target, cb);
379
463
  };
380
464
  get(url);
381
465
  });
@@ -384,21 +468,29 @@ function downloadBuffer(url) {
384
468
  function resolveFinalURL(url) {
385
469
  return new Promise((resolve, reject) => {
386
470
  const get = (target) => {
387
- https
388
- .get(target, (res) => {
389
- if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
390
- res.resume();
391
- get(new URL(res.headers.location, target).toString());
392
- return;
393
- }
394
- if (res.statusCode !== 200) {
395
- reject(new Error(`${target} returned ${res.statusCode}`));
396
- return;
397
- }
471
+ let handled = false;
472
+ const cb = (res) => {
473
+ if (handled) return;
474
+ if (res instanceof Error) {
475
+ handled = true;
476
+ reject(res);
477
+ return;
478
+ }
479
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
398
480
  res.resume();
399
- resolve(target);
400
- })
401
- .on("error", reject);
481
+ get(new URL(res.headers.location, target).toString());
482
+ return;
483
+ }
484
+ if (res.statusCode !== 200) {
485
+ handled = true;
486
+ reject(new Error(`${target} returned ${res.statusCode}`));
487
+ return;
488
+ }
489
+ handled = true;
490
+ res.resume();
491
+ resolve(target);
492
+ };
493
+ httpGetGeneric(target, cb);
402
494
  };
403
495
  get(url);
404
496
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ggcode-cli/ggcode",
3
- "version": "1.1.33",
3
+ "version": "1.1.35",
4
4
  "description": "Thin npm wrapper that installs the ggcode GitHub Release binary",
5
5
  "license": "MIT",
6
6
  "repository": {