@gscdump/cli 4.8.0 → 5.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.
- package/dist/analysis-local.mjs +2 -2
- package/dist/auth-state.mjs +41 -6
- package/dist/auth.mjs +1 -7
- package/dist/bing-hosted.mjs +26 -5
- package/dist/cli.d.mts +0 -1
- package/dist/cli.mjs +4 -4
- package/dist/commands/analyze.mjs +2 -2
- package/dist/commands/auth.mjs +1 -1
- package/dist/commands/bing.mjs +11 -6
- package/dist/commands/doctor.mjs +12 -69
- package/dist/commands/indexing-urls.mjs +2 -2
- package/dist/commands/indexing-watch.mjs +10 -7
- package/dist/commands/init.mjs +4 -89
- package/dist/commands/mcp.mjs +1 -1
- package/dist/commands/papercut.mjs +1 -1
- package/dist/commands/profile.mjs +1 -1
- package/dist/commands/query.mjs +16 -9
- package/dist/commands/report.mjs +2 -2
- package/dist/commands/sitemaps.mjs +5 -5
- package/dist/commands/sites.mjs +10 -10
- package/dist/config.mjs +1 -1
- package/dist/context.mjs +3 -3
- package/dist/coverage.mjs +1 -3
- package/dist/environment.mjs +1 -5
- package/dist/error-handler.mjs +37 -11
- package/dist/hosted-query.mjs +23 -1
- package/dist/hosted-site.mjs +37 -17
- package/dist/mcp/errors.mjs +1 -1
- package/dist/mcp/types.mjs +1 -0
- package/dist/package.mjs +1 -1
- package/dist/render/query.mjs +1 -1
- package/dist/route.mjs +5 -9
- package/dist/runtime.d.mts +2 -0
- package/dist/runtime.mjs +1 -0
- package/dist/stop.mjs +10 -0
- package/dist/sync-plan.mjs +1 -1
- package/dist/utils.mjs +9 -5
- package/package.json +7 -7
- package/skills/gscdump/SKILL.md +36 -4
- package/dist/env-file.mjs +0 -53
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gscdump/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "5.1.0",
|
|
5
5
|
"description": "CLI for Google Search Console and Bing with hosted or local authentication, data exports, and an MCP server",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -44,16 +44,16 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@clack/prompts": "^1.8.1",
|
|
46
46
|
"@duckdb/node-api": "1.5.5-r.5",
|
|
47
|
-
"@gscdump/analysis": "^
|
|
48
|
-
"@gscdump/contracts": "^
|
|
49
|
-
"@gscdump/engine": "^
|
|
50
|
-
"@gscdump/engine-gsc-api": "^
|
|
51
|
-
"@gscdump/sdk": "^
|
|
47
|
+
"@gscdump/analysis": "^5.1.0",
|
|
48
|
+
"@gscdump/contracts": "^5.1.0",
|
|
49
|
+
"@gscdump/engine": "^5.1.0",
|
|
50
|
+
"@gscdump/engine-gsc-api": "^5.1.0",
|
|
51
|
+
"@gscdump/sdk": "^5.1.0",
|
|
52
52
|
"@modelcontextprotocol/sdk": "^1.30.1",
|
|
53
53
|
"citty": "^0.2.2",
|
|
54
54
|
"consola": "^3.4.2",
|
|
55
55
|
"google-auth-library": "^11.1.0",
|
|
56
|
-
"gscdump": "^
|
|
56
|
+
"gscdump": "^5.1.0",
|
|
57
57
|
"ofetch": "^1.5.1",
|
|
58
58
|
"open": "^11.0.4",
|
|
59
59
|
"proper-lockfile": "^4.1.2",
|
package/skills/gscdump/SKILL.md
CHANGED
|
@@ -11,7 +11,7 @@ For `query`, `-s` means `--site`, `-d` means `--dimensions`, and `-f` means `--f
|
|
|
11
11
|
Use `--start` and `--end` for dates. `--site=SITE` also works.
|
|
12
12
|
Use each option once, with either its short or long spelling.
|
|
13
13
|
Put options after the subcommand name: `gscdump store stats --json`, not `gscdump store --json stats`.
|
|
14
|
-
A failed command prints one `Error:` line to stderr and exits 1.
|
|
14
|
+
A failed command prints one `Error:` line to stderr and exits 1. A [stop](#stops) with JSON output also prints `{ "error" }` on stdout.
|
|
15
15
|
Example: `gscdump query --site=SITE --start=DATE --end=DATE -d page -f json`.
|
|
16
16
|
|
|
17
17
|
## Start each task
|
|
@@ -43,6 +43,9 @@ gscdump has 2 access modes. Check `gscdump auth status --json` before queries. R
|
|
|
43
43
|
In Local mode, `googleAuthenticated: true` means Google accepted the credentials. When it is false, `googleError` says why.
|
|
44
44
|
In Hosted mode, `hostedSync` lists each hosted Site with `syncStatus` and `syncProgress`, and `commands` lists what Hosted mode can run.
|
|
45
45
|
`gscdump sites` shows the same Sites and progress.
|
|
46
|
+
An empty `sites` list means the hosted record has no Sites. Commands that need a Site then stop with `NO_SITES`.
|
|
47
|
+
Tell the user to connect a Site. A browser login connects Sites on gscdump.com.
|
|
48
|
+
An API key connects Sites in the app that issued the key. That app can be a partner app, not gscdump.com.
|
|
46
49
|
|
|
47
50
|
`--mode local|hosted` overrides one invocation. `GSCDUMP_AUTH_MODE` also overrides the saved mode.
|
|
48
51
|
A successful login saves the mode per profile.
|
|
@@ -128,8 +131,7 @@ mixes Store rows and live rows.
|
|
|
128
131
|
- `--live` always asks Search Console. It needs Local mode with Google credentials.
|
|
129
132
|
- `query --sql` reads the Store only. It stops when no table it names has data.
|
|
130
133
|
- JSON output carries `meta.source`: `local`, `live`, or `hosted`.
|
|
131
|
-
- A stop with
|
|
132
|
-
Codes: `NOT_CONNECTED`, `STORE_RANGE_NOT_COVERED` (with `missingDates`), `SYNC_RUNNING` (with `sync.done` and `sync.total`), `NO_SYNCED_DATA`, `STORE_ONLY`, `LIVE_ONLY`.
|
|
134
|
+
- A routing stop with JSON output prints `{ "error" }` on stdout and exits 1. See [Stops](#stops).
|
|
133
135
|
Partial coverage and a running sync are normal progress. Run `nextCommand`, or tell the user to.
|
|
134
136
|
- A sync is running only while its heartbeat is recent. A killed sync does not block reads.
|
|
135
137
|
- Every Search Analytics, URL Inspection, and Indexing API call spends the shared quota ledger in the data dir.
|
|
@@ -153,7 +155,8 @@ gscdump skill install --agent claude # Codex: --agent codex
|
|
|
153
155
|
```
|
|
154
156
|
|
|
155
157
|
After upgrading the CLI, run this command again to update the installed skill.
|
|
156
|
-
The command prints where it wrote the skill
|
|
158
|
+
The command prints where it wrote the skill, as a path that works from any directory, such as `~/.claude/skills/gscdump`.
|
|
159
|
+
With `--json`, `destination` is the absolute path. Clients without a skill
|
|
157
160
|
directory can read `gscdump --help` and `gscdump <command> --help` instead.
|
|
158
161
|
|
|
159
162
|
## Local mode setup
|
|
@@ -220,6 +223,35 @@ Parse JSON. Never scrape human output.
|
|
|
220
223
|
If the user requests JSON, return the CLI JSON unchanged. Do not replace it with a table.
|
|
221
224
|
Do not rewrite rows, estimate metrics, or add manually calculated totals.
|
|
222
225
|
|
|
226
|
+
## Stops
|
|
227
|
+
|
|
228
|
+
A stop ends a command at a known condition and exits 1. stderr gets the message.
|
|
229
|
+
If the command writes JSON, stdout gets `{ "error": { "code", "message", "nextCommand" } }`.
|
|
230
|
+
A command writes JSON with `--json`, with `--format json`, and for `query` with its default format.
|
|
231
|
+
Read `code`, not the message. If `nextCommand` is not null, run it, or tell the user to run it.
|
|
232
|
+
A `gscdump auth login` command needs the user. Tell the user to run it. If `nextCommand` is null, tell the user the `message`.
|
|
233
|
+
A routing stop also has `siteUrl`. `STORE_RANGE_NOT_COVERED` adds `missingDates`, and `SYNC_RUNNING` adds `sync.done` and `sync.total`.
|
|
234
|
+
|
|
235
|
+
| Code | Meaning |
|
|
236
|
+
| --- | --- |
|
|
237
|
+
| `NOT_CONNECTED` | The Store cannot answer, and Google is not connected |
|
|
238
|
+
| `STORE_RANGE_NOT_COVERED` | The Store does not have `missingDates` |
|
|
239
|
+
| `SYNC_RUNNING` | A sync is still filling the dates |
|
|
240
|
+
| `NO_SYNCED_DATA` | A Store-only read found no synced data |
|
|
241
|
+
| `STORE_ONLY` | The read needs the Store, so `--live` cannot run it |
|
|
242
|
+
| `LIVE_ONLY` | Only `--live` can answer the read |
|
|
243
|
+
| `LOCAL_MODE_REQUIRED` | The command calls Google, and Hosted mode is selected |
|
|
244
|
+
| `HOSTED_MODE_REQUIRED` | The command reads the hosted record, and Local mode is selected |
|
|
245
|
+
| `HOSTED_CREDENTIALS_MISSING` | Hosted mode has no CLI session and no API key |
|
|
246
|
+
| `HOSTED_CREDENTIALS_REJECTED` | gscdump.com rejected the CLI session or API key. For an API key, `nextCommand` is null: the user needs a new key from the app that issued it |
|
|
247
|
+
| `NO_SITES` | The hosted record has no Sites. The message says where the user connects one |
|
|
248
|
+
| `SITE_NOT_FOUND` | No hosted Site matches `--site` |
|
|
249
|
+
| `SITE_AMBIGUOUS` | More than one hosted Site matches `--site` |
|
|
250
|
+
| `SITE_REQUIRED` | The hosted record has more than one Site. Pass `--site` |
|
|
251
|
+
| `BING_NOT_CONNECTED` | The Site has no hosted Bing connection |
|
|
252
|
+
| `RECORD_NOT_READY` | gscdump has not prepared the Site's record for reads yet |
|
|
253
|
+
| `RANGE_NOT_SYNCED` | The hosted record does not hold the requested dates |
|
|
254
|
+
|
|
223
255
|
## Commands
|
|
224
256
|
|
|
225
257
|
| Command | Use it for |
|
package/dist/env-file.mjs
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { useCliRuntime } from "./runtime.mjs";
|
|
2
|
-
import process from "node:process";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import fs from "node:fs";
|
|
5
|
-
const ENV_LINE_RE = /^([^=]+)=(.*)$/;
|
|
6
|
-
function parseEnvFile(envPath) {
|
|
7
|
-
let content;
|
|
8
|
-
try {
|
|
9
|
-
content = fs.readFileSync(envPath, "utf-8");
|
|
10
|
-
} catch {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
const env = {};
|
|
14
|
-
for (const line of content.split("\n")) {
|
|
15
|
-
const trimmed = line.trim();
|
|
16
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
17
|
-
const match = trimmed.match(ENV_LINE_RE);
|
|
18
|
-
if (!match) continue;
|
|
19
|
-
const key = match[1].trim();
|
|
20
|
-
let value = match[2].trim();
|
|
21
|
-
if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1);
|
|
22
|
-
env[key] = value;
|
|
23
|
-
}
|
|
24
|
-
return env;
|
|
25
|
-
}
|
|
26
|
-
const appliedEnvKeys = /* @__PURE__ */ new Set();
|
|
27
|
-
let loadedEnvPath = null;
|
|
28
|
-
function getAppliedEnvKeys() {
|
|
29
|
-
return appliedEnvKeys;
|
|
30
|
-
}
|
|
31
|
-
function getLoadedEnvPath() {
|
|
32
|
-
return loadedEnvPath;
|
|
33
|
-
}
|
|
34
|
-
function loadEnvFromCwd() {
|
|
35
|
-
return loadEnvFile({
|
|
36
|
-
cwd: process.cwd(),
|
|
37
|
-
env: useCliRuntime().environment
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
function loadEnvFile(opts) {
|
|
41
|
-
const envPath = path.join(opts.cwd, ".env");
|
|
42
|
-
const parsed = parseEnvFile(envPath);
|
|
43
|
-
if (!parsed) return [];
|
|
44
|
-
loadedEnvPath = envPath;
|
|
45
|
-
const applied = [];
|
|
46
|
-
for (const [key, value] of Object.entries(parsed)) if (opts.env[key] === void 0) {
|
|
47
|
-
opts.env[key] = value;
|
|
48
|
-
applied.push(key);
|
|
49
|
-
appliedEnvKeys.add(key);
|
|
50
|
-
}
|
|
51
|
-
return applied;
|
|
52
|
-
}
|
|
53
|
-
export { getAppliedEnvKeys, getLoadedEnvPath, loadEnvFile, loadEnvFromCwd, parseEnvFile };
|