binary-collections 2.0.10 → 2.0.11

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 (165) hide show
  1. package/.puppeterrc.cjs +25 -0
  2. package/binaries/binary-executor.cjs +138 -3
  3. package/binaries/clean-nodemodule.cjs +138 -3
  4. package/binaries/clean-nodemodules.cjs +138 -3
  5. package/binaries/dev.cjs +138 -3
  6. package/binaries/empty.cjs +138 -3
  7. package/binaries/git-reduce-size.cjs +138 -3
  8. package/binaries/javakill.cjs +138 -3
  9. package/binaries/kill-night-crows.bat +7 -0
  10. package/binaries/kill-night-crows.ps1 +172 -0
  11. package/binaries/kill-process.cjs +138 -3
  12. package/binaries/nodekill.cjs +138 -3
  13. package/binaries/prod.cjs +138 -3
  14. package/binaries/py +111 -0
  15. package/binaries/py.cjs +178 -0
  16. package/binaries/py.cmd +49 -0
  17. package/binaries/rmfind.cjs +138 -3
  18. package/binaries/rmx.cjs +138 -3
  19. package/binaries/submodule-token.cjs +138 -3
  20. package/binaries/test-cjs +10 -0
  21. package/binaries/test-cjs.cjs +178 -0
  22. package/binaries/test-cjs.cmd +11 -0
  23. package/binaries/yarn-clean +32 -0
  24. package/binaries/yarn-clean.cjs +178 -0
  25. package/binaries/yarn-clean.cmd +30 -0
  26. package/binaries/yarn-clean.py +148 -0
  27. package/lib/binary-collections-config.cjs +1 -1
  28. package/lib/binary-collections-config.mjs +1 -1
  29. package/lib/binary-collections.cjs +167 -106
  30. package/lib/binary-collections.mjs +108 -94
  31. package/lib/changelog.cjs +61 -13
  32. package/lib/changelog.mjs +1 -1
  33. package/lib/{chunk-AI4CVPJ7.mjs → chunk-2CBJCW7E.mjs} +4 -4
  34. package/lib/chunk-34IQDTLZ.mjs +27 -0
  35. package/lib/chunk-3HFFECCI.mjs +27 -0
  36. package/lib/{chunk-SBNDSKG5.mjs → chunk-4UHL4WVN.mjs} +1 -1
  37. package/lib/chunk-7XTEJHOE.mjs +193 -0
  38. package/lib/chunk-AJDD5DZM.mjs +109 -0
  39. package/lib/chunk-BZWVHODJ.mjs +62 -0
  40. package/lib/{chunk-BEZKJ25G.mjs → chunk-FCDQGYBF.mjs} +5 -9
  41. package/lib/chunk-GEYA2USY.mjs +207 -0
  42. package/lib/chunk-ID2WBTE2.mjs +80 -0
  43. package/lib/chunk-JXFOHKDM.mjs +239 -0
  44. package/lib/{chunk-DI5MDPSN.mjs → chunk-N436BNBK.mjs} +192 -64
  45. package/lib/chunk-NCXAP7AA.mjs +31 -0
  46. package/lib/chunk-PDN26I7O.mjs +188 -0
  47. package/lib/{chunk-E6FDDAOO.mjs → chunk-RWLXRTYP.mjs} +1 -1
  48. package/lib/{chunk-BDCHCWHD.mjs → chunk-TOIVAQF7.mjs} +4 -4
  49. package/lib/chunk-V5SKYJUB.mjs +136 -0
  50. package/lib/{chunk-HMRMTYZM.mjs → chunk-WSRETQCA.mjs} +21 -2
  51. package/lib/chunk-XA3SNBPA.mjs +184 -0
  52. package/lib/chunk-YYLIQQKF.mjs +31 -0
  53. package/lib/{chunk-V3N3JEUF.mjs → chunk-Z6JLYU2J.mjs} +60 -13
  54. package/lib/{chunk-O6SWBEOQ.mjs → chunk-ZDMWBSYF.mjs} +2 -2
  55. package/lib/clean-github-actions-caches.cjs +63 -15
  56. package/lib/clean-github-actions-caches.mjs +3 -3
  57. package/lib/del-gradle.cjs +61 -13
  58. package/lib/del-gradle.js +1 -0
  59. package/lib/del-gradle.mjs +1 -1
  60. package/lib/del-node-modules.cjs +143 -148
  61. package/lib/del-node-modules.js +210 -14
  62. package/lib/del-node-modules.mjs +148 -17
  63. package/lib/del-ps.cjs +61 -13
  64. package/lib/del-ps.js +1 -0
  65. package/lib/del-ps.mjs +1 -1
  66. package/lib/del-yarn-caches.cjs +61 -13
  67. package/lib/del-yarn-caches.mjs +1 -1
  68. package/lib/find-node-modules-cli.js +1 -0
  69. package/lib/free-chatgpt.cjs +253 -47
  70. package/lib/free-chatgpt.mjs +2 -2
  71. package/lib/git/gitattributes.cjs +1 -0
  72. package/lib/git/gitattributes.d.cts +7 -2
  73. package/lib/git/gitattributes.mjs +1 -1
  74. package/lib/git/line-endings.cjs +2 -1
  75. package/lib/git/line-endings.mjs +2 -2
  76. package/lib/git/undo-commit-cli.cjs +110 -0
  77. package/lib/git/undo-commit-cli.d.ts +1 -0
  78. package/lib/git/undo-commit-cli.js +4 -0
  79. package/lib/git/undo-commit-cli.mjs +14 -0
  80. package/lib/git/undo-commit.cjs +81 -0
  81. package/lib/git/undo-commit.d.cts +1 -0
  82. package/lib/git/undo-commit.mjs +7 -0
  83. package/lib/git/undo-staged-cli.cjs +110 -0
  84. package/lib/git/undo-staged-cli.d.ts +1 -0
  85. package/lib/git/undo-staged-cli.js +4 -0
  86. package/lib/git/undo-staged-cli.mjs +14 -0
  87. package/lib/git/undo-staged.cjs +81 -0
  88. package/lib/git/undo-staged.d.cts +1 -0
  89. package/lib/git/undo-staged.mjs +7 -0
  90. package/lib/git/user-config.cjs +61 -14
  91. package/lib/git/user-config.mjs +2 -2
  92. package/lib/git-diff-cli.cjs +255 -49
  93. package/lib/git-diff-cli.d.ts +1 -0
  94. package/lib/git-diff-cli.js +1 -0
  95. package/lib/git-diff-cli.mjs +5 -4
  96. package/lib/git-diff.cjs +254 -49
  97. package/lib/git-diff.mjs +4 -4
  98. package/lib/git-fix.cjs +64 -16
  99. package/lib/git-fix.mjs +10 -10
  100. package/lib/git-purge.cjs +61 -13
  101. package/lib/git-purge.mjs +1 -1
  102. package/lib/kill-night-crows.cjs +87 -0
  103. package/lib/kill-night-crows.d.mts +1 -0
  104. package/lib/kill-night-crows.mjs +65 -0
  105. package/lib/npm-run-series.cjs +60 -13
  106. package/lib/npm-run-series.mjs +1 -1
  107. package/lib/package-resolutions-updater-cli.cjs +560 -0
  108. package/lib/package-resolutions-updater-cli.d.mts +1 -0
  109. package/lib/package-resolutions-updater-cli.mjs +124 -0
  110. package/lib/package-resolutions-updater.cjs +174 -154
  111. package/lib/package-resolutions-updater.d.mts +32 -1
  112. package/lib/package-resolutions-updater.mjs +16 -294
  113. package/lib/php-cs-fixer-staged.cjs +105 -0
  114. package/lib/php-cs-fixer-staged.d.cts +2 -0
  115. package/lib/php-cs-fixer-staged.mjs +117 -0
  116. package/lib/print-directory-tree.cjs +62 -14
  117. package/lib/print-directory-tree.mjs +2 -2
  118. package/lib/ps/connected-domain.d.ts +1 -1
  119. package/lib/ps/index.js +1 -0
  120. package/lib/remove-module.cjs +61 -13
  121. package/lib/remove-module.mjs +1 -1
  122. package/lib/rmpath.cjs +63 -15
  123. package/lib/rmpath.mjs +2 -2
  124. package/lib/submodule-install.cjs +62 -15
  125. package/lib/submodule-install.mjs +3 -3
  126. package/lib/submodule-remove-cli.cjs +5 -1
  127. package/lib/submodule-remove-cli.mjs +1 -1
  128. package/lib/submodule-remove.cjs +4 -1
  129. package/lib/submodule-remove.mjs +1 -1
  130. package/lib/utils/chatgpt.cjs +192 -34
  131. package/lib/utils/chatgpt.js +210 -43
  132. package/lib/utils/chatgpt.mjs +1 -1
  133. package/lib/utils/findEnvFiles.cjs +107 -0
  134. package/lib/utils/findEnvFiles.d.ts +8 -0
  135. package/lib/utils/findEnvFiles.js +121 -0
  136. package/lib/utils/findEnvFiles.mjs +8 -0
  137. package/lib/utils/findWorkspaceRoot.cjs +70 -0
  138. package/lib/utils/findWorkspaceRoot.d.ts +9 -0
  139. package/lib/utils/findWorkspaceRoot.js +57 -0
  140. package/lib/utils/findWorkspaceRoot.mjs +40 -0
  141. package/lib/utils/index.cjs +60 -13
  142. package/lib/utils/index.mjs +1 -1
  143. package/lib/utils/isGithubTokenValid.cjs +64 -0
  144. package/lib/utils/isGithubTokenValid.d.ts +7 -0
  145. package/lib/utils/isGithubTokenValid.js +48 -0
  146. package/lib/utils/isGithubTokenValid.mjs +36 -0
  147. package/lib/yarn-reinstall.cjs +61 -13
  148. package/lib/yarn-reinstall.mjs +1 -1
  149. package/package.json +107 -93
  150. package/readme.md +33 -34
  151. package/releases/readme.md +1 -1
  152. package/requirements.txt +1 -0
  153. package/lib/chunk-4EWQC6GZ.mjs +0 -382
  154. package/lib/chunk-4ZI7BQKQ.mjs +0 -381
  155. package/lib/chunk-5J2BEPY5.mjs +0 -83
  156. package/lib/chunk-AGZYRDC2.mjs +0 -323
  157. package/lib/chunk-HN52G2YL.mjs +0 -305
  158. package/lib/chunk-HO6GHCOB.mjs +0 -385
  159. package/lib/chunk-LEM5OMRP.mjs +0 -384
  160. package/lib/chunk-RCP7DHVY.mjs +0 -190
  161. package/lib/chunk-U6SO4QEV.mjs +0 -320
  162. package/lib/chunk-XD6BJK6Q.mjs +0 -351
  163. package/lib/chunk-YXSFGA2D.mjs +0 -383
  164. package/lib/git/gitattributes.d.ts +0 -33
  165. package/lib/git/gitattributes.js +0 -223
