gologin-web-access 0.3.0

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 (141) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +344 -0
  4. package/dist/cli.js +173 -0
  5. package/dist/commands/back.js +13 -0
  6. package/dist/commands/batch.js +81 -0
  7. package/dist/commands/batchChangeTrack.js +99 -0
  8. package/dist/commands/batchExtract.js +97 -0
  9. package/dist/commands/batchScrape.js +140 -0
  10. package/dist/commands/changeTrack.js +65 -0
  11. package/dist/commands/check.js +14 -0
  12. package/dist/commands/click.js +14 -0
  13. package/dist/commands/close.js +19 -0
  14. package/dist/commands/configInit.js +77 -0
  15. package/dist/commands/configShow.js +23 -0
  16. package/dist/commands/cookies.js +22 -0
  17. package/dist/commands/cookiesClear.js +13 -0
  18. package/dist/commands/cookiesImport.js +14 -0
  19. package/dist/commands/crawl.js +71 -0
  20. package/dist/commands/crawlErrors.js +20 -0
  21. package/dist/commands/crawlResult.js +27 -0
  22. package/dist/commands/crawlStart.js +56 -0
  23. package/dist/commands/crawlStatus.js +25 -0
  24. package/dist/commands/current.js +14 -0
  25. package/dist/commands/dblclick.js +14 -0
  26. package/dist/commands/eval.js +20 -0
  27. package/dist/commands/extract.js +44 -0
  28. package/dist/commands/fill.js +15 -0
  29. package/dist/commands/find.js +16 -0
  30. package/dist/commands/focus.js +14 -0
  31. package/dist/commands/forward.js +13 -0
  32. package/dist/commands/get.js +15 -0
  33. package/dist/commands/hover.js +14 -0
  34. package/dist/commands/jobs.js +47 -0
  35. package/dist/commands/map.js +61 -0
  36. package/dist/commands/open.js +22 -0
  37. package/dist/commands/parseDocument.js +34 -0
  38. package/dist/commands/pdf.js +14 -0
  39. package/dist/commands/press.js +15 -0
  40. package/dist/commands/read.js +51 -0
  41. package/dist/commands/reload.js +13 -0
  42. package/dist/commands/run.js +76 -0
  43. package/dist/commands/scrape.js +19 -0
  44. package/dist/commands/scrapeJson.js +24 -0
  45. package/dist/commands/scrapeMarkdown.js +37 -0
  46. package/dist/commands/scrapeScreenshot.js +65 -0
  47. package/dist/commands/scrapeText.js +37 -0
  48. package/dist/commands/screenshot.js +23 -0
  49. package/dist/commands/scroll.js +23 -0
  50. package/dist/commands/scrollIntoView.js +14 -0
  51. package/dist/commands/search.js +39 -0
  52. package/dist/commands/searchBrowser.js +28 -0
  53. package/dist/commands/select.js +15 -0
  54. package/dist/commands/sessions.js +14 -0
  55. package/dist/commands/shared.js +102 -0
  56. package/dist/commands/snapshot.js +18 -0
  57. package/dist/commands/storageClear.js +18 -0
  58. package/dist/commands/storageExport.js +26 -0
  59. package/dist/commands/storageImport.js +23 -0
  60. package/dist/commands/tabClose.js +18 -0
  61. package/dist/commands/tabFocus.js +15 -0
  62. package/dist/commands/tabOpen.js +19 -0
  63. package/dist/commands/tabs.js +13 -0
  64. package/dist/commands/type.js +15 -0
  65. package/dist/commands/uncheck.js +14 -0
  66. package/dist/commands/upload.js +15 -0
  67. package/dist/commands/wait.js +27 -0
  68. package/dist/config.js +260 -0
  69. package/dist/doctor.js +86 -0
  70. package/dist/internal-agent/cli.js +336 -0
  71. package/dist/internal-agent/commands/back.js +12 -0
  72. package/dist/internal-agent/commands/check.js +17 -0
  73. package/dist/internal-agent/commands/click.js +17 -0
  74. package/dist/internal-agent/commands/close.js +12 -0
  75. package/dist/internal-agent/commands/cookies.js +23 -0
  76. package/dist/internal-agent/commands/cookiesClear.js +12 -0
  77. package/dist/internal-agent/commands/cookiesImport.js +18 -0
  78. package/dist/internal-agent/commands/current.js +9 -0
  79. package/dist/internal-agent/commands/dblclick.js +17 -0
  80. package/dist/internal-agent/commands/doctor.js +53 -0
  81. package/dist/internal-agent/commands/eval.js +30 -0
  82. package/dist/internal-agent/commands/fill.js +18 -0
  83. package/dist/internal-agent/commands/find.js +86 -0
  84. package/dist/internal-agent/commands/focus.js +17 -0
  85. package/dist/internal-agent/commands/forward.js +12 -0
  86. package/dist/internal-agent/commands/get.js +19 -0
  87. package/dist/internal-agent/commands/hover.js +17 -0
  88. package/dist/internal-agent/commands/open.js +67 -0
  89. package/dist/internal-agent/commands/pdf.js +18 -0
  90. package/dist/internal-agent/commands/press.js +19 -0
  91. package/dist/internal-agent/commands/reload.js +12 -0
  92. package/dist/internal-agent/commands/screenshot.js +22 -0
  93. package/dist/internal-agent/commands/scroll.js +25 -0
  94. package/dist/internal-agent/commands/scrollIntoView.js +17 -0
  95. package/dist/internal-agent/commands/select.js +18 -0
  96. package/dist/internal-agent/commands/sessions.js +15 -0
  97. package/dist/internal-agent/commands/shared.js +51 -0
  98. package/dist/internal-agent/commands/snapshot.js +16 -0
  99. package/dist/internal-agent/commands/storageClear.js +13 -0
  100. package/dist/internal-agent/commands/storageExport.js +24 -0
  101. package/dist/internal-agent/commands/storageImport.js +20 -0
  102. package/dist/internal-agent/commands/tabClose.js +21 -0
  103. package/dist/internal-agent/commands/tabFocus.js +21 -0
  104. package/dist/internal-agent/commands/tabOpen.js +13 -0
  105. package/dist/internal-agent/commands/tabs.js +17 -0
  106. package/dist/internal-agent/commands/type.js +18 -0
  107. package/dist/internal-agent/commands/uncheck.js +17 -0
  108. package/dist/internal-agent/commands/upload.js +18 -0
  109. package/dist/internal-agent/commands/wait.js +41 -0
  110. package/dist/internal-agent/daemon/browser.js +818 -0
  111. package/dist/internal-agent/daemon/refStore.js +26 -0
  112. package/dist/internal-agent/daemon/server.js +330 -0
  113. package/dist/internal-agent/daemon/sessionManager.js +684 -0
  114. package/dist/internal-agent/daemon/snapshot.js +285 -0
  115. package/dist/internal-agent/lib/config.js +59 -0
  116. package/dist/internal-agent/lib/daemon.js +300 -0
  117. package/dist/internal-agent/lib/errors.js +63 -0
  118. package/dist/internal-agent/lib/types.js +2 -0
  119. package/dist/internal-agent/lib/utils.js +165 -0
  120. package/dist/jobRunner.js +56 -0
  121. package/dist/lib/agentCli.js +158 -0
  122. package/dist/lib/browserRead.js +125 -0
  123. package/dist/lib/browserStructured.js +77 -0
  124. package/dist/lib/changeTracking.js +117 -0
  125. package/dist/lib/cloudApi.js +41 -0
  126. package/dist/lib/concurrency.js +15 -0
  127. package/dist/lib/crawl.js +313 -0
  128. package/dist/lib/document.js +170 -0
  129. package/dist/lib/errors.js +55 -0
  130. package/dist/lib/extract.js +65 -0
  131. package/dist/lib/extractRunner.js +22 -0
  132. package/dist/lib/jobRegistry.js +164 -0
  133. package/dist/lib/output.js +122 -0
  134. package/dist/lib/readSource.js +297 -0
  135. package/dist/lib/runbooks.js +193 -0
  136. package/dist/lib/search.js +727 -0
  137. package/dist/lib/selfCli.js +136 -0
  138. package/dist/lib/structuredScrape.js +83 -0
  139. package/dist/lib/types.js +2 -0
  140. package/dist/lib/unlocker.js +383 -0
  141. package/package.json +67 -0
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildTabFocusCommand = buildTabFocusCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildTabFocusCommand() {
7
+ const command = new commander_1.Command("tabfocus")
8
+ .alias("tabswitch")
9
+ .description("Focus a specific tab in the active Cloud Browser session.")
10
+ .argument("<index>", "1-based tab index")
11
+ .action(async (index, options) => {
12
+ await (0, shared_1.runBrowserCommand)(["tabfocus", index], { session: options.session });
13
+ });
14
+ return (0, shared_1.addSessionOption)(command);
15
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildTabOpenCommand = buildTabOpenCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildTabOpenCommand() {
7
+ const command = new commander_1.Command("tabopen")
8
+ .alias("tabnew")
9
+ .description("Open a new tab in the active Cloud Browser session.")
10
+ .argument("[url]", "Optional URL to open in the new tab")
11
+ .action(async (url, options) => {
12
+ const args = ["tabopen"];
13
+ if (url) {
14
+ args.push(url);
15
+ }
16
+ await (0, shared_1.runBrowserCommand)(args, { session: options.session });
17
+ });
18
+ return (0, shared_1.addSessionOption)(command);
19
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildTabsCommand = buildTabsCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildTabsCommand() {
7
+ const command = new commander_1.Command("tabs")
8
+ .description("List open tabs in the current Gologin Cloud Browser session.")
9
+ .action(async (options) => {
10
+ await (0, shared_1.runBrowserCommand)(["tabs"], { session: options.session });
11
+ });
12
+ return (0, shared_1.addSessionOption)(command);
13
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildTypeCommand = buildTypeCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildTypeCommand() {
7
+ const command = new commander_1.Command("type")
8
+ .description("Type text into an element by snapshot ref.")
9
+ .argument("<ref>", "Snapshot ref, for example e2")
10
+ .argument("<text>", "Text to type")
11
+ .action(async (ref, text, options) => {
12
+ await (0, shared_1.runBrowserCommand)(["type", ref, text], { session: options.session });
13
+ });
14
+ return (0, shared_1.addSessionOption)(command);
15
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildUncheckCommand = buildUncheckCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildUncheckCommand() {
7
+ const command = new commander_1.Command("uncheck")
8
+ .description("Uncheck an element by snapshot ref.")
9
+ .argument("<ref>", "Snapshot ref, for example e2")
10
+ .action(async (ref, options) => {
11
+ await (0, shared_1.runBrowserCommand)(["uncheck", ref], { session: options.session });
12
+ });
13
+ return (0, shared_1.addSessionOption)(command);
14
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildUploadCommand = buildUploadCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildUploadCommand() {
7
+ const command = new commander_1.Command("upload")
8
+ .description("Upload one or more files to an element by snapshot ref.")
9
+ .argument("<ref>", "Snapshot ref, for example e2")
10
+ .argument("<files...>", "One or more files to upload")
11
+ .action(async (ref, files, options) => {
12
+ await (0, shared_1.runBrowserCommand)(["upload", ref, ...files.map(shared_1.resolveOutputPath)], { session: options.session });
13
+ });
14
+ return (0, shared_1.addSessionOption)(command);
15
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildWaitCommand = buildWaitCommand;
4
+ const commander_1 = require("commander");
5
+ const shared_1 = require("./shared");
6
+ function buildWaitCommand() {
7
+ const command = new commander_1.Command("wait")
8
+ .description("Wait for a target, text, URL pattern, load state, or timeout.")
9
+ .argument("<targetOrMs>", "Target ref or timeout in milliseconds")
10
+ .option("--text <text>", "Wait for matching text")
11
+ .option("--url <pattern>", "Wait for URL pattern")
12
+ .option("--load <state>", "load, domcontentloaded, or networkidle")
13
+ .action(async (targetOrMs, options) => {
14
+ const args = ["wait", targetOrMs];
15
+ if (options.text) {
16
+ args.push("--text", options.text);
17
+ }
18
+ if (options.url) {
19
+ args.push("--url", options.url);
20
+ }
21
+ if (options.load) {
22
+ args.push("--load", options.load);
23
+ }
24
+ await (0, shared_1.runBrowserCommand)(args, { session: options.session });
25
+ });
26
+ return (0, shared_1.addSessionOption)(command);
27
+ }
package/dist/config.js ADDED
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ENV_NAMES = exports.DEFAULT_DAEMON_PORT = void 0;
7
+ exports.getDefaultConfigPath = getDefaultConfigPath;
8
+ exports.loadConfig = loadConfig;
9
+ exports.initConfigFile = initConfigFile;
10
+ exports.requireWebUnlockerKey = requireWebUnlockerKey;
11
+ exports.requireCloudToken = requireCloudToken;
12
+ exports.resolveProfileId = resolveProfileId;
13
+ exports.getRecommendedCredentialStatus = getRecommendedCredentialStatus;
14
+ exports.getMaskedConfigRows = getMaskedConfigRows;
15
+ const fs_1 = require("fs");
16
+ const os_1 = __importDefault(require("os"));
17
+ const path_1 = __importDefault(require("path"));
18
+ const errors_1 = require("./lib/errors");
19
+ const output_1 = require("./lib/output");
20
+ const CONFIG_DIR = ".gologin-web-access";
21
+ const LEGACY_CONFIG_DIR = ".gologin-web";
22
+ const CONFIG_FILENAME = "config.json";
23
+ exports.DEFAULT_DAEMON_PORT = 4590;
24
+ exports.ENV_NAMES = {
25
+ webUnlockerApiKey: "GOLOGIN_WEB_UNLOCKER_API_KEY",
26
+ cloudToken: "GOLOGIN_CLOUD_TOKEN",
27
+ defaultProfileId: "GOLOGIN_DEFAULT_PROFILE_ID",
28
+ daemonPort: "GOLOGIN_DAEMON_PORT",
29
+ };
30
+ const LEGACY_ENV_NAMES = {
31
+ webUnlockerApiKey: ["GOLOGIN_WEBUNLOCKER_API_KEY"],
32
+ cloudToken: ["GOLOGIN_TOKEN"],
33
+ defaultProfileId: ["GOLOGIN_PROFILE_ID"],
34
+ daemonPort: [],
35
+ };
36
+ function getDefaultConfigPath() {
37
+ return path_1.default.join(os_1.default.homedir(), CONFIG_DIR, CONFIG_FILENAME);
38
+ }
39
+ async function loadConfig() {
40
+ const configPath = await resolveConfigPath();
41
+ const stateDir = path_1.default.dirname(configPath);
42
+ const fileConfig = await readConfigFile(configPath);
43
+ const webUnlockerEnv = firstEnvValue(exports.ENV_NAMES.webUnlockerApiKey, LEGACY_ENV_NAMES.webUnlockerApiKey);
44
+ const cloudTokenEnv = firstEnvValue(exports.ENV_NAMES.cloudToken, LEGACY_ENV_NAMES.cloudToken);
45
+ const profileEnv = firstEnvValue(exports.ENV_NAMES.defaultProfileId, LEGACY_ENV_NAMES.defaultProfileId);
46
+ const daemonPortEnv = firstEnvValue(exports.ENV_NAMES.daemonPort, LEGACY_ENV_NAMES.daemonPort);
47
+ const webUnlockerApiKey = pickString(webUnlockerEnv, fileConfig.webUnlockerApiKey);
48
+ const cloudToken = pickString(cloudTokenEnv, fileConfig.cloudToken);
49
+ const defaultProfileId = pickString(profileEnv, fileConfig.defaultProfileId);
50
+ const daemonPort = pickNumber(daemonPortEnv, fileConfig.daemonPort, exports.DEFAULT_DAEMON_PORT);
51
+ return {
52
+ configPath,
53
+ stateDir,
54
+ jobsDir: path_1.default.join(stateDir, "jobs"),
55
+ trackingDir: path_1.default.join(stateDir, "tracking"),
56
+ artifactsDir: path_1.default.join(stateDir, "artifacts"),
57
+ webUnlockerApiKey,
58
+ cloudToken,
59
+ defaultProfileId,
60
+ daemonPort,
61
+ sources: {
62
+ webUnlockerApiKey: resolveSource(webUnlockerEnv, fileConfig.webUnlockerApiKey),
63
+ cloudToken: resolveSource(cloudTokenEnv, fileConfig.cloudToken),
64
+ defaultProfileId: resolveSource(profileEnv, fileConfig.defaultProfileId),
65
+ daemonPort: resolveNumberSource(daemonPortEnv, fileConfig.daemonPort),
66
+ },
67
+ };
68
+ }
69
+ async function initConfigFile(overrides, options = {}) {
70
+ const configPath = getDefaultConfigPath();
71
+ const directory = path_1.default.dirname(configPath);
72
+ await fs_1.promises.mkdir(directory, { recursive: true });
73
+ const fileExists = await exists(configPath);
74
+ if (fileExists && !options.force) {
75
+ const existing = await readConfigFile(configPath);
76
+ return {
77
+ path: configPath,
78
+ config: existing,
79
+ created: false,
80
+ };
81
+ }
82
+ const nextConfig = {
83
+ webUnlockerApiKey: overrides.webUnlockerApiKey,
84
+ cloudToken: overrides.cloudToken,
85
+ defaultProfileId: overrides.defaultProfileId,
86
+ daemonPort: overrides.daemonPort ?? exports.DEFAULT_DAEMON_PORT,
87
+ };
88
+ await fs_1.promises.writeFile(configPath, JSON.stringify(nextConfig, null, 2) + "\n", "utf8");
89
+ return {
90
+ path: configPath,
91
+ config: nextConfig,
92
+ created: true,
93
+ };
94
+ }
95
+ function requireWebUnlockerKey(config) {
96
+ if (!config.webUnlockerApiKey) {
97
+ throw new errors_1.MissingCredentialError(exports.ENV_NAMES.webUnlockerApiKey, "scraping commands like `gologin-web-access scrape`");
98
+ }
99
+ return config.webUnlockerApiKey;
100
+ }
101
+ function requireCloudToken(config) {
102
+ if (!config.cloudToken) {
103
+ throw new errors_1.MissingCredentialError(exports.ENV_NAMES.cloudToken, "browser commands like `gologin-web-access open`");
104
+ }
105
+ return config.cloudToken;
106
+ }
107
+ function resolveProfileId(config, explicitProfileId) {
108
+ return explicitProfileId || config.defaultProfileId;
109
+ }
110
+ function getRecommendedCredentialStatus(config) {
111
+ const missing = [];
112
+ if (!config.webUnlockerApiKey) {
113
+ missing.push(exports.ENV_NAMES.webUnlockerApiKey);
114
+ }
115
+ if (!config.cloudToken) {
116
+ missing.push(exports.ENV_NAMES.cloudToken);
117
+ }
118
+ if (missing.length === 0) {
119
+ return {
120
+ ready: true,
121
+ missing,
122
+ detail: "complete (Web Unlocker + Cloud Browser configured)",
123
+ };
124
+ }
125
+ return {
126
+ ready: false,
127
+ missing,
128
+ detail: `incomplete - missing ${missing.join(" and ")}`,
129
+ };
130
+ }
131
+ function getMaskedConfigRows(config) {
132
+ const recommended = getRecommendedCredentialStatus(config);
133
+ return [
134
+ {
135
+ label: "Config file",
136
+ value: config.configPath,
137
+ },
138
+ {
139
+ label: exports.ENV_NAMES.webUnlockerApiKey,
140
+ value: describeValue(config.webUnlockerApiKey, config.sources.webUnlockerApiKey),
141
+ },
142
+ {
143
+ label: exports.ENV_NAMES.cloudToken,
144
+ value: describeValue(config.cloudToken, config.sources.cloudToken),
145
+ },
146
+ {
147
+ label: "Recommended setup",
148
+ value: recommended.detail,
149
+ },
150
+ {
151
+ label: exports.ENV_NAMES.defaultProfileId,
152
+ value: describePlainValue(config.defaultProfileId, config.sources.defaultProfileId),
153
+ },
154
+ {
155
+ label: exports.ENV_NAMES.daemonPort,
156
+ value: `${config.daemonPort} (${config.sources.daemonPort})`,
157
+ },
158
+ ];
159
+ }
160
+ async function readConfigFile(configPath) {
161
+ try {
162
+ const raw = await fs_1.promises.readFile(configPath, "utf8");
163
+ const parsed = JSON.parse(raw);
164
+ return {
165
+ webUnlockerApiKey: normalizeString(parsed.webUnlockerApiKey),
166
+ cloudToken: normalizeString(parsed.cloudToken),
167
+ defaultProfileId: normalizeString(parsed.defaultProfileId),
168
+ daemonPort: parsed.daemonPort,
169
+ };
170
+ }
171
+ catch (error) {
172
+ const nodeError = error;
173
+ if (nodeError.code === "ENOENT") {
174
+ return {};
175
+ }
176
+ throw error;
177
+ }
178
+ }
179
+ async function resolveConfigPath() {
180
+ const currentPath = getDefaultConfigPath();
181
+ if (await exists(currentPath)) {
182
+ return currentPath;
183
+ }
184
+ const legacyPath = path_1.default.join(os_1.default.homedir(), LEGACY_CONFIG_DIR, CONFIG_FILENAME);
185
+ if (await exists(legacyPath)) {
186
+ return legacyPath;
187
+ }
188
+ return currentPath;
189
+ }
190
+ function pickString(envValue, fileValue) {
191
+ return normalizeString(envValue) ?? normalizeString(fileValue);
192
+ }
193
+ function pickNumber(envValue, fileValue, fallback) {
194
+ if (normalizeString(envValue)) {
195
+ const parsed = Number(envValue);
196
+ if (!Number.isNaN(parsed) && parsed > 0) {
197
+ return parsed;
198
+ }
199
+ }
200
+ if (typeof fileValue === "number" && fileValue > 0) {
201
+ return fileValue;
202
+ }
203
+ return fallback;
204
+ }
205
+ function normalizeString(value) {
206
+ if (!value) {
207
+ return undefined;
208
+ }
209
+ const trimmed = value.trim();
210
+ return trimmed.length > 0 ? trimmed : undefined;
211
+ }
212
+ function firstEnvValue(primary, legacyNames) {
213
+ const candidates = [primary, ...legacyNames];
214
+ for (const name of candidates) {
215
+ const value = normalizeString(process.env[name]);
216
+ if (value) {
217
+ return value;
218
+ }
219
+ }
220
+ return undefined;
221
+ }
222
+ function resolveSource(envValue, fileValue) {
223
+ if (normalizeString(envValue)) {
224
+ return "env";
225
+ }
226
+ if (normalizeString(fileValue)) {
227
+ return "file";
228
+ }
229
+ return "unset";
230
+ }
231
+ function resolveNumberSource(envValue, fileValue) {
232
+ if (normalizeString(envValue)) {
233
+ return "env";
234
+ }
235
+ if (typeof fileValue === "number") {
236
+ return "file";
237
+ }
238
+ return "default";
239
+ }
240
+ function describeValue(value, source) {
241
+ if (!value) {
242
+ return "missing";
243
+ }
244
+ return `${(0, output_1.maskSecret)(value)} (${source})`;
245
+ }
246
+ function describePlainValue(value, source) {
247
+ if (!value) {
248
+ return "missing";
249
+ }
250
+ return `${value} (${source})`;
251
+ }
252
+ async function exists(targetPath) {
253
+ try {
254
+ await fs_1.promises.access(targetPath);
255
+ return true;
256
+ }
257
+ catch {
258
+ return false;
259
+ }
260
+ }
package/dist/doctor.js ADDED
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runDoctor = runDoctor;
4
+ const config_1 = require("./config");
5
+ const cloudApi_1 = require("./lib/cloudApi");
6
+ const agentCli_1 = require("./lib/agentCli");
7
+ const output_1 = require("./lib/output");
8
+ async function runDoctor(options = {}) {
9
+ const config = await (0, config_1.loadConfig)();
10
+ const checks = [];
11
+ const daemonReachable = await (0, agentCli_1.isDaemonReachable)(config.daemonPort);
12
+ const agentCli = await (0, agentCli_1.inspectAgentCli)();
13
+ const recommended = (0, config_1.getRecommendedCredentialStatus)(config);
14
+ checks.push({
15
+ name: "Web Unlocker API key",
16
+ status: config.webUnlockerApiKey ? "ok" : "warn",
17
+ detail: config.webUnlockerApiKey ? `configured via ${config.sources.webUnlockerApiKey}` : "missing",
18
+ });
19
+ checks.push({
20
+ name: "Cloud Browser token",
21
+ status: config.cloudToken ? "ok" : "warn",
22
+ detail: config.cloudToken ? `configured via ${config.sources.cloudToken}` : "missing",
23
+ });
24
+ checks.push({
25
+ name: "Recommended full setup",
26
+ status: recommended.ready ? "ok" : "warn",
27
+ detail: recommended.ready
28
+ ? "both GOLOGIN_WEB_UNLOCKER_API_KEY and GOLOGIN_CLOUD_TOKEN are configured"
29
+ : `missing ${recommended.missing.join(" and ")}`,
30
+ });
31
+ checks.push({
32
+ name: "Embedded browser runtime",
33
+ status: agentCli ? "ok" : "error",
34
+ detail: agentCli
35
+ ? `${agentCli.source}${agentCli.version ? ` v${agentCli.version}` : ""} at ${agentCli.cwd}`
36
+ : "missing embedded Cloud Browser runtime inside this gologin-web-access install",
37
+ });
38
+ if (!config.defaultProfileId) {
39
+ checks.push({
40
+ name: "Default profile",
41
+ status: "warn",
42
+ detail: "missing",
43
+ });
44
+ }
45
+ else if (!config.cloudToken) {
46
+ checks.push({
47
+ name: "Default profile",
48
+ status: "warn",
49
+ detail: `${config.defaultProfileId} configured, but Cloud Browser token is missing so existence could not be verified`,
50
+ });
51
+ }
52
+ else {
53
+ try {
54
+ const profile = await (0, cloudApi_1.getProfile)(config.defaultProfileId, config.cloudToken);
55
+ checks.push({
56
+ name: "Default profile",
57
+ status: profile ? "ok" : "error",
58
+ detail: profile ? `${profile.id}${profile.name ? ` (${profile.name})` : ""}` : `${config.defaultProfileId} not found`,
59
+ });
60
+ }
61
+ catch (error) {
62
+ const message = error instanceof Error ? error.message : "profile lookup failed";
63
+ checks.push({
64
+ name: "Default profile",
65
+ status: "error",
66
+ detail: message,
67
+ });
68
+ }
69
+ }
70
+ checks.push({
71
+ name: "Daemon",
72
+ status: daemonReachable ? "ok" : "warn",
73
+ detail: daemonReachable
74
+ ? `running on 127.0.0.1:${config.daemonPort}`
75
+ : `not running on 127.0.0.1:${config.daemonPort}`,
76
+ });
77
+ if (options.json) {
78
+ (0, output_1.printJson)({
79
+ configPath: config.configPath,
80
+ agentCli,
81
+ checks,
82
+ });
83
+ return;
84
+ }
85
+ (0, output_1.printText)((0, output_1.formatDoctorChecks)(checks));
86
+ }