@gscdump/cli 0.16.0 → 0.17.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 (2) hide show
  1. package/dist/index.mjs +29 -23
  2. package/package.json +8 -8
package/dist/index.mjs CHANGED
@@ -17,6 +17,7 @@ import { ofetch } from "ofetch";
17
17
  import fs$1 from "node:fs";
18
18
  import { Buffer } from "node:buffer";
19
19
  import { createConsola } from "consola";
20
+ import { SearchTypes, and, between, contains, country, date, device, eq, gsc, notRegex, page, query, regex, searchAppearance } from "gscdump/query";
20
21
  import { createNodeHarness } from "@gscdump/engine/node";
21
22
  import { TABLE_DIMS, transformGscRow } from "@gscdump/engine/ingest";
22
23
  import { allTables, inferTable } from "@gscdump/engine/schema";
@@ -25,7 +26,6 @@ import { sqlEscape } from "@gscdump/engine/sql";
25
26
  import { createEmptyTypesStore, createIndexingMetadataStore, createInspectionStore, createSitemapStore } from "@gscdump/engine/entities";
26
27
  import { createGscMcpServer } from "@gscdump/mcp/server";
27
28
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
28
- import { SearchTypes, and, between, contains, country, date, device, eq, gsc, notRegex, page, query, regex, searchAppearance } from "gscdump/query";
29
29
  import { defaultReportRegistry, dryRunReport, formatReport, runReport } from "@gscdump/analysis/report";
30
30
  import { resolveWindow } from "@gscdump/engine/period";
31
31
  import { inferLegacyTier } from "@gscdump/engine";
@@ -73,7 +73,9 @@ function loadEnvFromCwd() {
73
73
  }
74
74
  return applied;
75
75
  }
