camou 0.1.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 (89) hide show
  1. package/README.md +229 -0
  2. package/dist/browser/actions.d.ts +4 -0
  3. package/dist/browser/actions.js +15 -0
  4. package/dist/browser/actions.js.map +1 -0
  5. package/dist/browser/manager.d.ts +85 -0
  6. package/dist/browser/manager.js +300 -0
  7. package/dist/browser/manager.js.map +1 -0
  8. package/dist/browser/snapshot.d.ts +17 -0
  9. package/dist/browser/snapshot.js +93 -0
  10. package/dist/browser/snapshot.js.map +1 -0
  11. package/dist/browser/tabs.d.ts +24 -0
  12. package/dist/browser/tabs.js +8 -0
  13. package/dist/browser/tabs.js.map +1 -0
  14. package/dist/camoufox/config.d.ts +67 -0
  15. package/dist/camoufox/config.js +121 -0
  16. package/dist/camoufox/config.js.map +1 -0
  17. package/dist/camoufox/env.d.ts +3 -0
  18. package/dist/camoufox/env.js +27 -0
  19. package/dist/camoufox/env.js.map +1 -0
  20. package/dist/camoufox/installer.d.ts +24 -0
  21. package/dist/camoufox/installer.js +291 -0
  22. package/dist/camoufox/installer.js.map +1 -0
  23. package/dist/camoufox/launcher.d.ts +22 -0
  24. package/dist/camoufox/launcher.js +105 -0
  25. package/dist/camoufox/launcher.js.map +1 -0
  26. package/dist/camoufox/prefs.d.ts +5 -0
  27. package/dist/camoufox/prefs.js +27 -0
  28. package/dist/camoufox/prefs.js.map +1 -0
  29. package/dist/camoufox/presets.d.ts +14 -0
  30. package/dist/camoufox/presets.js +73 -0
  31. package/dist/camoufox/presets.js.map +1 -0
  32. package/dist/camoufox/registry.d.ts +30 -0
  33. package/dist/camoufox/registry.js +195 -0
  34. package/dist/camoufox/registry.js.map +1 -0
  35. package/dist/camoufox/validation.d.ts +4 -0
  36. package/dist/camoufox/validation.js +103 -0
  37. package/dist/camoufox/validation.js.map +1 -0
  38. package/dist/cli/daemon.d.ts +2 -0
  39. package/dist/cli/daemon.js +59 -0
  40. package/dist/cli/daemon.js.map +1 -0
  41. package/dist/cli/main.d.ts +2 -0
  42. package/dist/cli/main.js +147 -0
  43. package/dist/cli/main.js.map +1 -0
  44. package/dist/cli/output.d.ts +1 -0
  45. package/dist/cli/output.js +108 -0
  46. package/dist/cli/output.js.map +1 -0
  47. package/dist/cli/program.d.ts +42 -0
  48. package/dist/cli/program.js +214 -0
  49. package/dist/cli/program.js.map +1 -0
  50. package/dist/daemon/daemon.d.ts +12 -0
  51. package/dist/daemon/daemon.js +36 -0
  52. package/dist/daemon/daemon.js.map +1 -0
  53. package/dist/daemon/main.d.ts +2 -0
  54. package/dist/daemon/main.js +28 -0
  55. package/dist/daemon/main.js.map +1 -0
  56. package/dist/daemon/router.d.ts +7 -0
  57. package/dist/daemon/router.js +43 -0
  58. package/dist/daemon/router.js.map +1 -0
  59. package/dist/daemon/runtime.d.ts +11 -0
  60. package/dist/daemon/runtime.js +54 -0
  61. package/dist/daemon/runtime.js.map +1 -0
  62. package/dist/doctor/diagnostics.d.ts +38 -0
  63. package/dist/doctor/diagnostics.js +152 -0
  64. package/dist/doctor/diagnostics.js.map +1 -0
  65. package/dist/ipc/client.d.ts +6 -0
  66. package/dist/ipc/client.js +63 -0
  67. package/dist/ipc/client.js.map +1 -0
  68. package/dist/ipc/protocol.d.ts +775 -0
  69. package/dist/ipc/protocol.js +128 -0
  70. package/dist/ipc/protocol.js.map +1 -0
  71. package/dist/ipc/server.d.ts +10 -0
  72. package/dist/ipc/server.js +99 -0
  73. package/dist/ipc/server.js.map +1 -0
  74. package/dist/state/paths.d.ts +32 -0
  75. package/dist/state/paths.js +121 -0
  76. package/dist/state/paths.js.map +1 -0
  77. package/dist/state/store.d.ts +4 -0
  78. package/dist/state/store.js +30 -0
  79. package/dist/state/store.js.map +1 -0
  80. package/dist/util/errors.d.ts +45 -0
  81. package/dist/util/errors.js +82 -0
  82. package/dist/util/errors.js.map +1 -0
  83. package/dist/util/log.d.ts +19 -0
  84. package/dist/util/log.js +71 -0
  85. package/dist/util/log.js.map +1 -0
  86. package/dist/util/platform.d.ts +12 -0
  87. package/dist/util/platform.js +44 -0
  88. package/dist/util/platform.js.map +1 -0
  89. package/package.json +58 -0