@@ -0,0 +1,239 @@
1
+ import { createRequire } from 'module'; const require = createRequire(import.meta.url);
2
+ import {
3
+ findEnvFiles
4
+ } from "./chunk-ID2WBTE2.mjs";
5
+ import {
6
+ require_utils
7
+ } from "./chunk-Z6JLYU2J.mjs";
8
+ import {
9
+ __toESM,
10
+ init_esm_shims
11
+ } from "./chunk-QQ4A6DLD.mjs";
12
+
13
+ // src/package-resolutions-updater.mjs
14
+ init_esm_shims();
15
+ var utils = __toESM(require_utils(), 1);
16
+ import * as dotenv from "dotenv";
17
+ import fs from "fs";
18
+ import https from "https";
19
+ import os from "os";
20
+ import path from "path";
21
+ var projectDir = process.cwd();
22
+ var envPath = path.join(projectDir, ".env");
23
+ var args = utils.getArgs();
24
+ if (!fs.existsSync(envPath)) {
25
+ const envFiles = findEnvFiles(projectDir, (file) => {
26
+ const content = fs.readFileSync(file, "utf-8");
27
+ return /GITHUB_TOKEN|ACCESS_TOKEN/.test(content);
28
+ });
29
+ if (envFiles.length > 0) {
30
+ envPath = envFiles[0];
31
+ }
32
+ }
33
+ if (fs.existsSync(envPath)) {
34
+ dotenv.config({ path: envPath, quiet: true, override: true });
35
+ }
36
+ var ACCESS_TOKEN = process.env.GITHUB_TOKEN || process.env.ACCESS_TOKEN;
37
+ if (args.help || args.h) {
38
+ showHelp();
39
+ }
40
+ function showHelp() {
41
+ const helpText = `
42
+ GitHub Package Resolutions Updater
43
+ Usage:
44
+ node src/package-resolutions-updater.mjs [options]
45
+ Options:
46
+ --help, -h Show this help message
47
+ Description:
48
+ Updates the commit hashes in package.json's 'resolutions' field for GitHub tarball URLs to point to the latest commit SHA of the corresponding repository and branch.
49
+ Features:
50
+ - Parses GitHub URLs to extract repository owner, name, and branch.
51
+ - Fetches the latest commit SHA across all branches using GitHub's API.
52
+ - Replaces the old branch or commit in the URL with the latest SHA.
53
+ - Overwrites package.json with the updated URLs.
54
+ Requirements:
55
+ - GitHub Personal Access Token (GITHUB_TOKEN) via .env
56
+ - ESM support (type: "module" in package.json)
57
+ - Node.js v18+ recommended
58
+ Dependencies:
59
+ - ansi-colors \u2013 for styled terminal output
60
+ - dotenv \u2013 to load GitHub token from .env
61
+ Examples:
62
+ node src/package-resolutions-updater.mjs
63
+ node src/package-resolutions-updater.mjs --help
64
+
65
+ `;
66
+ console.log(helpText);
67
+ process.exit(0);
68
+ }
69
+ var GITHUB_USER_AGENTS = [
70
+ "octokit-rest.js/19.0.7",
71
+ "GitHub CLI/2.40.0",
72
+ "Mozilla/5.0 (compatible; GitHubCopilot/1.0)",
73
+ "PostmanRuntime/7.32.3",
74
+ "binary-collections-resolver/1.0 (+https://github.com/dimaslanjaka/bin)"
75
+ ];
76
+ var userAgentDir = path.join(os.tmpdir(), "nodejs");
77
+ var userAgentFile = path.join(userAgentDir, "useragent.txt");
78
+ var selectedUserAgent;
79
+ try {
80
+ if (!fs.existsSync(userAgentDir)) fs.mkdirSync(userAgentDir, { recursive: true });
81
+ if (fs.existsSync(userAgentFile)) {
82
+ const fileAgent = fs.readFileSync(userAgentFile, "utf-8").trim();
83
+ if (GITHUB_USER_AGENTS.includes(fileAgent)) {
84
+ selectedUserAgent = fileAgent;
85
+ }
86
+ }
87
+ if (!selectedUserAgent) {
88
+ selectedUserAgent = GITHUB_USER_AGENTS[Math.floor(Math.random() * GITHUB_USER_AGENTS.length)];
89
+ fs.writeFileSync(userAgentFile, selectedUserAgent, "utf-8");
90
+ }
91
+ } catch (_e) {
92
+ selectedUserAgent = GITHUB_USER_AGENTS[Math.floor(Math.random() * GITHUB_USER_AGENTS.length)];
93
+ }
94
+ function fetchJson(url) {
95
+ const headers = {
96
+ "User-Agent": selectedUserAgent,
97
+ Accept: "application/vnd.github.v3+json",
98
+ "X-GitHub-Api-Version": "2022-11-28",
99
+ ...ACCESS_TOKEN ? { Authorization: `token ${ACCESS_TOKEN}` } : {}
100
+ };
101
+ return new Promise((resolve, reject) => {
102
+ https.get(url, { headers }, (res) => {
103
+ let data = "";
104
+ res.on("data", (chunk) => data += chunk);
105
+ res.on("end", () => {
106
+ try {
107
+ const json = JSON.parse(data);
108
+ if (res.statusCode < 200 || res.statusCode >= 300) {
109
+ return reject(
110
+ new Error(`GitHub API Error ${res.statusCode}: ${json.message || "Unknown error"}
111
+ URL: ${url}`)
112
+ );
113
+ }
114
+ resolve(json);
115
+ } catch {
116
+ reject(new Error(`Invalid JSON from: ${url}`));
117
+ }
118
+ });
119
+ }).on("error", reject);
120
+ });
121
+ }
122
+ async function getLatestCommit(owner, repo, branch = "main") {
123
+ var _a, _b, _c, _d;
124
+ const url = `https://api.github.com/repos/${owner}/${repo}/commits/${branch}`;
125
+ const json = await fetchJson(url);
126
+ const sha = json.sha;
127
+ const dateStr = ((_b = (_a = json.commit) == null ? void 0 : _a.committer) == null ? void 0 : _b.date) || ((_d = (_c = json.commit) == null ? void 0 : _c.author) == null ? void 0 : _d.date);
128
+ if (!sha || !dateStr) {
129
+ console.log(json);
130
+ throw new Error(`Missing SHA or date for ${owner}/${repo}@${branch}`);
131
+ }
132
+ return {
133
+ owner,
134
+ repo,
135
+ branch,
136
+ sha,
137
+ date: new Date(dateStr).toISOString()
138
+ };
139
+ }
140
+ async function getLatestCommitAcrossBranches(owner, repo) {
141
+ const branches = await fetchJson(`https://api.github.com/repos/${owner}/${repo}/branches`);
142
+ const commits = await Promise.all(
143
+ branches.map(async ({ name, commit }) => {
144
+ var _a, _b, _c, _d;
145
+ const commitSha = commit == null ? void 0 : commit.sha;
146
+ if (!commitSha) {
147
+ console.warn(`No commit SHA for '${owner}/${repo}' branch: ${name}`);
148
+ return { branch: name, sha: "", date: /* @__PURE__ */ new Date(0) };
149
+ }
150
+ try {
151
+ const commitData = await fetchJson(`https://api.github.com/repos/${owner}/${repo}/commits/${commitSha}`);
152
+ const dateStr = ((_b = (_a = commitData.commit) == null ? void 0 : _a.committer) == null ? void 0 : _b.date) || ((_d = (_c = commitData.commit) == null ? void 0 : _c.author) == null ? void 0 : _d.date);
153
+ const date = dateStr ? new Date(dateStr) : /* @__PURE__ */ new Date(0);
154
+ return { branch: name, sha: commitData.sha, date };
155
+ } catch (e) {
156
+ console.warn(`Failed to fetch commit for ${name}: ${e.message}`);
157
+ return { branch: name, sha: commitSha, date: /* @__PURE__ */ new Date(0) };
158
+ }
159
+ })
160
+ );
161
+ const latest = commits.reduce((a, b) => a.date > b.date ? a : b, { date: /* @__PURE__ */ new Date(0) });
162
+ return {
163
+ owner,
164
+ repo,
165
+ branch: latest.branch,
166
+ sha: latest.sha,
167
+ date: latest.date.toISOString()
168
+ };
169
+ }
170
+ function replaceRawWithLatestHash(url, latestHash) {
171
+ const match = url.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/raw\/([^/]+)\/(.+)$/);
172
+ if (!match) throw new Error("Invalid GitHub raw URL");
173
+ const [, owner, repo, _oldHash, path2] = match;
174
+ return `https://github.com/${owner}/${repo}/raw/${latestHash}/${path2}`;
175
+ }
176
+ function splitGitHubRefPath(refPath) {
177
+ const segments = refPath.split("/").filter(Boolean);
178
+ if (segments.length === 0) {
179
+ return { branch: "", remainder: null };
180
+ }
181
+ if (segments[0] === "refs" && segments[1] === "heads" && segments.length >= 3) {
182
+ return {
183
+ branch: segments[2],
184
+ remainder: segments.slice(3).join("/") || null
185
+ };
186
+ }
187
+ let branchSegmentCount = 1;
188
+ if (segments[0] === "refs") {
189
+ if ((segments[1] === "tags" || segments[1] === "remotes" || segments[1] === "pull") && segments.length >= 3) {
190
+ branchSegmentCount = segments[1] === "tags" ? 3 : 4;
191
+ }
192
+ }
193
+ const branch = segments.slice(0, branchSegmentCount).join("/");
194
+ const remainder = segments.slice(branchSegmentCount).join("/");
195
+ return {
196
+ branch,
197
+ remainder: remainder || null
198
+ };
199
+ }
200
+ function parseGitHubUrl(url) {
201
+ const ghRepoRoot = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/?$/;
202
+ const ghTreeOrBlob = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/(tree|blob)\/([^/]+(?:\/[^/]+)*)/;
203
+ const ghRaw = /^https:\/\/raw\.githubusercontent\.com\/([^/]+)\/([^/]+)\/(.+)$/;
204
+ const ghDotComRaw = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/raw\/(.+)$/;
205
+ let match;
206
+ if (match = url.match(ghRaw)) {
207
+ const [, owner, repo, rawPath] = match;
208
+ const { branch, remainder } = splitGitHubRefPath(rawPath);
209
+ return {
210
+ owner,
211
+ repo,
212
+ branch,
213
+ url: `https://raw.githubusercontent.com/${owner}/${repo}/${branch}${remainder ? `/${remainder}` : ""}`
214
+ };
215
+ }
216
+ if (match = url.match(ghDotComRaw)) {
217
+ const [, owner, repo, rawPath] = match;
218
+ const { branch } = splitGitHubRefPath(rawPath);
219
+ return { owner, repo, branch, url };
220
+ }
221
+ if (match = url.match(ghTreeOrBlob)) {
222
+ const [, owner, repo, , branchPath] = match;
223
+ const { branch } = splitGitHubRefPath(branchPath);
224
+ return { owner, repo, branch, url };
225
+ }
226
+ if (match = url.match(ghRepoRoot)) {
227
+ const [, owner, repo] = match;
228
+ return { owner, repo, url };
229
+ }
230
+ throw new Error(`Unsupported GitHub URL: ${url}`);
231
+ }
232
+
233
+ export {
234
+ fetchJson,
235
+ getLatestCommit,
236
+ getLatestCommitAcrossBranches,
237
+ replaceRawWithLatestHash,
238
+ parseGitHubUrl
239
+ };
@@ -1,7 +1,5 @@
1
1
  import { createRequire } from 'module'; const require = createRequire(import.meta.url);