76
- const VERSION = "0.16.0";
76
+ var version = "0.17.0";
77
+ const ALL_SEARCH_TYPES$1 = Object.values(SearchTypes);
78
+ const VERSION = version;
77
79
  const baseLogger = createConsola({
78
80
  stdout: process.stderr,
79
81
  stderr: process.stderr
@@ -104,6 +106,15 @@ function applyOutputMode(args) {
104
106
  quiet
105
107
  };
106
108
  }
109
+ function parseSearchType(value, flag = "--search-type") {
110
+ if (!value) return void 0;
111
+ const v = String(value);
112
+ if (!ALL_SEARCH_TYPES$1.includes(v)) {
113
+ logger.error(`Invalid ${flag}: ${v}. Allowed: ${ALL_SEARCH_TYPES$1.join(", ")}`);
114
+ process.exit(1);
115
+ }
116
+ return v;
117
+ }
107
118
  let colorEnabled = (() => {
108
119
  if (process.env.NO_COLOR) return false;
109
120
  if (process.argv.includes("--no-color")) return false;
@@ -2247,6 +2258,10 @@ const dumpCommand = defineCommand({
2247
2258
  default: false,
2248
2259
  description: "Compact every closed month into a single file before exporting"
2249
2260
  },
2261
+ "search-type": {
2262
+ type: "string",
2263
+ description: `Restrict dump to a single GSC search-type slice (${ALL_SEARCH_TYPES$1.join(", ")}). Default: all slices.`
2264
+ },
2250
2265
  ...OUTPUT_ARGS
2251
2266
  },
2252
2267
  async run({ args }) {
@@ -2257,6 +2272,7 @@ const dumpCommand = defineCommand({
2257
2272
  process.exit(1);
2258
2273
  }
2259
2274
  const tablesFilter = args.tables ? new Set(String(args.tables).split(",").map((t) => t.trim()).filter(Boolean)) : null;
2275
+ const searchType = parseSearchType(args["search-type"]);
2260
2276
  const ctx = await createCommandContext({
2261
2277
  needsAuth: !args["all-sites"],
2262
2278
  needsStore: true
@@ -2271,7 +2287,7 @@ const dumpCommand = defineCommand({
2271
2287
  if (args.compact) for (const siteUrl of targets) await compactClosedMonths(store, siteUrl, quiet);
2272
2288
  const summary = [];
2273
2289
  for (const siteUrl of targets) {
2274
- const entries = (await listLiveEntries(store, siteUrl)).filter((e) => !tablesFilter || tablesFilter.has(e.table));
2290
+ const entries = (await listLiveEntries(store, siteUrl, searchType)).filter((e) => !tablesFilter || tablesFilter.has(e.table));
2275
2291
  if (entries.length === 0) {
2276
2292
  if (!quiet) logger.warn(`No data for ${siteUrl}; skipping`);
2277
2293
  continue;
@@ -2320,12 +2336,13 @@ async function listSitesWithData(store) {
2320
2336
  }
2321
2337
  return Array.from(siteIds);
2322
2338
  }
2323
- async function listLiveEntries(store, siteUrl) {
2339
+ async function listLiveEntries(store, siteUrl, searchType) {
2324
2340
  const siteId = store.siteIdFor(siteUrl);
2325
2341
  return (await Promise.all(allTables().map((table) => store.engine.listLive({
2326
2342
  userId: store.userId,
2327
2343
  siteId,
2328
- table
2344
+ table,
2345
+ ...searchType !== void 0 ? { searchType } : {}
2329
2346
  })))).flat();
2330
2347
  }
2331
2348
  async function dumpParquet(store, entries, outDir) {
@@ -3514,7 +3531,6 @@ const FILTER_COL = {
3514
3531
  device,
3515
3532
  searchAppearance
3516
3533
  };
3517
- const ALL_SEARCH_TYPES$1 = Object.values(SearchTypes);
3518
3534
  const DATA_STATES = [
3519
3535
  "all",
3520
3536
  "final",
@@ -3702,7 +3718,8 @@ const queryCommand = defineCommand({
3702
3718
  site: args.site ? String(args.site) : void 0,
3703
3719
  table: args.table ? String(args.table) : "pages",
3704
3720
  output: args.output ? String(args.output) : void 0,
3705
- quiet: Boolean(args.quiet)
3721
+ quiet: Boolean(args.quiet),
3722
+ searchType: parseSearchType(args.type, "--type")
3706
3723
  });
3707
3724
  return;
3708
3725
  }
@@ -3714,7 +3731,7 @@ const queryCommand = defineCommand({
3714
3731
  const rowLimit = limitArg != null && limitArg !== "1000" ? Number.parseInt(limitArg, 10) : ctxConfig.defaultLimit ?? 1e3;
3715
3732
  const format = String(args.format);
3716
3733
  const dimensionFilter = buildDimensionFilter(args);
3717
- const searchType = parseSearchType(args.type ?? ctxConfig.defaultSearchType);
3734
+ const searchType = parseSearchType(args.type ?? ctxConfig.defaultSearchType, "--type");
3718
3735
  const dataState = args["data-state"] ? String(args["data-state"]) : ctxConfig.defaultDataState;
3719
3736
  const aggregationType = args["aggregation-type"] ? String(args["aggregation-type"]) : void 0;
3720
3737
  if (dataState && !DATA_STATES.includes(dataState)) {
@@ -3777,10 +3794,6 @@ const queryCommand = defineCommand({
3777
3794
  });
3778
3795
  return;
3779
3796
  }
3780
- if (searchType && searchType !== "web") {
3781
- logger.error(`--type=${searchType} requires --live (local store query path is web-only).`);
3782
- process.exit(1);
3783
- }
3784
3797
  if (dataState || aggregationType) logger.warn("--data-state / --aggregation-type are ignored without --live");
3785
3798
  if (!args.quiet) logger.info(`Querying ${siteUrl} from local Parquet store...`);
3786
3799
  const state = buildLocalState(dimNames, startDate, endDate, rowLimit, dimensionFilter);
@@ -3798,7 +3811,8 @@ const queryCommand = defineCommand({
3798
3811
  const result = await store.engine.query({
3799
3812
  userId: store.userId,
3800
3813
  siteId: store.siteIdFor(siteUrl),
3801
- table
3814
+ table,
3815
+ ...searchType !== void 0 ? { searchType } : {}
3802
3816
  }, state).catch((e) => {
3803
3817
  logger.error(`Query failed: ${e.message}`);
3804
3818
  process.exit(1);
@@ -3925,15 +3939,6 @@ function buildDimensionFilter(args) {
3925
3939
  if (leaves.length === 1) return leaves[0];
3926
3940
  return and(...leaves);
3927
3941
  }
3928
- function parseSearchType(value) {
3929
- if (!value) return void 0;
3930
- const v = String(value);
3931
- if (!ALL_SEARCH_TYPES$1.includes(v)) {
3932
- logger.error(`Invalid --type: ${v}. Allowed: ${ALL_SEARCH_TYPES$1.join(", ")}`);
3933
- process.exit(1);
3934
- }
3935
- return v;
3936
- }
3937
3942
  async function assertRangeCovered(store, siteUrl, table, startDate, endDate) {
3938
3943
  const wm = (await store.engine.getWatermarks({
3939
3944
  userId: store.userId,
@@ -3968,7 +3973,8 @@ async function runRawSqlMode(opts) {
3968
3973
  const { rows, sql } = await store.runRawSql({
3969
3974
  sql: opts.sql,
3970
3975
  siteUrl,
3971
- table: opts.table
3976
+ table: opts.table,
3977
+ ...opts.searchType !== void 0 ? { searchType: opts.searchType } : {}
3972
3978
  }).catch((e) => {
3973
3979
  logger.error(`SQL failed: ${e.message}`);
3974
3980
  process.exit(1);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/cli",
3
3
  "type": "module",
4
- "version": "0.16.0",
4
+ "version": "0.17.0",
5
5
  "description": "CLI for Google Search Console - dump, query, and run MCP server",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -35,22 +35,22 @@
35
35
  "dist"
36
36
  ],
37
37
  "dependencies": {
38
- "@clack/prompts": "^1.3.0",
38
+ "@clack/prompts": "^1.4.0",
39
39
  "@modelcontextprotocol/sdk": "^1.29.0",
40
40
  "citty": "^0.2.2",
41
41
  "consola": "^3.4.2",
42
42
  "google-auth-library": "^10.6.2",
43
43
  "ofetch": "^1.5.1",
44
44
  "open": "^11.0.0",
45
- "@gscdump/analysis": "0.16.0",
46
- "@gscdump/engine": "0.16.0",
47
- "@gscdump/engine-gsc-api": "0.16.0",
48
- "@gscdump/mcp": "0.16.0",
49
- "gscdump": "0.16.0"
45
+ "@gscdump/analysis": "0.17.0",
46
+ "@gscdump/engine-gsc-api": "0.17.0",
47
+ "@gscdump/engine": "0.17.0",
48
+ "gscdump": "0.17.0",
49
+ "@gscdump/mcp": "0.17.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@duckdb/node-api": "1.5.1-r.2",
53
- "vitest": "^4.1.5"
53
+ "vitest": "^4.1.6"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "obuild",