@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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/cli",
3
3
  "type": "module",
4
- "version": "4.8.0",
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": "^4.8.0",
48
- "@gscdump/contracts": "^4.8.0",
49
- "@gscdump/engine": "^4.8.0",
50
- "@gscdump/engine-gsc-api": "^4.8.0",
51
- "@gscdump/sdk": "^4.8.0",
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": "^4.8.0",
56
+ "gscdump": "^5.1.0",
57
57
  "ofetch": "^1.5.1",
58
58
  "open": "^11.0.4",
59
59
  "proper-lockfile": "^4.1.2",
@@ -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 `--format json` or `--json` prints `{ "error": { "code", "message", "nextCommand" } }` on stdout and exits 1.
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. Clients without a 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 };