gscdump 0.8.0 → 0.8.1

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/index.d.mts CHANGED
@@ -162,6 +162,21 @@ interface GSCQueryBuilder<D extends Dimension[] = [], C = object> {
162
162
  toBody: () => SearchAnalyticsQuery;
163
163
  getState: () => BuilderState;
164
164
  }
165
+ type VerificationMethod = 'META' | 'FILE' | 'DNS_TXT' | 'DNS_CNAME' | 'ANALYTICS' | 'TAG_MANAGER';
166
+ type VerificationSiteType = 'SITE' | 'INET_DOMAIN' | 'ANDROID_APP';
167
+ interface VerificationSite {
168
+ type: VerificationSiteType;
169
+ identifier: string;
170
+ }
171
+ interface VerificationToken {
172
+ method: string;
173
+ token: string;
174
+ }
175
+ interface VerificationWebResource {
176
+ id?: string;
177
+ site: VerificationSite;
178
+ owners?: string[];
179
+ }
165
180
  /**
166
181
  * Compatible interface with OAuth2Client from google-auth-library
167
182
  */
@@ -193,8 +208,30 @@ interface CallOptions {
193
208
  interface GoogleSearchConsoleClient {
194
209
  /** Query search analytics with builder, returns async generator yielding typed row batches */
195
210
  query: <D extends Dimension[], C>(siteUrl: string, builder: GSCQueryBuilder<D, C>, opts?: CallOptions) => AsyncGenerator<GSCRow<D, C>[]>;
196
- /** List all sites */
197
- sites: (opts?: CallOptions) => Promise<ApiSite[]>;
211
+ /**
212
+ * List all sites. Also exposes write ops as `client.sites.add(siteUrl)` and
213
+ * `client.sites.delete(siteUrl)`. Calling `client.sites()` is equivalent to
214
+ * `client.sites.list()`.
215
+ */
216
+ sites: ((opts?: CallOptions) => Promise<ApiSite[]>) & {
217
+ list: (opts?: CallOptions) => Promise<ApiSite[]>; /** Add a property in unverified state. Caller must verify ownership separately. */
218
+ add: (siteUrl: string, opts?: CallOptions) => Promise<void>; /** Remove a property from the user's account. */
219
+ delete: (siteUrl: string, opts?: CallOptions) => Promise<void>;
220
+ };
221
+ /** Site Verification API (siteverification.googleapis.com). Required to flip a property from unverified to verified. */
222
+ verification: {
223
+ /** Returns the token to place on the site/DNS, plus the resolved method. */getToken: (params: {
224
+ site: VerificationSite;
225
+ verificationMethod: VerificationMethod;
226
+ }, opts?: CallOptions) => Promise<VerificationToken>; /** Triggers Google to fetch + validate; returns the verified WebResource. */
227
+ insert: (params: {
228
+ site: VerificationSite;
229
+ verificationMethod: VerificationMethod;
230
+ }, opts?: CallOptions) => Promise<VerificationWebResource>;
231
+ list: (opts?: CallOptions) => Promise<VerificationWebResource[]>;
232
+ get: (id: string, opts?: CallOptions) => Promise<VerificationWebResource>;
233
+ delete: (id: string, opts?: CallOptions) => Promise<void>;
234
+ };
198
235
  /** Inspect a URL */
199
236
  inspect: (siteUrl: string, url: string, opts?: CallOptions) => Promise<InspectUrlIndexResponse>;
200
237
  /** Sitemap operations */
@@ -251,6 +288,7 @@ declare function getIndexingMetadata(client: GoogleSearchConsoleClient, url: str
251
288
  declare function batchRequestIndexing(client: GoogleSearchConsoleClient, urls: string[], options?: {
252
289
  type?: IndexingNotificationType;
253
290
  delayMs?: number;
291
+ concurrency?: number;
254
292
  onProgress?: (result: IndexingResult, index: number, total: number) => void;
255
293
  }): Promise<IndexingResult[]>;
256
294
  interface InspectUrlResult {
@@ -271,6 +309,7 @@ declare function inspectUrl(client: GoogleSearchConsoleClient, siteUrl: string,
271
309
  */
272
310
  declare function batchInspectUrls(client: GoogleSearchConsoleClient, siteUrl: string, urls: string[], options?: {
273
311
  delayMs?: number;
312
+ concurrency?: number;
274
313
  onProgress?: (result: InspectUrlResult, index: number, total: number) => void;
275
314
  }): Promise<InspectUrlResult[]>;
276
315
  /**
@@ -299,6 +338,43 @@ declare function submitSitemap(client: GoogleSearchConsoleClient, siteUrl: strin
299
338
  * Deletes a sitemap from Google Search Console.
300
339
  */
301
340
  declare function deleteSitemap(client: GoogleSearchConsoleClient, siteUrl: string, feedpath: string): Promise<void>;
341
+ /**
342
+ * Add a property to the user's Search Console account.
343
+ *
344
+ * Note: this only registers the property in an unverified state. Ownership
345
+ * must be proven via the Site Verification API (see `verifySite`) before any
346
+ * data is accessible.
347
+ */
348
+ declare function addSite(client: GoogleSearchConsoleClient, siteUrl: string): Promise<void>;
349
+ /**
350
+ * Remove a property from the user's Search Console account.
351
+ */
352
+ declare function deleteSite(client: GoogleSearchConsoleClient, siteUrl: string): Promise<void>;
353
+ /**
354
+ * Resolve a Search Console site URL (`https://example.com/` or
355
+ * `sc-domain:example.com`) to the Site Verification API's site shape.
356
+ */
357
+ declare function siteUrlToVerificationSite(siteUrl: string): VerificationSite;
358
+ /**
359
+ * Methods valid for a given site shape. SITE properties can use META/FILE/
360
+ * ANALYTICS/TAG_MANAGER; INET_DOMAIN must use DNS_TXT or DNS_CNAME.
361
+ */
362
+ declare function verificationMethodsFor(site: VerificationSite): VerificationMethod[];
363
+ /**
364
+ * Get the verification token Google expects to find on the site or DNS.
365
+ */
366
+ declare function getVerificationToken(client: GoogleSearchConsoleClient, siteUrl: string, method: VerificationMethod): Promise<VerificationToken & {
367
+ site: VerificationSite;
368
+ }>;
369
+ /**
370
+ * Trigger Google to validate the placed token. Caller is responsible for
371
+ * having placed the token (HTML tag / file / DNS record) before calling.
372
+ */
373
+ declare function verifySite(client: GoogleSearchConsoleClient, siteUrl: string, method: VerificationMethod): Promise<VerificationWebResource>;
374
+ /**
375
+ * List all verified WebResources for the authed user.
376
+ */
377
+ declare function listVerifiedSites(client: GoogleSearchConsoleClient): Promise<VerificationWebResource[]>;
302
378
  interface GscdumpApiOptions {
303
379
  /** API key (gsd_user_xxx or gsd_prod_xxx) */
304
380
  apiKey: string;
@@ -463,4 +539,4 @@ declare const INDEXING_EFFECTIVE_LIMIT = 1800;
463
539
  declare function hasGscReadScope(scopes: string | null | undefined): boolean;
464
540
  declare function hasGscWriteScope(scopes: string | null | undefined): boolean;
465
541
  declare function hasIndexingScope(scopes: string | null | undefined): boolean;
466
- export { ApiSite, ApiSitemap, ApiSitemapContent, Auth, AuthClient, AuthOptions, BackfillProgress, CallOptions, DAYS_PER_RANGE, DataRow, DimensionFilter, DimensionFilterGroup, GSC_FINALIZED_LAG_DAYS, GSC_FRESHEST_LAG_DAYS, GSC_QUOTAS, GSC_RETENTION_MONTHS, GoogleSearchConsoleClient, GoogleSearchConsoleClientOptions, GscError, GscErrorKind, GscdumpApiOptions, INDEXING_DAILY_LIMIT, INDEXING_EFFECTIVE_LIMIT, INDEXING_ISSUE_FILTERS, INDEXING_ISSUE_LABELS, INDEXING_ISSUE_SEVERITY, IndexStatusResult, IndexingIssueType, IndexingMetadata, IndexingNotificationType, IndexingResult, InspectUrlIndexResponse, InspectUrlResult, MS_PER_DAY, MobileUsabilityResult, Period, PublishUrlNotificationResponse, RequiredNonNullable, ResolvedAnalyticsRange, RichResultsResult, SearchAnalyticsQuery, SearchAnalyticsResponse, Site, SiteAnalytics, UrlInspectionResult, UrlNotificationMetadata, addDays, batchInspectUrls, batchRequestIndexing, classifyError, countDays, createAuth, createFetch, daysAgo, deleteSitemap, fetchSitemap, fetchSitemaps, fetchSites, fetchSitesWithSitemaps, formatErrorForCli, generateGscDateRange, getBackfillProgress, getDateRange, getFreshestGscDate, getIndexingMetadata, getLatestGscDate, getNextDate, getOldestGscDate, getPendingDates, getPreviousDate, getPstDate, googleSearchConsole, groupIntoRanges, gscdumpApi, hasGscReadScope, hasGscWriteScope, hasIndexingScope, inspectUrl, isPermissionDeniedError, isValidGscDate, progressBar, requestIndexing, rowWithMetricDefaults, storageError, submitSitemap, toIsoDate };
542
+ export { ApiSite, ApiSitemap, ApiSitemapContent, Auth, AuthClient, AuthOptions, BackfillProgress, CallOptions, DAYS_PER_RANGE, DataRow, DimensionFilter, DimensionFilterGroup, GSC_FINALIZED_LAG_DAYS, GSC_FRESHEST_LAG_DAYS, GSC_QUOTAS, GSC_RETENTION_MONTHS, GoogleSearchConsoleClient, GoogleSearchConsoleClientOptions, GscError, GscErrorKind, GscdumpApiOptions, INDEXING_DAILY_LIMIT, INDEXING_EFFECTIVE_LIMIT, INDEXING_ISSUE_FILTERS, INDEXING_ISSUE_LABELS, INDEXING_ISSUE_SEVERITY, IndexStatusResult, IndexingIssueType, IndexingMetadata, IndexingNotificationType, IndexingResult, InspectUrlIndexResponse, InspectUrlResult, MS_PER_DAY, MobileUsabilityResult, Period, PublishUrlNotificationResponse, RequiredNonNullable, ResolvedAnalyticsRange, RichResultsResult, SearchAnalyticsQuery, SearchAnalyticsResponse, Site, SiteAnalytics, UrlInspectionResult, UrlNotificationMetadata, VerificationMethod, VerificationSite, VerificationSiteType, VerificationToken, VerificationWebResource, addDays, addSite, batchInspectUrls, batchRequestIndexing, classifyError, countDays, createAuth, createFetch, daysAgo, deleteSite, deleteSitemap, fetchSitemap, fetchSitemaps, fetchSites, fetchSitesWithSitemaps, formatErrorForCli, generateGscDateRange, getBackfillProgress, getDateRange, getFreshestGscDate, getIndexingMetadata, getLatestGscDate, getNextDate, getOldestGscDate, getPendingDates, getPreviousDate, getPstDate, getVerificationToken, googleSearchConsole, groupIntoRanges, gscdumpApi, hasGscReadScope, hasGscWriteScope, hasIndexingScope, inspectUrl, isPermissionDeniedError, isValidGscDate, listVerifiedSites, progressBar, requestIndexing, rowWithMetricDefaults, siteUrlToVerificationSite, storageError, submitSitemap, toIsoDate, verificationMethodsFor, verifySite };
package/dist/index.mjs CHANGED
@@ -1,13 +1,30 @@
1
1
  import { ofetch } from "ofetch";
2
2
  async function runSequentialBatch(items, operation, options = {}) {
3
- const { delayMs = 0, onProgress } = options;
4
- const results = [];
5
- for (let i = 0; i < items.length; i++) {
6
- const result = await operation(items[i], i);
7
- results.push(result);
8
- onProgress?.(result, i, items.length);
9
- if (i < items.length - 1 && delayMs > 0) await new Promise((r) => setTimeout(r, delayMs));
3
+ const { delayMs = 0, concurrency = 1, onProgress } = options;
4
+ const results = Array.from({ length: items.length });
5
+ let completed = 0;
6
+ if (concurrency <= 1) {
7
+ for (let i = 0; i < items.length; i++) {
8
+ const result = await operation(items[i], i);
9
+ results[i] = result;
10
+ onProgress?.(result, i, items.length);
11
+ if (i < items.length - 1 && delayMs > 0) await new Promise((r) => setTimeout(r, delayMs));
12
+ }
13
+ return results;
10
14
  }
15
+ const cursor = { i: 0 };
16
+ const worker = async () => {
17
+ while (true) {
18
+ const i = cursor.i++;
19
+ if (i >= items.length) return;
20
+ const result = await operation(items[i], i);
21
+ results[i] = result;
22
+ completed++;
23
+ onProgress?.(result, completed - 1, items.length);
24
+ if (delayMs > 0) await new Promise((r) => setTimeout(r, delayMs));
25
+ }
26
+ };
27
+ await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, worker));
11
28
  return results;
12
29
  }
13
30
  async function requestIndexing(client, url, options = {}) {
@@ -26,9 +43,10 @@ async function getIndexingMetadata(client, url) {
26
43
  }));
27
44
  }
28
45
  async function batchRequestIndexing(client, urls, options = {}) {
29
- const { type = "URL_UPDATED", delayMs = 100, onProgress } = options;
46
+ const { type = "URL_UPDATED", delayMs = 100, concurrency, onProgress } = options;
30
47
  return runSequentialBatch(urls, (url) => requestIndexing(client, url, { type }), {
31
48
  delayMs,
49
+ concurrency,
32
50
  onProgress
33
51
  });
34
52
  }
@@ -40,7 +58,7 @@ async function inspectUrl(client, siteUrl, inspectionUrl) {
40
58
  };
41
59
  }
42
60
  async function batchInspectUrls(client, siteUrl, urls, options = {}) {
43
- const { delayMs = 200, onProgress } = options;
61
+ const { delayMs = 200, concurrency, onProgress } = options;
44
62
  return runSequentialBatch(urls, async (url) => {
45
63
  const { inspection, isIndexed } = await inspectUrl(client, siteUrl, url);
46
64
  return {
@@ -50,6 +68,7 @@ async function batchInspectUrls(client, siteUrl, urls, options = {}) {
50
68
  };
51
69
  }, {
52
70
  delayMs,
71
+ concurrency,
53
72
  onProgress
54
73
  });
55
74
  }
@@ -78,6 +97,52 @@ async function submitSitemap(client, siteUrl, feedpath) {
78
97
  async function deleteSitemap(client, siteUrl, feedpath) {
79
98
  return client.sitemaps.delete(siteUrl, feedpath);
80
99
  }
100
+ async function addSite(client, siteUrl) {
101
+ return client.sites.add(siteUrl);
102
+ }
103
+ async function deleteSite(client, siteUrl) {
104
+ return client.sites.delete(siteUrl);
105
+ }
106
+ const SC_DOMAIN_PREFIX = "sc-domain:";
107
+ function siteUrlToVerificationSite(siteUrl) {
108
+ if (siteUrl.startsWith(SC_DOMAIN_PREFIX)) return {
109
+ type: "INET_DOMAIN",
110
+ identifier: siteUrl.slice(10)
111
+ };
112
+ return {
113
+ type: "SITE",
114
+ identifier: siteUrl
115
+ };
116
+ }
117
+ function verificationMethodsFor(site) {
118
+ if (site.type === "INET_DOMAIN") return ["DNS_TXT", "DNS_CNAME"];
119
+ return [
120
+ "META",
121
+ "FILE",
122
+ "ANALYTICS",
123
+ "TAG_MANAGER"
124
+ ];
125
+ }
126
+ async function getVerificationToken(client, siteUrl, method) {
127
+ const site = siteUrlToVerificationSite(siteUrl);
128
+ return {
129
+ ...await client.verification.getToken({
130
+ site,
131
+ verificationMethod: method
132
+ }),
133
+ site
134
+ };
135
+ }
136
+ async function verifySite(client, siteUrl, method) {
137
+ const site = siteUrlToVerificationSite(siteUrl);
138
+ return client.verification.insert({
139
+ site,
140
+ verificationMethod: method
141
+ });
142
+ }
143
+ async function listVerifiedSites(client) {
144
+ return client.verification.list();
145
+ }
81
146
  const MS_PER_DAY = 864e5;
82
147
  function toIsoDate(d) {
83
148
  return d.toISOString().slice(0, 10);
@@ -377,11 +442,38 @@ function gscdumpApi(options) {
377
442
  startRow += rows.length;
378
443
  }
379
444
  },
380
- sites: async (opts) => {
381
- return (await fetch("/api/sites", { signal: opts?.signal })).sites.map((s) => ({
382
- siteUrl: s.gscSiteUrl,
383
- permissionLevel: s.permissionLevel || "siteOwner"
384
- }));
445
+ sites: (() => {
446
+ const list = async (opts) => {
447
+ return (await fetch("/api/sites", { signal: opts?.signal })).sites.map((s) => ({
448
+ siteUrl: s.gscSiteUrl,
449
+ permissionLevel: s.permissionLevel || "siteOwner"
450
+ }));
451
+ };
452
+ const unsupported = (op) => () => {
453
+ throw new Error(`sites.${op} not available via gscdump API. Use googleSearchConsole() with OAuth credentials.`);
454
+ };
455
+ return Object.assign(list, {
456
+ list,
457
+ add: unsupported("add"),
458
+ delete: unsupported("delete")
459
+ });
460
+ })(),
461
+ verification: {
462
+ getToken: () => {
463
+ throw new Error("Site Verification API not available via gscdump API. Use googleSearchConsole() with OAuth credentials.");
464
+ },
465
+ insert: () => {
466
+ throw new Error("Site Verification API not available via gscdump API. Use googleSearchConsole() with OAuth credentials.");
467
+ },
468
+ list: () => {
469
+ throw new Error("Site Verification API not available via gscdump API. Use googleSearchConsole() with OAuth credentials.");
470
+ },
471
+ get: () => {
472
+ throw new Error("Site Verification API not available via gscdump API. Use googleSearchConsole() with OAuth credentials.");
473
+ },
474
+ delete: () => {
475
+ throw new Error("Site Verification API not available via gscdump API. Use googleSearchConsole() with OAuth credentials.");
476
+ }
385
477
  },
386
478
  inspect: () => {
387
479
  throw new Error("URL inspection not available via gscdump API. Use googleSearchConsole() with OAuth credentials.");
@@ -413,6 +505,7 @@ function gscdumpApi(options) {
413
505
  }
414
506
  const GSC_API = "https://searchconsole.googleapis.com";
415
507
  const INDEXING_API = "https://indexing.googleapis.com";
508
+ const SITE_VERIFICATION_API = "https://www.googleapis.com/siteVerification/v1";
416
509
  function createAuth(options) {
417
510
  let credentials = { refresh_token: options.refreshToken };
418
511
  return {
@@ -529,8 +622,42 @@ function googleSearchConsole(auth, options = {}) {
529
622
  startRow += rows.length;
530
623
  }
531
624
  },
532
- sites: async (opts) => {
533
- return (await fetch(`${GSC_API}/webmasters/v3/sites`, { signal: opts?.signal })).siteEntry || [];
625
+ sites: (() => {
626
+ const list = async (opts) => {
627
+ return (await fetch(`${GSC_API}/webmasters/v3/sites`, { signal: opts?.signal })).siteEntry || [];
628
+ };
629
+ return Object.assign(list, {
630
+ list,
631
+ add: (siteUrl, opts) => fetch(`${GSC_API}/webmasters/v3/sites/${encodeURIComponent(siteUrl)}`, {
632
+ method: "PUT",
633
+ signal: opts?.signal
634
+ }),
635
+ delete: (siteUrl, opts) => fetch(`${GSC_API}/webmasters/v3/sites/${encodeURIComponent(siteUrl)}`, {
636
+ method: "DELETE",
637
+ signal: opts?.signal
638
+ })
639
+ });
640
+ })(),
641
+ verification: {
642
+ getToken: (params, opts) => fetch(`${SITE_VERIFICATION_API}/token`, {
643
+ method: "POST",
644
+ body: params,
645
+ signal: opts?.signal
646
+ }),
647
+ insert: (params, opts) => fetch(`${SITE_VERIFICATION_API}/webResource`, {
648
+ method: "POST",
649
+ query: { verificationMethod: params.verificationMethod },
650
+ body: { site: params.site },
651
+ signal: opts?.signal
652
+ }),
653
+ list: async (opts) => {
654
+ return (await fetch(`${SITE_VERIFICATION_API}/webResource`, { signal: opts?.signal })).items || [];
655
+ },
656
+ get: (id, opts) => fetch(`${SITE_VERIFICATION_API}/webResource/${encodeURIComponent(id)}`, { signal: opts?.signal }),
657
+ delete: (id, opts) => fetch(`${SITE_VERIFICATION_API}/webResource/${encodeURIComponent(id)}`, {
658
+ method: "DELETE",
659
+ signal: opts?.signal
660
+ })
534
661
  },
535
662
  inspect: (siteUrl, url, opts) => fetch(`${GSC_API}/v1/urlInspection/index:inspect`, {
536
663
  method: "POST",
@@ -796,4 +923,4 @@ function hasIndexingScope(scopes) {
796
923
  if (!scopes) return false;
797
924
  return scopes.includes("googleapis.com/auth/indexing");
798
925
  }
799
- export { DAYS_PER_RANGE, GSC_FINALIZED_LAG_DAYS, GSC_FRESHEST_LAG_DAYS, GSC_QUOTAS, GSC_RETENTION_MONTHS, INDEXING_DAILY_LIMIT, INDEXING_EFFECTIVE_LIMIT, INDEXING_ISSUE_FILTERS, INDEXING_ISSUE_LABELS, INDEXING_ISSUE_SEVERITY, MS_PER_DAY, addDays, batchInspectUrls, batchRequestIndexing, classifyError, countDays, createAuth, createFetch, daysAgo, deleteSitemap, fetchSitemap, fetchSitemaps, fetchSites, fetchSitesWithSitemaps, formatErrorForCli, generateGscDateRange, getBackfillProgress, getDateRange, getFreshestGscDate, getIndexingMetadata, getLatestGscDate, getNextDate, getOldestGscDate, getPendingDates, getPreviousDate, getPstDate, googleSearchConsole, groupIntoRanges, gscdumpApi, hasGscReadScope, hasGscWriteScope, hasIndexingScope, inspectUrl, isPermissionDeniedError, isValidGscDate, progressBar, requestIndexing, rowWithMetricDefaults, storageError, submitSitemap, toIsoDate };
926
+ export { DAYS_PER_RANGE, GSC_FINALIZED_LAG_DAYS, GSC_FRESHEST_LAG_DAYS, GSC_QUOTAS, GSC_RETENTION_MONTHS, INDEXING_DAILY_LIMIT, INDEXING_EFFECTIVE_LIMIT, INDEXING_ISSUE_FILTERS, INDEXING_ISSUE_LABELS, INDEXING_ISSUE_SEVERITY, MS_PER_DAY, addDays, addSite, batchInspectUrls, batchRequestIndexing, classifyError, countDays, createAuth, createFetch, daysAgo, deleteSite, deleteSitemap, fetchSitemap, fetchSitemaps, fetchSites, fetchSitesWithSitemaps, formatErrorForCli, generateGscDateRange, getBackfillProgress, getDateRange, getFreshestGscDate, getIndexingMetadata, getLatestGscDate, getNextDate, getOldestGscDate, getPendingDates, getPreviousDate, getPstDate, getVerificationToken, googleSearchConsole, groupIntoRanges, gscdumpApi, hasGscReadScope, hasGscWriteScope, hasIndexingScope, inspectUrl, isPermissionDeniedError, isValidGscDate, listVerifiedSites, progressBar, requestIndexing, rowWithMetricDefaults, siteUrlToVerificationSite, storageError, submitSitemap, toIsoDate, verificationMethodsFor, verifySite };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gscdump",
3
3
  "type": "module",
4
- "version": "0.8.0",
4
+ "version": "0.8.1",
5
5
  "description": "Google Search Console API wrapper with typed query builder, streaming pagination, and SEO analysis functions",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -102,7 +102,7 @@
102
102
  "dayjs": "^1.11.20",
103
103
  "defu": "^6.1.7",
104
104
  "ofetch": "^1.5.1",
105
- "ufo": "^1.6.3"
105
+ "ufo": "^1.6.4"
106
106
  },
107
107
  "devDependencies": {
108
108
  "@googleapis/indexing": "^6.0.1",