2
2
  import {
3
- __filename,
4
- __require,
5
3
  init_esm_shims
6
4
  } from "./chunk-QQ4A6DLD.mjs";
7
5
 
@@ -11,10 +9,19 @@ import fs from "fs-extra";
11
9
  import puppeteer from "puppeteer-extra";
12
10
  import StealthPlugin from "puppeteer-extra-plugin-stealth";
13
11
  import path from "upath";
14
- import { pathToFileURL } from "url";
15
12
  var COOKIE_DIR = path.join(process.cwd(), "tmp", "cookies");
16
13
  var DEFAULT_COOKIE_PATH = path.join(COOKIE_DIR, "cookies.json");
14
+ var NAVIGATION_TIMEOUT_MS = 9e4;
15
+ var NETWORK_IDLE_TIMEOUT_MS = 15e3;
16
+ var MAX_INLINE_QUESTION_FILE_BYTES = 2 * 1024;
17
17
  fs.ensureDirSync(COOKIE_DIR);
18
+ async function gotoWithFallback(page, url) {
19
+ await page.goto(url, { waitUntil: "domcontentloaded", timeout: NAVIGATION_TIMEOUT_MS });
20
+ try {
21
+ await page.waitForNetworkIdle({ idleTime: 1e3, timeout: NETWORK_IDLE_TIMEOUT_MS });
22
+ } catch {
23
+ }
24
+ }
18
25
  async function saveCookies(page, path2 = DEFAULT_COOKIE_PATH) {
19
26
  const cookies = await page.cookies();
20
27
  fs.writeFileSync(path2, JSON.stringify(cookies, null, 2));
@@ -33,7 +40,7 @@ async function navigatePage(page, url) {
33
40
  if (cookies) {
34
41
  await page.setCookie(...cookies);
35
42
  }
36
- await page.goto(url, { waitUntil: "networkidle0" });
43
+ await gotoWithFallback(page, url);
37
44
  await page.evaluate(() => {
38
45
  window.__domStillUpdating = true;
39
46
  if (window.__domObserver) {
@@ -73,46 +80,151 @@ function loadCookies(cookieFilePath = DEFAULT_COOKIE_PATH) {
73
80
  return JSON.parse(fs.readFileSync(cookieFilePath));
74
81
  }
75
82
  async function writeQuestion(page, question) {
76
- const questions = question.split("\n");
77
83
  const promptTextarea = await page.waitForSelector("#prompt-textarea", { timeout: 3e4 });
78
84
  if (!promptTextarea) {
79
85
  console.log(
80
86
  "Cannot find the prompt input on the webpage. Please check whether you have access to chat.openai.com without logging in via your browser."
81
87
  );
82
- }
83
- await page.evaluate(() => {
84
- document.querySelector("#prompt-textarea").innerHTML = `<p></p>`;
85
- });
86
- if (questions.length === 1) {
87
- await page.type("#prompt-textarea", questions[0], { delay: 100 });
88
88
  return;
89
89
  }
90
- for (const q of questions) {
91
- await page.type("#prompt-textarea", q, { delay: 100 });
92
- if (q !== questions[questions.length - 1]) {
93
- await page.keyboard.down("Shift");
94
- await page.keyboard.press("Enter");
95
- await page.keyboard.up("Shift");
90
+ await page.evaluate((text) => {
91
+ const promptEl = document.querySelector("#prompt-textarea");
92
+ if (!promptEl) {
93
+ return;
94
+ }
95
+ promptEl.focus();
96
+ promptEl.innerHTML = "";
97
+ const lines = String(text).split("\n");
98
+ for (const line of lines) {
99
+ const p = document.createElement("p");
100
+ p.textContent = line;
101
+ promptEl.appendChild(p);
96
102
  }
103
+ promptEl.dispatchEvent(new InputEvent("beforeinput", { bubbles: true, inputType: "insertFromPaste", data: text }));
104
+ promptEl.dispatchEvent(new InputEvent("input", { bubbles: true, inputType: "insertFromPaste", data: text }));
105
+ promptEl.dispatchEvent(new Event("change", { bubbles: true }));
106
+ }, question);
107
+ const hasPromptText = await page.evaluate(() => {
108
+ const promptEl = document.querySelector("#prompt-textarea");
109
+ return Boolean(promptEl && promptEl.textContent && promptEl.textContent.trim().length > 0);
110
+ });
111
+ if (!hasPromptText) {
112
+ console.log("Prompt state not updated by DOM injection. Falling back to keyboard insertText.");
113
+ await promptTextarea.click({ clickCount: 1 });
114
+ await page.keyboard.down("Control");
115
+ await page.keyboard.press("KeyA");
116
+ await page.keyboard.up("Control");
117
+ await page.keyboard.insertText(question);
97
118
  }
98
119
  }
99
120
  async function clickSubmitButton(page) {
121
+ console.log("Attempting to click the submit button...");
100
122
  try {
101
- const fruitjuiceSendButton = await page.evaluate(() => {
102
- return document.querySelector('[data-testid="fruitjuice-send-button"]') !== null;
123
+ const userMessageCountBefore = await page.$$eval('[data-message-author-role="user"]', (elements) => elements.length);
124
+ const waitForSubmit = async (timeout = 5e3) => {
125
+ try {
126
+ await page.waitForFunction(
127
+ (previousCount) => {
128
+ const currentCount = document.querySelectorAll('[data-message-author-role="user"]').length;
129
+ return currentCount > previousCount;
130
+ },
131
+ { timeout },
132
+ userMessageCountBefore
133
+ );
134
+ return true;
135
+ } catch {
136
+ return false;
137
+ }
138
+ };
139
+ await page.waitForFunction(() => {
140
+ const candidates = [
141
+ document.querySelector('[data-testid="fruitjuice-send-button"]'),
142
+ document.querySelector("#composer-submit-button"),
143
+ document.querySelector('[data-testid="send-button"]')
144
+ ].filter(Boolean);
145
+ return candidates.some((button) => {
146
+ const isDisabled = button.disabled || button.getAttribute("aria-disabled") === "true";
147
+ const isVisible = button.offsetParent !== null;
148
+ return !isDisabled && isVisible;
149
+ });
150
+ }, { timeout: 5e3 }).catch(() => {
151
+ });
152
+ const buttonDetails = await page.evaluate(() => {
153
+ const selectors = [
154
+ '[data-testid="fruitjuice-send-button"]',
155
+ "#composer-submit-button",
156
+ '[data-testid="send-button"]'
157
+ ];
158
+ const details = selectors.map((selector) => {
159
+ const el = document.querySelector(selector);
160
+ const exists = Boolean(el);
161
+ const disabled = exists ? Boolean(el.disabled || el.getAttribute("aria-disabled") === "true") : null;
162
+ const visible = exists ? el.offsetParent !== null : null;
163
+ return { selector, exists, disabled, visible };
164
+ });
165
+ return details;
103
166
  });
104
- const sendButton = await page.evaluate(() => {
105
- return document.querySelector('[data-testid="send-button"]') !== null;
167
+ console.log(`Submit button details: ${JSON.stringify(buttonDetails)}`);
168
+ const clickable = buttonDetails.find((item) => item.exists && item.visible && item.disabled === false);
169
+ const selectedSelector = clickable ? clickable.selector : null;
170
+ if (selectedSelector) {
171
+ await page.click(selectedSelector);
172
+ console.log(`Clicked submit button selector: ${selectedSelector}`);
173
+ if (await waitForSubmit(5e3)) {
174
+ console.log("Submission detected after selector click.");
175
+ return true;
176
+ }
177
+ const forcedClickWorked = await page.evaluate((selector) => {
178
+ const el = document.querySelector(selector);
179
+ if (!el) {
180
+ return false;
181
+ }
182
+ el.click();
183
+ return true;
184
+ }, selectedSelector);
185
+ if (forcedClickWorked) {
186
+ console.log(`Forced DOM click on selector: ${selectedSelector}`);
187
+ if (await waitForSubmit(5e3)) {
188
+ console.log("Submission detected after forced DOM click.");
189
+ return true;
190
+ }
191
+ }
192
+ }
193
+ console.log("Submit button path did not submit. Trying Enter key fallback on prompt.");
194
+ await page.focus("#prompt-textarea");
195
+ await page.keyboard.press("Enter");
196
+ if (await waitForSubmit(5e3)) {
197
+ console.log("Submission detected after Enter key fallback.");
198
+ return true;
199
+ }
200
+ const didRequestSubmit = await page.evaluate(() => {
201
+ const prompt = document.querySelector("#prompt-textarea");
202
+ if (!prompt) {
203
+ return false;
204
+ }
205
+ const form = prompt.closest("form");
206
+ if (!form) {
207
+ return false;
208
+ }
209
+ if (typeof form.requestSubmit === "function") {
210
+ form.requestSubmit();
211
+ } else {
212
+ form.submit();
213
+ }
214
+ return true;
106
215
  });
107
- if (fruitjuiceSendButton) {
108
- await page.click('[data-testid="fruitjuice-send-button"]');
109
- } else if (sendButton) {
110
- await page.click('[data-testid="send-button"]');
111
- } else {
112
- console.log("Neither send button is present");
216
+ if (didRequestSubmit) {
217
+ console.log("Triggered form submit fallback.");
218
+ if (await waitForSubmit(5e3)) {
219
+ console.log("Submission detected after form submit fallback.");
220
+ return true;
221
+ }
113
222
  }
223
+ console.log("Failed to submit prompt after all strategies.");
224
+ return false;
114
225
  } catch (e) {
115
226
  console.log(`Failed to click the send button: ${e}`);
227
+ return false;
116
228
  }
117
229
  }
118
230
  var lastMessageId = null;
@@ -185,11 +297,15 @@ async function isLoggedIn(page) {
185
297
  return result === true;
186
298
  }
187
299
  async function createBrowser(browserOptions = {}) {
300
+ const windowsChromeExecutable = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe";
301
+ const hasWindowsChrome = process.platform === "win32" && fs.existsSync(windowsChromeExecutable);
188
302
  const defaultOptions = {
189
303
  headless: false,
304
+ defaultViewport: null,
190
305
  userDataDir: path.join(process.cwd(), "tmp/puppeteer-profile"),
191
306
  // Windows-specific options to handle browser launch issues
192
307
  args: [
308
+ "--start-maximized",
193
309
  "--no-sandbox",
194
310
  "--disable-setuid-sandbox",
195
311
  "--disable-dev-shm-usage",
@@ -202,10 +318,9 @@ async function createBrowser(browserOptions = {}) {
202
318
  "--disable-renderer-backgrounding"
203
319
  ],
204
320
  ignoreDefaultArgs: ["--disable-extensions"],
205
- ...process.platform === "win32" && {
206
- // Additional Windows-specific options
207
- executablePath: void 0
208
- // Let Puppeteer find Chrome automatically
321
+ ...hasWindowsChrome && {
322
+ // Prefer local Chrome installation when present on Windows.
323
+ executablePath: windowsChromeExecutable
209
324
  }
210
325
  };
211
326
  try {
@@ -215,8 +330,12 @@ async function createBrowser(browserOptions = {}) {
215
330
  try {
216
331
  return await puppeteer.use(StealthPlugin()).launch({
217
332
  headless: browserOptions.headless || false,
218
- args: ["--no-sandbox", "--disable-setuid-sandbox"],
333
+ defaultViewport: null,
334
+ args: ["--start-maximized", "--no-sandbox", "--disable-setuid-sandbox"],
219
335
  ignoreDefaultArgs: false,
336
+ ...hasWindowsChrome && {
337
+ executablePath: windowsChromeExecutable
338
+ },
220
339
  ...browserOptions
221
340
  });
222
341
  } catch (fallbackError) {
@@ -241,7 +360,11 @@ async function loginToChatGpt() {
241
360
  if (loginButtonExists) {
242
361
  console.log("Login button found, clicking to log in...");
243
362
  await page.click('[data-testid="login-button"]');
244
- await page.waitForNavigation({ waitUntil: "networkidle0" });
363
+ await page.waitForNavigation({ waitUntil: "domcontentloaded", timeout: NAVIGATION_TIMEOUT_MS });
364
+ try {
365
+ await page.waitForNetworkIdle({ idleTime: 1e3, timeout: NETWORK_IDLE_TIMEOUT_MS });
366
+ } catch {
367
+ }
245
368
  console.log("Login process completed.");
246
369
  } else {
247
370
  console.log("No login required - user appears to be already logged in.");
@@ -251,6 +374,7 @@ async function runChatGpt(chatgptOptions = {}) {
251
374
  const headless = chatgptOptions.headless !== void 0 ? chatgptOptions.headless : true;
252
375
  const questionFile = chatgptOptions.questionFile;
253
376
  let question = chatgptOptions.question;
377
+ let shouldUploadQuestionFile = Boolean(questionFile);
254
378
  const responseFile = chatgptOptions.responseFile || path.join(process.cwd(), "tmp", "response.txt");
255
379
  const noInputProvided = !question && !questionFile;
256
380
  const questionIsEmpty = question && question.trim().length === 0;
@@ -258,6 +382,22 @@ async function runChatGpt(chatgptOptions = {}) {
258
382
  if (noInputProvided || questionIsEmpty || questionFileIsEmpty) {
259
383
  throw new Error("You must provide a question or a question file.");
260
384
  }
385
+ if (!question && questionFile) {
386
+ if (!fs.existsSync(questionFile)) {
387
+ throw new Error(`Question file does not exist: ${questionFile}`);
388
+ }
389
+ const questionFileStats = fs.statSync(questionFile);
390
+ if (questionFileStats.size <= MAX_INLINE_QUESTION_FILE_BYTES) {
391
+ question = fs.readFileSync(questionFile, "utf8").trim();
392
+ if (!question) {
393
+ throw new Error("Question file is empty.");
394
+ }
395
+ shouldUploadQuestionFile = false;
396
+ console.log(
397
+ `Question file is ${questionFileStats.size} bytes (<= ${MAX_INLINE_QUESTION_FILE_BYTES}). Sending as text prompt.`
398
+ );
399
+ }
400
+ }
261
401
  let browser;
262
402
  try {
263
403
  browser = await createBrowser({ headless });
@@ -270,7 +410,16 @@ async function runChatGpt(chatgptOptions = {}) {
270
410
  console.error("4. Close any running Chrome instances and try again");
271
411
  throw error;
272
412
  }
273
- const page = (await browser.pages()).length > 0 ? (await browser.pages())[0] : await browser.newPage();
413
+ const allPages = await browser.pages();
414
+ const page = allPages.length > 0 ? allPages[0] : await browser.newPage();
415
+ await page.bringToFront();
416
+ if (allPages.length > 1) {
417
+ for (const p of allPages) {
418
+ if (p !== page) {
419
+ await p.close();
420
+ }
421
+ }
422
+ }
274
423
  try {
275
424
  const url = "https://chat.openai.com";
276
425
  const navigate = await navigatePage(page, url);
@@ -289,12 +438,15 @@ async function runChatGpt(chatgptOptions = {}) {
289
438
  }
290
439
  if (question) {
291
440
  await writeQuestion(page, question);
292
- await clickSubmitButton(page);
441
+ const didSubmit = await clickSubmitButton(page);
442
+ if (!didSubmit) {
443
+ throw new Error("Prompt was not submitted. The composer button may be disabled or blocked.");
444
+ }
293
445
  await navigate.waitForDomIdle(1e3, 3e4);
294
446
  await waitForInitialResponse(page);
295
447
  await handleStreamingResponse(page, responseFile);
296
448
  await saveCookies(page, getCookiePathForUrl(url));
297
- } else if (questionFile) {
449
+ } else if (shouldUploadQuestionFile && questionFile) {
298
450
  await navigate.waitForDomIdle(2e3, 1e4);
299
451
  const isUserLoggedIn = await isLoggedIn(page);
300
452
  console.log(`Login status: ${isUserLoggedIn ? "Logged in" : "Not logged in"}`);
@@ -333,7 +485,10 @@ async function runChatGpt(chatgptOptions = {}) {
333
485
  await fileInput.uploadFile(questionFile);
334
486
  await navigate.waitForDomIdle(2e3, 15e3);
335
487
  console.log("File uploaded successfully");
336
- await clickSubmitButton(page);
488
+ const didSubmit = await clickSubmitButton(page);
489
+ if (!didSubmit) {
490
+ throw new Error("Prompt was not submitted after file upload.");
491
+ }
337
492
  await navigate.waitForDomIdle(1e3, 3e4);
338
493
  await waitForInitialResponse(page);
339
494
  await handleStreamingResponse(page, responseFile);
@@ -353,33 +508,6 @@ async function runChatGpt(chatgptOptions = {}) {
353
508
  }
354
509
  }
355
510
  }
356
- var isMain = false;
357
- try {
358
- const mainArg = process.argv[1] && path.resolve(process.argv[1]);
359
- const currentScript = __filename && path.resolve(__filename);
360
- if (typeof __require !== "undefined" && typeof module !== "undefined" && __require.main === module) {
361
- isMain = true;
362
- }
363
- console.log("[chatgpt.js][CJS check]", typeof __require, typeof module, __require.main === module);
364
- console.log("[chatgpt.js][CJS check]", mainArg, currentScript);
365
- console.log("[chatgpt.js][CJS check]", "isMain:", isMain);
366
- } catch (_e) {
367
- }
368
- try {
369
- const mainArg = process.argv[1] && path.resolve(process.argv[1]);
370
- if (mainArg && import.meta.url === pathToFileURL(mainArg).href) {
371
- isMain = true;
372
- }
373
- } catch (_e) {
374
- }
375
- if (isMain) {
376
- (async () => {
377
- try {
378
- } catch (error) {
379
- console.error("Error running ChatGPT:", error);
380
- }
381
- })();
382
- }
383
511
 
384
512
  export {
385
513
  runChatGpt
@@ -0,0 +1,31 @@
1
+ import { createRequire } from 'module'; const require = createRequire(import.meta.url);
2
+ import {
3
+ __commonJS,
4
+ __require,
5
+ init_esm_shims
6
+ } from "./chunk-QQ4A6DLD.mjs";
7
+
8
+ // src/binary-collections-config.cjs
9
+ var require_binary_collections_config = __commonJS({
10
+ "src/binary-collections-config.cjs"(exports, module) {
11
+ init_esm_shims();
12
+ var path = __require("path");
13
+ __require("dotenv").config({ path: path.join(process.cwd(), ".env"), quiet: true });
14
+ function getTempDir() {
15
+ return process.env.TEMP_DIR || path.join(process.cwd(), "tmp");
16
+ }
17
+ function getTempPath(...segments) {
18
+ return path.join(getTempDir(), ...segments);
19
+ }
20
+ var TEMP_BASE_DIR = getTempDir();
21
+ module.exports = {
22
+ getTempDir,
23
+ getTempPath,
24
+ TEMP_BASE_DIR
25
+ };
26
+ }
27
+ });
28
+
29
+ export {
30
+ require_binary_collections_config
31
+ };