semrush-cli 0.4.0 → 0.5.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.
- package/README.md +169 -165
- package/assets/demo-keywords.gif +0 -0
- package/assets/demo-keywords.png +0 -0
- package/assets/demo-projects.gif +0 -0
- package/assets/demo-projects.png +0 -0
- package/assets/logo-lockup.svg +10 -0
- package/assets/logo.png +0 -0
- package/assets/logo.svg +4 -8
- package/dist/{auth-CHCXZZpR.js → auth-CrYOA8QT.js} +4 -4
- package/dist/{auth-CHCXZZpR.js.map → auth-CrYOA8QT.js.map} +1 -1
- package/dist/{browser-layer-DgW0vW92.js → browser-layer-gdm03TCV.js} +6 -6
- package/dist/browser-layer-gdm03TCV.js.map +1 -0
- package/dist/cli.js +18 -18
- package/dist/cli.js.map +1 -1
- package/dist/{errors-BjuHkMt_.js → errors-DNn_XeoU.js} +2 -2
- package/dist/errors-DNn_XeoU.js.map +1 -0
- package/dist/{mcp-BPznArmB.js → mcp-DqvGEnxx.js} +6 -6
- package/dist/{mcp-BPznArmB.js.map → mcp-DqvGEnxx.js.map} +1 -1
- package/dist/{session-layer-DJzN9Xx2.js → session-layer-Bq5OpnR5.js} +5 -5
- package/dist/{session-layer-DJzN9Xx2.js.map → session-layer-Bq5OpnR5.js.map} +1 -1
- package/dist/{validation-CenS7xI_.js → validation-B3hdOxdH.js} +4 -4
- package/dist/validation-B3hdOxdH.js.map +1 -0
- package/dist/validation-B8xjCr9w.js +4 -0
- package/package.json +2 -2
- package/dist/browser-layer-DgW0vW92.js.map +0 -1
- package/dist/errors-BjuHkMt_.js.map +0 -1
- package/dist/validation-B5M_ocvQ.js +0 -4
- package/dist/validation-CenS7xI_.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { c as version, i as previewMutation, n as SessionError, o as reports } from "./errors-
|
|
3
|
-
import { a as Sessions, i as sessionsLive, n as defaultStateDirectory, r as origin, t as defaultDaemonURL } from "./session-layer-
|
|
2
|
+
import { c as version, i as previewMutation, n as SessionError, o as reports } from "./errors-DNn_XeoU.js";
|
|
3
|
+
import { a as Sessions, i as sessionsLive, n as defaultStateDirectory, r as origin, t as defaultDaemonURL } from "./session-layer-Bq5OpnR5.js";
|
|
4
4
|
import { Command, CommanderError, InvalidArgumentError, Option } from "commander";
|
|
5
5
|
import { Effect } from "effect";
|
|
6
6
|
import { chmod, mkdir, open, writeFile } from "node:fs/promises";
|
|
@@ -13,7 +13,7 @@ import { fileURLToPath } from "node:url";
|
|
|
13
13
|
//#region src/daemon.ts
|
|
14
14
|
const exec = promisify(execFile);
|
|
15
15
|
const daemonPath = () => fileURLToPath(new URL(`./daemon/galleton-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`, import.meta.url));
|
|
16
|
-
const failed = () => new SessionError({ message: "Local daemon setup failed. Check semrush
|
|
16
|
+
const failed = () => new SessionError({ message: "Local daemon setup failed. Check semrush daemon start and the private daemon.log in the state directory." });
|
|
17
17
|
const io = (run) => Effect.tryPromise({
|
|
18
18
|
try: run,
|
|
19
19
|
catch: failed
|
|
@@ -123,8 +123,8 @@ const installBrowser = Effect.fn("Browser.install")(() => io(async () => {
|
|
|
123
123
|
//#endregion
|
|
124
124
|
//#region src/cli.ts
|
|
125
125
|
const interruption = new AbortController();
|
|
126
|
-
const cli = new Command().name("semrush
|
|
127
|
-
cli.addHelpText("after", "\nExamples:\n semrush
|
|
126
|
+
const cli = new Command().name("semrush").description("Semrush research through your signed-in account. CLI + MCP, powered by Effect and Galleton.").version(version).exitOverride().showHelpAfterError().option("--json", "Emit compact JSON").option("--no-input", "Never prompt for terminal input").option("--no-color", "Disable terminal colors");
|
|
127
|
+
cli.addHelpText("after", "\nExamples:\n semrush setup\n semrush auth login\n semrush domain-overview --domain openai.com --json\n semrush keyword-magic --keyword \"email marketing\" --page-size 20 --json\n semrush mcp\n\nDocumentation: https://semrush.micr.dev\n");
|
|
128
128
|
function output(value, command) {
|
|
129
129
|
process.stdout.write(JSON.stringify(value, null, command.optsWithGlobals().json ? void 0 : 2) + "\n");
|
|
130
130
|
}
|
|
@@ -132,7 +132,7 @@ async function execute(program, command) {
|
|
|
132
132
|
await Effect.runPromise(Effect.scoped(program).pipe(Effect.match({
|
|
133
133
|
onSuccess: (value) => output(value, command),
|
|
134
134
|
onFailure: (error) => {
|
|
135
|
-
process.stderr.write(`semrush
|
|
135
|
+
process.stderr.write(`semrush: ${error.message}\n`);
|
|
136
136
|
process.exitCode = "name" in error && error.name === "UsageError" ? 2 : 1;
|
|
137
137
|
}
|
|
138
138
|
})), { signal: interruption.signal });
|
|
@@ -175,7 +175,7 @@ for (const [name, definition] of Object.entries(reports)) {
|
|
|
175
175
|
report.addOption(option);
|
|
176
176
|
}
|
|
177
177
|
report.action(async (_options, command) => {
|
|
178
|
-
const { parseReport } = await import("./validation-
|
|
178
|
+
const { parseReport } = await import("./validation-B8xjCr9w.js");
|
|
179
179
|
const options = command.opts();
|
|
180
180
|
const input = Object.fromEntries(Object.keys(schema.properties).map((key) => [key, options[key.replace(/_([a-z])/g, (_match, char) => char.toUpperCase())]]).filter(([, value]) => value !== void 0));
|
|
181
181
|
const parsed = await Effect.runPromise(parseReport(name, input).pipe(Effect.match({
|
|
@@ -189,7 +189,7 @@ for (const [name, definition] of Object.entries(reports)) {
|
|
|
189
189
|
})
|
|
190
190
|
})));
|
|
191
191
|
if (!parsed.ok) {
|
|
192
|
-
process.stderr.write(`semrush
|
|
192
|
+
process.stderr.write(`semrush: ${parsed.error.message}\n`);
|
|
193
193
|
process.exitCode = 2;
|
|
194
194
|
return;
|
|
195
195
|
}
|
|
@@ -198,7 +198,7 @@ for (const [name, definition] of Object.entries(reports)) {
|
|
|
198
198
|
output(preview, command);
|
|
199
199
|
return;
|
|
200
200
|
}
|
|
201
|
-
const { appLayer } = await import("./mcp-
|
|
201
|
+
const { appLayer } = await import("./mcp-DqvGEnxx.js");
|
|
202
202
|
const { Semrush } = await import("./browser-service-CL8YPaIT.js");
|
|
203
203
|
await execute(Effect.gen(function* () {
|
|
204
204
|
return yield* (yield* Semrush).report(parsed.value);
|
|
@@ -210,21 +210,21 @@ cli.command("setup").description("Install Chromium and initialize the private Ga
|
|
|
210
210
|
yield* installBrowser();
|
|
211
211
|
return {
|
|
212
212
|
...yield* startDaemon(),
|
|
213
|
-
next: "semrush
|
|
213
|
+
next: "semrush auth login"
|
|
214
214
|
};
|
|
215
215
|
}), command));
|
|
216
216
|
const daemon = cli.command("daemon").description("Control the CLI-owned Galleton daemon");
|
|
217
217
|
daemon.command("start").description("Start the private daemon").action((_options, command) => execute(startDaemon(), command));
|
|
218
218
|
daemon.command("stop").description("Gracefully stop the private daemon").action((_options, command) => execute(stopDaemon(), command));
|
|
219
219
|
const auth = cli.command("auth").description("Store and inspect your Semrush session in Galleton");
|
|
220
|
-
auth.command("import").description("Import a signed-in local Chromium context").requiredOption("--cdp-url <url>", "Loopback CDP URL, e.g. http://127.0.0.1:9234").action(async (options, command) => execute((await import("./auth-
|
|
221
|
-
auth.command("login").description("Sign in through an isolated visible Chromium window").action(async (_options, command) => execute((await import("./auth-
|
|
220
|
+
auth.command("import").description("Import a signed-in local Chromium context").requiredOption("--cdp-url <url>", "Loopback CDP URL, e.g. http://127.0.0.1:9234").action(async (options, command) => execute((await import("./auth-CrYOA8QT.js")).importBrowser(options.cdpUrl).pipe(Effect.provide(sessionsLive)), command));
|
|
221
|
+
auth.command("login").description("Sign in through an isolated visible Chromium window").action(async (_options, command) => execute((await import("./auth-CrYOA8QT.js")).login().pipe(Effect.provide(sessionsLive)), command));
|
|
222
222
|
auth.command("status").description("Show session metadata without credentials").option("--check", "Verify the stored session against Semrush").action((options, command) => execute(Effect.gen(function* () {
|
|
223
223
|
const status = yield* (yield* Sessions).status();
|
|
224
224
|
if (options.check) {
|
|
225
|
-
const { appLayer } = yield* Effect.promise(() => import("./mcp-
|
|
225
|
+
const { appLayer } = yield* Effect.promise(() => import("./mcp-DqvGEnxx.js"));
|
|
226
226
|
const { Semrush } = yield* Effect.promise(() => import("./browser-service-CL8YPaIT.js"));
|
|
227
|
-
const { parseReport } = yield* Effect.promise(() => import("./validation-
|
|
227
|
+
const { parseReport } = yield* Effect.promise(() => import("./validation-B8xjCr9w.js"));
|
|
228
228
|
yield* Effect.gen(function* () {
|
|
229
229
|
return yield* (yield* Semrush).report(yield* parseReport("account_status", {}));
|
|
230
230
|
}).pipe(Effect.provide(appLayer));
|
|
@@ -244,9 +244,9 @@ auth.command("logout").description("Forget this CLI session from Galleton").acti
|
|
|
244
244
|
};
|
|
245
245
|
}).pipe(Effect.provide(sessionsLive)), command));
|
|
246
246
|
cli.command("doctor").description("Check Galleton, browser and authenticated report access").action(async (_options, command) => {
|
|
247
|
-
const { appLayer } = await import("./mcp-
|
|
247
|
+
const { appLayer } = await import("./mcp-DqvGEnxx.js");
|
|
248
248
|
const { Semrush } = await import("./browser-service-CL8YPaIT.js");
|
|
249
|
-
const { parseReport } = await import("./validation-
|
|
249
|
+
const { parseReport } = await import("./validation-B8xjCr9w.js");
|
|
250
250
|
await execute(Effect.gen(function* () {
|
|
251
251
|
yield* (yield* Semrush).report(yield* parseReport("account_status", {}));
|
|
252
252
|
return {
|
|
@@ -257,7 +257,7 @@ cli.command("doctor").description("Check Galleton, browser and authenticated rep
|
|
|
257
257
|
};
|
|
258
258
|
}).pipe(Effect.provide(appLayer)), command);
|
|
259
259
|
});
|
|
260
|
-
cli.command("mcp").description("Run the MCP server over stdio").action(async () => (await import("./mcp-
|
|
260
|
+
cli.command("mcp").description("Run the MCP server over stdio").action(async () => (await import("./mcp-DqvGEnxx.js")).serveMcp());
|
|
261
261
|
process.once("SIGINT", () => {
|
|
262
262
|
if (process.argv.includes("mcp")) return;
|
|
263
263
|
process.exitCode = 130;
|
|
@@ -269,7 +269,7 @@ try {
|
|
|
269
269
|
if (interruption.signal.aborted) process.exitCode = 130;
|
|
270
270
|
else if (error instanceof CommanderError) process.exitCode = error.exitCode === 0 ? 0 : 2;
|
|
271
271
|
else {
|
|
272
|
-
process.stderr.write("semrush
|
|
272
|
+
process.stderr.write("semrush: Unexpected failure. Run semrush doctor and report the failing command at https://github.com/Microck/semrush-cli/issues.\n");
|
|
273
273
|
process.exitCode = 1;
|
|
274
274
|
}
|
|
275
275
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":["delay","cli","schema: { properties: Record<string, Property>; required?: string[] }","CliOption"],"sources":["../src/daemon.ts","../src/cli.ts"],"sourcesContent":["import { spawn, execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { setTimeout as delay } from 'node:timers/promises';\nimport { chmod, mkdir, open, writeFile } from 'node:fs/promises';\nimport { fileURLToPath } from 'node:url';\nimport { join } from 'node:path';\nimport { Effect } from 'effect';\nimport { defaultStateDirectory, defaultDaemonURL, origin } from './session-layer.js';\nimport { SessionError } from './errors.js';\n\nconst exec = promisify(execFile);\nconst daemonPath = () => fileURLToPath(new URL(`./daemon/galleton-${process.platform}-${process.arch}${process.platform === 'win32' ? '.exe' : ''}`, import.meta.url));\nconst failed = () => new SessionError({ message: 'Local daemon setup failed. Check semrush-cli daemon start and the private daemon.log in the state directory.' });\nconst io = <A>(run: () => Promise<A>) => Effect.tryPromise({ try: run, catch: failed });\n\n/** Own daemon, state directory and port. Never edits a shared Galleton installation. */\nexport const initializeDaemon = Effect.fn('Daemon.initialize')(function* () {\n yield* io(() => mkdir(defaultStateDirectory, { recursive: true, mode: 0o700 }));\n yield* io(() => chmod(defaultStateDirectory, 0o700));\n yield* io(() => exec(daemonPath(), ['init', '--dir', defaultStateDirectory]));\n const adapter = { providers: [{ name: 'semrush', kind: 'static', origins: [origin] }] };\n yield* io(() => writeFile(join(defaultStateDirectory, 'adapters.json'), JSON.stringify(adapter, null, 2) + '\\n', { mode: 0o600 }));\n});\n\nexport const startDaemon = Effect.fn('Daemon.start')(function* () {\n // A successful authenticated list proves this is the existing owned daemon.\n const listed = yield* io(() => exec(daemonPath(), ['list', '--dir', defaultStateDirectory, '--api', defaultDaemonURL])).pipe(Effect.match({ onSuccess: () => true, onFailure: () => false }));\n if (listed) return { running: true, url: defaultDaemonURL };\n yield* io(async () => {\n const log = await open(join(defaultStateDirectory, 'daemon.log'), 'a', 0o600);\n try {\n const child = spawn(daemonPath(), ['serve', '--dir', defaultStateDirectory, '--listen', new URL(defaultDaemonURL).host], { detached: true, stdio: ['ignore', log.fd, log.fd] });\n await new Promise<void>((resolve, reject) => { child.once('spawn', resolve); child.once('error', reject); });\n child.unref();\n } finally { await log.close(); }\n });\n // Bounded startup readiness, without launching duplicate daemons on failure.\n yield* io(async () => {\n for (let attempt = 0; attempt < 30; attempt++) {\n try { await exec(daemonPath(), ['list', '--dir', defaultStateDirectory, '--api', defaultDaemonURL]); return; }\n catch { await delay(100); }\n }\n throw new Error('Daemon did not become ready');\n });\n return { running: true, url: defaultDaemonURL };\n});\n\nexport const stopDaemon = Effect.fn('Daemon.stop')(function* () {\n yield* io(() => exec(daemonPath(), ['shutdown', '--dir', defaultStateDirectory, '--api', defaultDaemonURL]));\n return { stopping: true };\n});\n\nexport const installBrowser = Effect.fn('Browser.install')(() => io(async () => {\n const cli = fileURLToPath(new URL('./cli.js', import.meta.resolve('patchright')));\n await exec(process.execPath, [cli, 'install', 'chromium'], { timeout: 180000, maxBuffer: 1024 * 1024 });\n return { installed: true };\n}));\n","#!/usr/bin/env node\nimport { Command, Option as CliOption, InvalidArgumentError, CommanderError } from 'commander';\nimport { Effect } from 'effect';\nimport type { Scope } from 'effect';\nimport { reports, version, previewMutation, type Query } from './report-parameters.js';\nimport { Sessions } from './session-service.js';\nimport { sessionsLive } from './session-layer.js';\nimport { initializeDaemon, startDaemon, stopDaemon, installBrowser } from './daemon.js';\n\nconst interruption = new AbortController();\nconst cli = new Command().name('semrush-cli').description('Semrush research through your signed-in account. CLI + MCP, powered by Effect and Galleton.').version(version).exitOverride().showHelpAfterError().option('--json', 'Emit compact JSON').option('--no-input', 'Never prompt for terminal input').option('--no-color', 'Disable terminal colors');\ncli.addHelpText('after', '\\nExamples:\\n semrush-cli setup\\n semrush-cli auth login\\n semrush-cli domain-overview --domain openai.com --json\\n semrush-cli keyword-magic --keyword \"email marketing\" --page-size 20 --json\\n semrush-cli mcp\\n\\nDocumentation: https://semrush.micr.dev\\n');\n\nfunction output<A>(value: A, command: Command): void {\n process.stdout.write(JSON.stringify(value, null, command.optsWithGlobals().json ? undefined : 2) + '\\n');\n}\n\nasync function execute<A, E extends { readonly message: string }>(program: Effect.Effect<A, E, Scope.Scope>, command: Command): Promise<void> {\n await Effect.runPromise(Effect.scoped(program).pipe(Effect.match({\n onSuccess: value => output(value, command),\n onFailure: error => { process.stderr.write(`semrush-cli: ${error.message}\\n`); process.exitCode = 'name' in error && error.name === 'UsageError' ? 2 : 1; },\n })), { signal: interruption.signal });\n}\n\ncli.command('reports').description('List research reports and project operations').action((_options, command: Command) => {\n output(Object.entries(reports).map(([name, report]) => ({ command: name.replaceAll('_', '-'), tool: name, description: report.description, read_only: !report.mutation, destructive: report.destructive, schema: report.schema })), command);\n});\n\ninterface Property { type?: string; default?: unknown; description?: string; anyOf?: { type?: string }[]; }\nfor (const [name, definition] of Object.entries(reports)) {\n const report = cli.command(name.replaceAll('_', '-')).description(definition.description);\n const schema: { properties: Record<string, Property>; required?: string[] } = definition.schema;\n for (const [key, property] of Object.entries(schema.properties)) {\n const flag = key.replaceAll('_', '-');\n const description = (property.description ?? key.replaceAll('_', ' ')) + (property.default === undefined ? '' : ` (default: ${JSON.stringify(property.default)})`);\n const type = property.type ?? property.anyOf?.find(candidate => candidate.type !== 'null')?.type;\n const option = new CliOption(type === 'boolean' ? `--${flag} [boolean]` : `--${flag} <${type === 'array' || type === 'object' ? 'json' : 'value'}>`, description);\n option.argParser((text: string) => {\n if (type === 'boolean') {\n if (!['true', 'false'].includes(text)) throw new InvalidArgumentError('Expected true or false.');\n return text === 'true';\n }\n if (type === 'integer' || type === 'number') {\n if (!text.trim() || !Number.isFinite(Number(text))) throw new InvalidArgumentError('Expected a number.');\n return Number(text);\n }\n if (type === 'array' || type === 'object') {\n try { return JSON.parse(text); } catch { throw new InvalidArgumentError('Expected valid JSON.'); }\n }\n return text;\n });\n if (schema.required?.includes(key)) option.makeOptionMandatory();\n report.addOption(option);\n }\n report.action(async (_options, command: Command) => {\n const { parseReport } = await import('./validation.js');\n const options = command.opts<Query>();\n const input = Object.fromEntries(Object.keys(schema.properties).map(key => [key, options[key.replace(/_([a-z])/g, (_match, char: string) => char.toUpperCase())]]).filter(([, value]) => value !== undefined));\n // Parse before acquiring any credential-bearing browser resources.\n const parsed = await Effect.runPromise(parseReport(name, input).pipe(Effect.match({ onSuccess: value => ({ ok: true as const, value }), onFailure: error => ({ ok: false as const, error }) })));\n if (!parsed.ok) { process.stderr.write(`semrush-cli: ${parsed.error.message}\\n`); process.exitCode = 2; return; }\n const preview = previewMutation(parsed.value.name, parsed.value.definition, parsed.value.query);\n if (preview) { output(preview, command); return; }\n const { appLayer } = await import('./mcp.js');\n const { Semrush } = await import('./browser-service.js');\n await execute(Effect.gen(function* () { return yield* (yield* Semrush).report(parsed.value); }).pipe(Effect.provide(appLayer)), command);\n });\n}\n\ncli.command('setup').description('Install Chromium and initialize the private Galleton daemon').action((_options, command: Command) => execute(Effect.gen(function* () {\n yield* initializeDaemon();\n yield* installBrowser();\n return { ...(yield* startDaemon()), next: 'semrush-cli auth login' };\n}), command));\nconst daemon = cli.command('daemon').description('Control the CLI-owned Galleton daemon');\ndaemon.command('start').description('Start the private daemon').action((_options, command: Command) => execute(startDaemon(), command));\ndaemon.command('stop').description('Gracefully stop the private daemon').action((_options, command: Command) => execute(stopDaemon(), command));\nconst auth = cli.command('auth').description('Store and inspect your Semrush session in Galleton');\nauth.command('import').description('Import a signed-in local Chromium context').requiredOption('--cdp-url <url>', 'Loopback CDP URL, e.g. http://127.0.0.1:9234').action(async (options: { cdpUrl: string }, command: Command) => execute((await import('./auth.js')).importBrowser(options.cdpUrl).pipe(Effect.provide(sessionsLive)), command));\nauth.command('login').description('Sign in through an isolated visible Chromium window').action(async (_options, command: Command) => execute((await import('./auth.js')).login().pipe(Effect.provide(sessionsLive)), command));\nauth.command('status').description('Show session metadata without credentials').option('--check', 'Verify the stored session against Semrush').action((options: { check?: boolean }, command: Command) => execute(Effect.gen(function* () {\n const status = yield* (yield* Sessions).status();\n if (options.check) {\n const { appLayer } = yield* Effect.promise(() => import('./mcp.js'));\n const { Semrush } = yield* Effect.promise(() => import('./browser-service.js'));\n const { parseReport } = yield* Effect.promise(() => import('./validation.js'));\n yield* Effect.gen(function* () { return yield* (yield* Semrush).report(yield* parseReport('account_status', {})); }).pipe(Effect.provide(appLayer));\n }\n return { logged_in: status.status === 'ready', source: 'galleton', ...status, session_valid: options.check ? true : undefined };\n}).pipe(Effect.provide(sessionsLive)), command));\nauth.command('logout').description('Forget this CLI session from Galleton').action((_options, command: Command) => execute(Effect.gen(function* () { yield* (yield* Sessions).forget(); return { logged_in: false, forgotten: true }; }).pipe(Effect.provide(sessionsLive)), command));\ncli.command('doctor').description('Check Galleton, browser and authenticated report access').action(async (_options, command: Command) => {\n const { appLayer } = await import('./mcp.js');\n const { Semrush } = await import('./browser-service.js');\n const { parseReport } = await import('./validation.js');\n await execute(Effect.gen(function* () { yield* (yield* Semrush).report(yield* parseReport('account_status', {})); return { ok: true, galleton: true, chromium: true, authenticated: true }; }).pipe(Effect.provide(appLayer)), command);\n});\ncli.command('mcp').description('Run the MCP server over stdio').action(async () => (await import('./mcp.js')).serveMcp());\n\nprocess.once('SIGINT', () => { if (process.argv.includes('mcp')) return; process.exitCode = 130; interruption.abort(); });\ntry { await cli.parseAsync(); }\ncatch (error) {\n // Commander writes usage details itself. Other defects must not expose browser payloads.\n if (interruption.signal.aborted) process.exitCode = 130;\n else if (error instanceof CommanderError) process.exitCode = error.exitCode === 0 ? 0 : 2;\n else { process.stderr.write('semrush-cli: Unexpected failure. Run semrush-cli doctor and report the failing command at https://github.com/Microck/semrush-cli/issues.\\n'); process.exitCode = 1; }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","names":["delay","cli","schema: { properties: Record<string, Property>; required?: string[] }","CliOption"],"sources":["../src/daemon.ts","../src/cli.ts"],"sourcesContent":["import { spawn, execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { setTimeout as delay } from 'node:timers/promises';\nimport { chmod, mkdir, open, writeFile } from 'node:fs/promises';\nimport { fileURLToPath } from 'node:url';\nimport { join } from 'node:path';\nimport { Effect } from 'effect';\nimport { defaultStateDirectory, defaultDaemonURL, origin } from './session-layer.js';\nimport { SessionError } from './errors.js';\n\nconst exec = promisify(execFile);\nconst daemonPath = () => fileURLToPath(new URL(`./daemon/galleton-${process.platform}-${process.arch}${process.platform === 'win32' ? '.exe' : ''}`, import.meta.url));\nconst failed = () => new SessionError({ message: 'Local daemon setup failed. Check semrush daemon start and the private daemon.log in the state directory.' });\nconst io = <A>(run: () => Promise<A>) => Effect.tryPromise({ try: run, catch: failed });\n\n/** Own daemon, state directory and port. Never edits a shared Galleton installation. */\nexport const initializeDaemon = Effect.fn('Daemon.initialize')(function* () {\n yield* io(() => mkdir(defaultStateDirectory, { recursive: true, mode: 0o700 }));\n yield* io(() => chmod(defaultStateDirectory, 0o700));\n yield* io(() => exec(daemonPath(), ['init', '--dir', defaultStateDirectory]));\n const adapter = { providers: [{ name: 'semrush', kind: 'static', origins: [origin] }] };\n yield* io(() => writeFile(join(defaultStateDirectory, 'adapters.json'), JSON.stringify(adapter, null, 2) + '\\n', { mode: 0o600 }));\n});\n\nexport const startDaemon = Effect.fn('Daemon.start')(function* () {\n // A successful authenticated list proves this is the existing owned daemon.\n const listed = yield* io(() => exec(daemonPath(), ['list', '--dir', defaultStateDirectory, '--api', defaultDaemonURL])).pipe(Effect.match({ onSuccess: () => true, onFailure: () => false }));\n if (listed) return { running: true, url: defaultDaemonURL };\n yield* io(async () => {\n const log = await open(join(defaultStateDirectory, 'daemon.log'), 'a', 0o600);\n try {\n const child = spawn(daemonPath(), ['serve', '--dir', defaultStateDirectory, '--listen', new URL(defaultDaemonURL).host], { detached: true, stdio: ['ignore', log.fd, log.fd] });\n await new Promise<void>((resolve, reject) => { child.once('spawn', resolve); child.once('error', reject); });\n child.unref();\n } finally { await log.close(); }\n });\n // Bounded startup readiness, without launching duplicate daemons on failure.\n yield* io(async () => {\n for (let attempt = 0; attempt < 30; attempt++) {\n try { await exec(daemonPath(), ['list', '--dir', defaultStateDirectory, '--api', defaultDaemonURL]); return; }\n catch { await delay(100); }\n }\n throw new Error('Daemon did not become ready');\n });\n return { running: true, url: defaultDaemonURL };\n});\n\nexport const stopDaemon = Effect.fn('Daemon.stop')(function* () {\n yield* io(() => exec(daemonPath(), ['shutdown', '--dir', defaultStateDirectory, '--api', defaultDaemonURL]));\n return { stopping: true };\n});\n\nexport const installBrowser = Effect.fn('Browser.install')(() => io(async () => {\n const cli = fileURLToPath(new URL('./cli.js', import.meta.resolve('patchright')));\n await exec(process.execPath, [cli, 'install', 'chromium'], { timeout: 180000, maxBuffer: 1024 * 1024 });\n return { installed: true };\n}));\n","#!/usr/bin/env node\nimport { Command, Option as CliOption, InvalidArgumentError, CommanderError } from 'commander';\nimport { Effect } from 'effect';\nimport type { Scope } from 'effect';\nimport { reports, version, previewMutation, type Query } from './report-parameters.js';\nimport { Sessions } from './session-service.js';\nimport { sessionsLive } from './session-layer.js';\nimport { initializeDaemon, startDaemon, stopDaemon, installBrowser } from './daemon.js';\n\nconst interruption = new AbortController();\nconst cli = new Command().name('semrush').description('Semrush research through your signed-in account. CLI + MCP, powered by Effect and Galleton.').version(version).exitOverride().showHelpAfterError().option('--json', 'Emit compact JSON').option('--no-input', 'Never prompt for terminal input').option('--no-color', 'Disable terminal colors');\ncli.addHelpText('after', '\\nExamples:\\n semrush setup\\n semrush auth login\\n semrush domain-overview --domain openai.com --json\\n semrush keyword-magic --keyword \"email marketing\" --page-size 20 --json\\n semrush mcp\\n\\nDocumentation: https://semrush.micr.dev\\n');\n\nfunction output<A>(value: A, command: Command): void {\n process.stdout.write(JSON.stringify(value, null, command.optsWithGlobals().json ? undefined : 2) + '\\n');\n}\n\nasync function execute<A, E extends { readonly message: string }>(program: Effect.Effect<A, E, Scope.Scope>, command: Command): Promise<void> {\n await Effect.runPromise(Effect.scoped(program).pipe(Effect.match({\n onSuccess: value => output(value, command),\n onFailure: error => { process.stderr.write(`semrush: ${error.message}\\n`); process.exitCode = 'name' in error && error.name === 'UsageError' ? 2 : 1; },\n })), { signal: interruption.signal });\n}\n\ncli.command('reports').description('List research reports and project operations').action((_options, command: Command) => {\n output(Object.entries(reports).map(([name, report]) => ({ command: name.replaceAll('_', '-'), tool: name, description: report.description, read_only: !report.mutation, destructive: report.destructive, schema: report.schema })), command);\n});\n\ninterface Property { type?: string; default?: unknown; description?: string; anyOf?: { type?: string }[]; }\nfor (const [name, definition] of Object.entries(reports)) {\n const report = cli.command(name.replaceAll('_', '-')).description(definition.description);\n const schema: { properties: Record<string, Property>; required?: string[] } = definition.schema;\n for (const [key, property] of Object.entries(schema.properties)) {\n const flag = key.replaceAll('_', '-');\n const description = (property.description ?? key.replaceAll('_', ' ')) + (property.default === undefined ? '' : ` (default: ${JSON.stringify(property.default)})`);\n const type = property.type ?? property.anyOf?.find(candidate => candidate.type !== 'null')?.type;\n const option = new CliOption(type === 'boolean' ? `--${flag} [boolean]` : `--${flag} <${type === 'array' || type === 'object' ? 'json' : 'value'}>`, description);\n option.argParser((text: string) => {\n if (type === 'boolean') {\n if (!['true', 'false'].includes(text)) throw new InvalidArgumentError('Expected true or false.');\n return text === 'true';\n }\n if (type === 'integer' || type === 'number') {\n if (!text.trim() || !Number.isFinite(Number(text))) throw new InvalidArgumentError('Expected a number.');\n return Number(text);\n }\n if (type === 'array' || type === 'object') {\n try { return JSON.parse(text); } catch { throw new InvalidArgumentError('Expected valid JSON.'); }\n }\n return text;\n });\n if (schema.required?.includes(key)) option.makeOptionMandatory();\n report.addOption(option);\n }\n report.action(async (_options, command: Command) => {\n const { parseReport } = await import('./validation.js');\n const options = command.opts<Query>();\n const input = Object.fromEntries(Object.keys(schema.properties).map(key => [key, options[key.replace(/_([a-z])/g, (_match, char: string) => char.toUpperCase())]]).filter(([, value]) => value !== undefined));\n // Parse before acquiring any credential-bearing browser resources.\n const parsed = await Effect.runPromise(parseReport(name, input).pipe(Effect.match({ onSuccess: value => ({ ok: true as const, value }), onFailure: error => ({ ok: false as const, error }) })));\n if (!parsed.ok) { process.stderr.write(`semrush: ${parsed.error.message}\\n`); process.exitCode = 2; return; }\n const preview = previewMutation(parsed.value.name, parsed.value.definition, parsed.value.query);\n if (preview) { output(preview, command); return; }\n const { appLayer } = await import('./mcp.js');\n const { Semrush } = await import('./browser-service.js');\n await execute(Effect.gen(function* () { return yield* (yield* Semrush).report(parsed.value); }).pipe(Effect.provide(appLayer)), command);\n });\n}\n\ncli.command('setup').description('Install Chromium and initialize the private Galleton daemon').action((_options, command: Command) => execute(Effect.gen(function* () {\n yield* initializeDaemon();\n yield* installBrowser();\n return { ...(yield* startDaemon()), next: 'semrush auth login' };\n}), command));\nconst daemon = cli.command('daemon').description('Control the CLI-owned Galleton daemon');\ndaemon.command('start').description('Start the private daemon').action((_options, command: Command) => execute(startDaemon(), command));\ndaemon.command('stop').description('Gracefully stop the private daemon').action((_options, command: Command) => execute(stopDaemon(), command));\nconst auth = cli.command('auth').description('Store and inspect your Semrush session in Galleton');\nauth.command('import').description('Import a signed-in local Chromium context').requiredOption('--cdp-url <url>', 'Loopback CDP URL, e.g. http://127.0.0.1:9234').action(async (options: { cdpUrl: string }, command: Command) => execute((await import('./auth.js')).importBrowser(options.cdpUrl).pipe(Effect.provide(sessionsLive)), command));\nauth.command('login').description('Sign in through an isolated visible Chromium window').action(async (_options, command: Command) => execute((await import('./auth.js')).login().pipe(Effect.provide(sessionsLive)), command));\nauth.command('status').description('Show session metadata without credentials').option('--check', 'Verify the stored session against Semrush').action((options: { check?: boolean }, command: Command) => execute(Effect.gen(function* () {\n const status = yield* (yield* Sessions).status();\n if (options.check) {\n const { appLayer } = yield* Effect.promise(() => import('./mcp.js'));\n const { Semrush } = yield* Effect.promise(() => import('./browser-service.js'));\n const { parseReport } = yield* Effect.promise(() => import('./validation.js'));\n yield* Effect.gen(function* () { return yield* (yield* Semrush).report(yield* parseReport('account_status', {})); }).pipe(Effect.provide(appLayer));\n }\n return { logged_in: status.status === 'ready', source: 'galleton', ...status, session_valid: options.check ? true : undefined };\n}).pipe(Effect.provide(sessionsLive)), command));\nauth.command('logout').description('Forget this CLI session from Galleton').action((_options, command: Command) => execute(Effect.gen(function* () { yield* (yield* Sessions).forget(); return { logged_in: false, forgotten: true }; }).pipe(Effect.provide(sessionsLive)), command));\ncli.command('doctor').description('Check Galleton, browser and authenticated report access').action(async (_options, command: Command) => {\n const { appLayer } = await import('./mcp.js');\n const { Semrush } = await import('./browser-service.js');\n const { parseReport } = await import('./validation.js');\n await execute(Effect.gen(function* () { yield* (yield* Semrush).report(yield* parseReport('account_status', {})); return { ok: true, galleton: true, chromium: true, authenticated: true }; }).pipe(Effect.provide(appLayer)), command);\n});\ncli.command('mcp').description('Run the MCP server over stdio').action(async () => (await import('./mcp.js')).serveMcp());\n\nprocess.once('SIGINT', () => { if (process.argv.includes('mcp')) return; process.exitCode = 130; interruption.abort(); });\ntry { await cli.parseAsync(); }\ncatch (error) {\n // Commander writes usage details itself. Other defects must not expose browser payloads.\n if (interruption.signal.aborted) process.exitCode = 130;\n else if (error instanceof CommanderError) process.exitCode = error.exitCode === 0 ? 0 : 2;\n else { process.stderr.write('semrush: Unexpected failure. Run semrush doctor and report the failing command at https://github.com/Microck/semrush-cli/issues.\\n'); process.exitCode = 1; }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
|
|
3
3
|
//#region package.json
|
|
4
|
-
var version$1 = "0.
|
|
4
|
+
var version$1 = "0.5.0";
|
|
5
5
|
|
|
6
6
|
//#endregion
|
|
7
7
|
//#region src/report-catalog.json
|
|
@@ -4244,4 +4244,4 @@ var UsageError = class extends Schema.TaggedError()("UsageError", { message: Sch
|
|
|
4244
4244
|
|
|
4245
4245
|
//#endregion
|
|
4246
4246
|
export { reportParameters as a, version as c, previewMutation as i, webRequest as l, SessionError as n, reports as o, UsageError as r, rpcBody as s, ReportError as t };
|
|
4247
|
-
//# sourceMappingURL=errors-
|
|
4247
|
+
//# sourceMappingURL=errors-DNn_XeoU.js.map
|