@@ -0,0 +1,195 @@
1
+ import path from 'node:path';
2
+ import { readFile, readdir, stat } from 'node:fs/promises';
3
+ import { getPlatformTarget } from '../util/platform.js';
4
+ import { BrowserNotInstalledError } from '../util/errors.js';
5
+ import { readJsonFile, writeJsonFile } from '../state/store.js';
6
+ function createEmptyRegistry() {
7
+ return {
8
+ installs: {},
9
+ };
10
+ }
11
+ export async function loadBrowserRegistry(paths) {
12
+ return readJsonFile(paths.browserRegistryFile, createEmptyRegistry());
13
+ }
14
+ async function saveSharedCamoufoxConfig(paths, config) {
15
+ await writeJsonFile(paths.camoufoxConfigFile, config);
16
+ }
17
+ async function loadSharedCamoufoxConfig(paths) {
18
+ return readJsonFile(paths.camoufoxConfigFile, {});
19
+ }
20
+ async function loadSharedBrowserInstalls(paths) {
21
+ const target = getPlatformTarget();
22
+ const installs = {};
23
+ try {
24
+ const repoEntries = await readdir(paths.browsersDir, { withFileTypes: true });
25
+ for (const repoEntry of repoEntries) {
26
+ if (!repoEntry.isDirectory()) {
27
+ continue;
28
+ }
29
+ const repoRoot = path.join(paths.browsersDir, repoEntry.name);
30
+ const versionEntries = await readdir(repoRoot, { withFileTypes: true });
31
+ for (const versionEntry of versionEntries) {
32
+ if (!versionEntry.isDirectory()) {
33
+ continue;
34
+ }
35
+ const rootDir = path.join(repoRoot, versionEntry.name);
36
+ const versionJsonPath = path.join(rootDir, 'version.json');
37
+ let metadata;
38
+ try {
39
+ metadata = JSON.parse(await readFile(versionJsonPath, 'utf8'));
40
+ }
41
+ catch {
42
+ continue;
43
+ }
44
+ const build = metadata.build ?? metadata.release ?? metadata.tag;
45
+ const version = metadata.version && build ? `${metadata.version}-${build}` : versionEntry.name;
46
+ const executablePath = path.join(rootDir, target.executableRelativePath);
47
+ const rootStats = await stat(rootDir).catch(() => undefined);
48
+ installs[version] = {
49
+ version,
50
+ tag: build ? `v${version}` : version,
51
+ sourceRepo: repoEntry.name,
52
+ assetName: '',
53
+ assetUrl: '',
54
+ rootDir,
55
+ executablePath,
56
+ installedAt: rootStats?.mtime.toISOString() ?? new Date(0).toISOString(),
57
+ platform: target.os,
58
+ arch: target.arch,
59
+ };
60
+ }
61
+ }
62
+ }
63
+ catch {
64
+ return { installs: {} };
65
+ }
66
+ const sharedConfig = await loadSharedCamoufoxConfig(paths);
67
+ const activeVersion = sharedConfig.active_version ? path.basename(sharedConfig.active_version) : undefined;
68
+ return {
69
+ currentVersion: activeVersion && installs[activeVersion] ? activeVersion : pickLatestVersion(Object.keys(installs)),
70
+ installs,
71
+ };
72
+ }
73
+ async function loadEffectiveBrowserRegistry(paths) {
74
+ const [localRegistry, sharedRegistry] = await Promise.all([
75
+ loadBrowserRegistry(paths),
76
+ loadSharedBrowserInstalls(paths),
77
+ ]);
78
+ const installs = {
79
+ ...sharedRegistry.installs,
80
+ ...localRegistry.installs,
81
+ };
82
+ const currentVersion = resolveCurrentVersion(localRegistry.currentVersion, sharedRegistry.currentVersion, installs);
83
+ return {
84
+ currentVersion,
85
+ installs,
86
+ };
87
+ }
88
+ function resolveCurrentVersion(localCurrentVersion, sharedCurrentVersion, installs) {
89
+ if (localCurrentVersion && installs[localCurrentVersion]) {
90
+ return localCurrentVersion;
91
+ }
92
+ if (sharedCurrentVersion && installs[sharedCurrentVersion]) {
93
+ return sharedCurrentVersion;
94
+ }
95
+ return pickLatestVersion(Object.keys(installs));
96
+ }
97
+ function pickLatestVersion(versions) {
98
+ return versions.sort((left, right) => left.localeCompare(right, undefined, { numeric: true })).at(-1);
99
+ }
100
+ function listSortedInstalls(installs) {
101
+ return Object.values(installs).sort((left, right) => right.version.localeCompare(left.version, undefined, { numeric: true }));
102
+ }
103
+ function toSharedActiveVersion(paths, rootDir) {
104
+ const relativePath = path.relative(paths.camoufoxCacheDir, rootDir);
105
+ if (!relativePath || relativePath.startsWith('..')) {
106
+ return undefined;
107
+ }
108
+ return relativePath.split(path.sep).join('/');
109
+ }
110
+ async function updateSharedCurrentBrowser(paths, record) {
111
+ const config = await loadSharedCamoufoxConfig(paths);
112
+ config.active_version = record ? toSharedActiveVersion(paths, record.rootDir) ?? null : null;
113
+ await saveSharedCamoufoxConfig(paths, config);
114
+ }
115
+ export async function saveBrowserRegistry(paths, registry) {
116
+ await writeJsonFile(paths.browserRegistryFile, registry);
117
+ }
118
+ export async function setInstalledBrowser(paths, record, makeCurrent = true) {
119
+ const registry = await loadBrowserRegistry(paths);
120
+ registry.installs[record.version] = record;
121
+ if (makeCurrent || !registry.currentVersion) {
122
+ registry.currentVersion = record.version;
123
+ }
124
+ await saveBrowserRegistry(paths, registry);
125
+ if (registry.currentVersion === record.version) {
126
+ await updateSharedCurrentBrowser(paths, record);
127
+ }
128
+ return registry;
129
+ }
130
+ export async function setCurrentBrowser(paths, version) {
131
+ const [registry, effectiveRegistry] = await Promise.all([
132
+ loadBrowserRegistry(paths),
133
+ loadEffectiveBrowserRegistry(paths),
134
+ ]);
135
+ if (!effectiveRegistry.installs[version]) {
136
+ throw new BrowserNotInstalledError(`Camoufox version ${version} is not installed.`);
137
+ }
138
+ registry.currentVersion = version;
139
+ await saveBrowserRegistry(paths, registry);
140
+ await updateSharedCurrentBrowser(paths, effectiveRegistry.installs[version]);
141
+ return {
142
+ currentVersion: version,
143
+ installs: effectiveRegistry.installs,
144
+ };
145
+ }
146
+ export async function removeInstalledBrowser(paths, version) {
147
+ const [registry, sharedRegistry] = await Promise.all([
148
+ loadBrowserRegistry(paths),
149
+ loadSharedBrowserInstalls(paths),
150
+ ]);
151
+ delete registry.installs[version];
152
+ const remaining = {
153
+ ...sharedRegistry.installs,
154
+ ...registry.installs,
155
+ };
156
+ delete remaining[version];
157
+ if (registry.currentVersion === version) {
158
+ registry.currentVersion = pickLatestVersion(Object.keys(remaining));
159
+ }
160
+ await saveBrowserRegistry(paths, registry);
161
+ await updateSharedCurrentBrowser(paths, registry.currentVersion ? remaining[registry.currentVersion] : undefined);
162
+ return {
163
+ currentVersion: registry.currentVersion,
164
+ installs: remaining,
165
+ };
166
+ }
167
+ export async function resolveInstalledBrowser(paths, version) {
168
+ const registry = await loadEffectiveBrowserRegistry(paths);
169
+ const selectedVersion = version ?? registry.currentVersion;
170
+ if (!selectedVersion) {
171
+ return undefined;
172
+ }
173
+ return registry.installs[selectedVersion];
174
+ }
175
+ export async function listInstalledBrowsers(paths) {
176
+ const registry = await loadEffectiveBrowserRegistry(paths);
177
+ return {
178
+ currentVersion: registry.currentVersion,
179
+ installs: listSortedInstalls(registry.installs),
180
+ };
181
+ }
182
+ export async function requireInstalledBrowser(paths, version) {
183
+ const record = await resolveInstalledBrowser(paths, version);
184
+ if (!record) {
185
+ throw new BrowserNotInstalledError();
186
+ }
187
+ try {
188
+ await stat(record.executablePath);
189
+ }
190
+ catch {
191
+ throw new BrowserNotInstalledError(`Camoufox is registered at ${record.executablePath}, but the executable is missing. Run \`camou install ${record.version}\` again.`);
192
+ }
193
+ return record;
194
+ }
195
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/camoufox/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ type PropertyType = 'str' | 'int' | 'uint' | 'double' | 'bool' | 'array' | 'dict';
2
+ export declare function validateCamouConfigValue(value: unknown, expectedType: PropertyType): boolean;
3
+ export declare function validateCamouConfig(config: Record<string, unknown>, browserRootDir: string): Promise<void>;
4
+ export {};
@@ -0,0 +1,103 @@
1
+ import path from 'node:path';
2
+ import { readdir, readFile } from 'node:fs/promises';
3
+ import { z } from 'zod';
4
+ import { ValidationError } from '../util/errors.js';
5
+ const propertyDefinitionSchema = z.object({
6
+ property: z.string(),
7
+ type: z.string(),
8
+ });
9
+ const propertiesSchema = z.array(propertyDefinitionSchema);
10
+ const KNOWN_PROPERTY_FILES = [
11
+ 'properties.json',
12
+ path.join('Camoufox.app', 'Contents', 'Resources', 'properties.json'),
13
+ ];
14
+ async function fileExists(filePath) {
15
+ try {
16
+ await readFile(filePath);
17
+ return true;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ async function findPropertiesFile(rootDir) {
24
+ for (const relativePath of KNOWN_PROPERTY_FILES) {
25
+ const fullPath = path.join(rootDir, relativePath);
26
+ if (await fileExists(fullPath)) {
27
+ return fullPath;
28
+ }
29
+ }
30
+ const queue = [rootDir];
31
+ while (queue.length > 0) {
32
+ const current = queue.shift();
33
+ if (!current) {
34
+ continue;
35
+ }
36
+ const entries = await readdir(current, { withFileTypes: true }).catch(() => []);
37
+ for (const entry of entries) {
38
+ const fullPath = path.join(current, entry.name);
39
+ if (entry.isDirectory()) {
40
+ queue.push(fullPath);
41
+ continue;
42
+ }
43
+ if (entry.name === 'properties.json') {
44
+ return fullPath;
45
+ }
46
+ }
47
+ }
48
+ return undefined;
49
+ }
50
+ async function loadPropertyTypes(rootDir) {
51
+ const propertiesFile = await findPropertiesFile(rootDir);
52
+ if (!propertiesFile) {
53
+ return undefined;
54
+ }
55
+ const raw = await readFile(propertiesFile, 'utf8');
56
+ const parsed = propertiesSchema.parse(JSON.parse(raw));
57
+ return Object.fromEntries(parsed.map((item) => [item.property, item.type]));
58
+ }
59
+ export function validateCamouConfigValue(value, expectedType) {
60
+ switch (expectedType) {
61
+ case 'str':
62
+ return typeof value === 'string';
63
+ case 'int':
64
+ return Number.isInteger(value);
65
+ case 'uint':
66
+ return Number.isInteger(value) && Number(value) >= 0;
67
+ case 'double':
68
+ return typeof value === 'number';
69
+ case 'bool':
70
+ return typeof value === 'boolean';
71
+ case 'array':
72
+ return Array.isArray(value);
73
+ case 'dict':
74
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
75
+ default:
76
+ return true;
77
+ }
78
+ }
79
+ export async function validateCamouConfig(config, browserRootDir) {
80
+ if (Object.keys(config).length === 0) {
81
+ return;
82
+ }
83
+ let propertyTypes;
84
+ try {
85
+ propertyTypes = await loadPropertyTypes(browserRootDir);
86
+ }
87
+ catch (error) {
88
+ throw new ValidationError('Unable to read Camoufox property definitions for config validation.', undefined, error);
89
+ }
90
+ if (!propertyTypes) {
91
+ return;
92
+ }
93
+ for (const [key, value] of Object.entries(config)) {
94
+ const expectedType = propertyTypes[key];
95
+ if (!expectedType) {
96
+ throw new ValidationError(`Unknown Camoufox property: ${key}`);
97
+ }
98
+ if (!validateCamouConfigValue(value, expectedType)) {
99
+ throw new ValidationError(`Invalid type for Camoufox property ${key}. Expected ${expectedType}, received ${Array.isArray(value) ? 'array' : typeof value}.`);
100
+ }
101
+ }
102
+ }
103
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/camoufox/validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { CamoucliPaths } from '../state/paths.js';
2
+ export declare function ensureDaemonRunning(paths: CamoucliPaths, verbose: boolean): Promise<void>;
@@ -0,0 +1,59 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { spawn } from 'node:child_process';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { cleanupStaleDaemonArtifacts, readDaemonPid } from '../daemon/runtime.js';
5
+ import { DaemonStartError } from '../util/errors.js';
6
+ import { pingDaemon } from '../ipc/client.js';
7
+ function getDaemonSpawnConfig() {
8
+ const jsPath = fileURLToPath(new URL('../daemon/main.js', import.meta.url));
9
+ if (existsSync(jsPath)) {
10
+ return {
11
+ command: process.execPath,
12
+ args: [jsPath],
13
+ };
14
+ }
15
+ const tsPath = fileURLToPath(new URL('../daemon/main.ts', import.meta.url));
16
+ return {
17
+ command: process.execPath,
18
+ args: ['--import', 'tsx', tsPath],
19
+ };
20
+ }
21
+ function sleep(ms) {
22
+ return new Promise((resolve) => setTimeout(resolve, ms));
23
+ }
24
+ export async function ensureDaemonRunning(paths, verbose) {
25
+ if (await pingDaemon(paths)) {
26
+ return;
27
+ }
28
+ const artifactState = await cleanupStaleDaemonArtifacts(paths);
29
+ if (artifactState.pidAlive) {
30
+ for (let attempt = 0; attempt < 8; attempt += 1) {
31
+ await sleep(250);
32
+ if (await pingDaemon(paths)) {
33
+ return;
34
+ }
35
+ }
36
+ throw new DaemonStartError(`Daemon process ${artifactState.pid} exists but is not responding. Remove ${paths.daemonPidFile} or stop the stale process before retrying.`);
37
+ }
38
+ const spawnConfig = getDaemonSpawnConfig();
39
+ const child = spawn(spawnConfig.command, spawnConfig.args, {
40
+ detached: true,
41
+ stdio: 'ignore',
42
+ env: {
43
+ ...process.env,
44
+ CAMOUCLI_VERBOSE: verbose ? '1' : '0',
45
+ },
46
+ });
47
+ child.unref();
48
+ for (let attempt = 0; attempt < 40; attempt += 1) {
49
+ await sleep(250);
50
+ if (await pingDaemon(paths)) {
51
+ return;
52
+ }
53
+ }
54
+ const pid = await readDaemonPid(paths);
55
+ throw new DaemonStartError(pid
56
+ ? `Failed to start the camou daemon. See ${paths.daemonLogFile} and stop process ${pid} if it is stuck.`
57
+ : `Failed to start the camou daemon. See ${paths.daemonLogFile} for details.`);
58
+ }
59
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/cli/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+ import { CommanderError } from 'commander';
3
+ import { doctorCamoufox, inspectCamoufoxInstall, installCamoufox, removeCamoufox } from '../camoufox/installer.js';
4
+ import { listCamoufoxPresets } from '../camoufox/presets.js';
5
+ import { listInstalledBrowsers, requireInstalledBrowser, resolveInstalledBrowser, setCurrentBrowser } from '../camoufox/registry.js';
6
+ import { ensureBasePaths, getCamoucliPaths } from '../state/paths.js';
7
+ import { BrowserNotInstalledError, ValidationError, getExitCode, toErrorPayload } from '../util/errors.js';
8
+ import { Logger } from '../util/log.js';
9
+ import { sendDaemonRequest } from '../ipc/client.js';
10
+ import { ensureDaemonRunning } from './daemon.js';
11
+ import { printOutput } from './output.js';
12
+ import { createProgram } from './program.js';
13
+ function getLogger(verbose = false) {
14
+ return new Logger({ name: 'cli', verbose, mirrorToStderr: verbose });
15
+ }
16
+ async function runDaemonAction(action, payload, options) {
17
+ const paths = getCamoucliPaths();
18
+ await ensureBasePaths(paths);
19
+ await ensureDaemonRunning(paths, options.verbose ?? false);
20
+ const data = await sendDaemonRequest(paths, payload);
21
+ printOutput(action, data, options.json ?? false);
22
+ }
23
+ function wantsJsonOutput(argv) {
24
+ return argv.includes('--json');
25
+ }
26
+ function normalizeCliError(error) {
27
+ if (error instanceof CommanderError) {
28
+ return new ValidationError(error.message.replace(/^error:\s*/i, '').trim() || 'Invalid command input.');
29
+ }
30
+ return error;
31
+ }
32
+ function printCliError(error, asJson) {
33
+ const normalized = normalizeCliError(error);
34
+ if (asJson) {
35
+ process.stderr.write(`${JSON.stringify({
36
+ success: false,
37
+ error: toErrorPayload(normalized),
38
+ exitCode: getExitCode(normalized),
39
+ }, null, 2)}\n`);
40
+ return;
41
+ }
42
+ process.stderr.write(`${normalized instanceof Error ? normalized.message : String(normalized)}\n`);
43
+ }
44
+ async function main(argv = process.argv) {
45
+ const asJson = wantsJsonOutput(argv);
46
+ const program = createProgram({
47
+ onInstall: async (version, options) => {
48
+ const paths = getCamoucliPaths();
49
+ const logger = getLogger(options.verbose);
50
+ await ensureBasePaths(paths);
51
+ const installOptions = {
52
+ ...(version ? { version } : {}),
53
+ ...(options.force !== undefined ? { force: options.force } : {}),
54
+ logger,
55
+ };
56
+ const release = await installCamoufox(paths, installOptions);
57
+ const inspection = await inspectCamoufoxInstall(paths, release.version, logger);
58
+ printOutput('install', {
59
+ version: release.version,
60
+ tag: release.tag,
61
+ playwrightCoreVersion: inspection.playwrightCoreVersion,
62
+ launchCheck: inspection.launchCheck,
63
+ }, options.json ?? false);
64
+ },
65
+ onRemove: async (version, options) => {
66
+ const paths = getCamoucliPaths();
67
+ const logger = getLogger(options.verbose);
68
+ const installed = version ? await resolveInstalledBrowser(paths, version) : await resolveInstalledBrowser(paths);
69
+ if (!installed) {
70
+ throw new BrowserNotInstalledError('No installed Camoufox version found to remove.');
71
+ }
72
+ await removeCamoufox(paths, installed.version, logger);
73
+ printOutput('remove', { removed: installed.version }, options.json ?? false);
74
+ },
75
+ onUse: async (version, options) => {
76
+ const paths = getCamoucliPaths();
77
+ const logger = getLogger(options.verbose);
78
+ await ensureBasePaths(paths);
79
+ const registry = await setCurrentBrowser(paths, version);
80
+ const selectedVersion = registry.currentVersion ?? version;
81
+ const selected = await requireInstalledBrowser(paths, selectedVersion);
82
+ const inspection = await inspectCamoufoxInstall(paths, selected.version, logger);
83
+ printOutput('use', {
84
+ version: selected.version,
85
+ path: selected.executablePath,
86
+ playwrightCoreVersion: inspection.playwrightCoreVersion,
87
+ launchCheck: inspection.launchCheck,
88
+ }, options.json ?? false);
89
+ },
90
+ onVersions: async (options) => {
91
+ const paths = getCamoucliPaths();
92
+ await ensureBasePaths(paths);
93
+ const installedBrowsers = await listInstalledBrowsers(paths);
94
+ printOutput('versions', {
95
+ currentVersion: installedBrowsers.currentVersion,
96
+ installedVersions: installedBrowsers.installs.map((install) => ({
97
+ version: install.version,
98
+ current: install.version === installedBrowsers.currentVersion,
99
+ sourceRepo: install.sourceRepo,
100
+ path: install.executablePath,
101
+ })),
102
+ }, options.json ?? false);
103
+ },
104
+ onPresets: async (options) => {
105
+ printOutput('presets', {
106
+ presets: listCamoufoxPresets().map((preset) => ({
107
+ name: preset.name,
108
+ description: preset.description,
109
+ })),
110
+ }, options.json ?? false);
111
+ },
112
+ onPath: async (options) => {
113
+ const browser = await requireInstalledBrowser(getCamoucliPaths());
114
+ printOutput('path', { path: browser.executablePath }, options.json ?? false);
115
+ },
116
+ onVersion: async (options) => {
117
+ const browser = await requireInstalledBrowser(getCamoucliPaths());
118
+ printOutput('version', { version: browser.version }, options.json ?? false);
119
+ },
120
+ onDoctor: async (options) => {
121
+ const paths = getCamoucliPaths();
122
+ const logger = getLogger(options.verbose);
123
+ await ensureBasePaths(paths);
124
+ const data = await doctorCamoufox(paths, logger);
125
+ printOutput('doctor', data, options.json ?? false);
126
+ },
127
+ onDaemonAction: runDaemonAction,
128
+ }, { quietErrors: asJson });
129
+ try {
130
+ await program.parseAsync(argv);
131
+ return 0;
132
+ }
133
+ catch (error) {
134
+ if (error instanceof CommanderError && (error.code === 'commander.helpDisplayed' || error.code === 'commander.version')) {
135
+ return 0;
136
+ }
137
+ printCliError(error, asJson);
138
+ return getExitCode(normalizeCliError(error));
139
+ }
140
+ }
141
+ main().then((exitCode) => {
142
+ process.exit(exitCode);
143
+ }).catch((error) => {
144
+ printCliError(error, wantsJsonOutput(process.argv));
145
+ process.exit(getExitCode(normalizeCliError(error)));
146
+ });
147
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function printOutput(action: string, data: unknown, asJson: boolean): void;