@power-seo/search-console 1.0.4 → 1.0.8

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.cjs CHANGED
@@ -1,6 +1,39 @@
1
- 'use strict';
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
2
19
 
3
- var core = require('@power-seo/core');
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ GSCApiError: () => GSCApiError,
24
+ createGSCClient: () => createGSCClient,
25
+ createTokenManager: () => createTokenManager,
26
+ deleteSitemap: () => deleteSitemap,
27
+ exchangeRefreshToken: () => exchangeRefreshToken,
28
+ getServiceAccountToken: () => getServiceAccountToken,
29
+ inspectUrl: () => inspectUrl,
30
+ inspectUrlDirect: () => inspectUrlDirect,
31
+ listSitemaps: () => listSitemaps,
32
+ querySearchAnalytics: () => querySearchAnalytics,
33
+ querySearchAnalyticsAll: () => querySearchAnalyticsAll,
34
+ submitSitemap: () => submitSitemap
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
4
37
 
5
38
  // src/types.ts
6
39
  var GSCApiError = class extends Error {
@@ -103,19 +136,22 @@ function createTokenManager(fetchToken) {
103
136
  }
104
137
  };
105
138
  }
139
+
140
+ // src/client.ts
141
+ var import_core = require("@power-seo/core");
106
142
  var DEFAULT_BASE_URL = "https://searchconsole.googleapis.com/webmasters/v3";
107
143
  var DEFAULT_RATE_LIMIT = 1200;
108
144
  var DEFAULT_MAX_RETRIES = 3;
109
145
  function createGSCClient(config) {
110
146
  const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
111
147
  const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
112
- const bucket = core.createTokenBucket(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT);
148
+ const bucket = (0, import_core.createTokenBucket)(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT);
113
149
  async function request(path, options) {
114
- const waitTime = core.getWaitTime(bucket);
150
+ const waitTime = (0, import_core.getWaitTime)(bucket);
115
151
  if (waitTime > 0) {
116
- await core.sleep(waitTime);
152
+ await (0, import_core.sleep)(waitTime);
117
153
  }
118
- core.consumeToken(bucket);
154
+ (0, import_core.consumeToken)(bucket);
119
155
  const token = await config.auth.getToken();
120
156
  const url = `${baseUrl}${path}`;
121
157
  let lastError = null;
@@ -144,7 +180,7 @@ function createGSCClient(config) {
144
180
  }
145
181
  lastError = error;
146
182
  const backoff = Math.min(1e3 * Math.pow(2, attempt), 3e4);
147
- await core.sleep(backoff);
183
+ await (0, import_core.sleep)(backoff);
148
184
  } catch (err) {
149
185
  if (err instanceof GSCApiError) {
150
186
  if (!err.retryable || attempt === maxRetries) {
@@ -152,7 +188,7 @@ function createGSCClient(config) {
152
188
  }
153
189
  lastError = err;
154
190
  const backoff = Math.min(1e3 * Math.pow(2, attempt), 3e4);
155
- await core.sleep(backoff);
191
+ await (0, import_core.sleep)(backoff);
156
192
  } else {
157
193
  throw err;
158
194
  }
@@ -251,18 +287,19 @@ async function deleteSitemap(client, feedpath) {
251
287
  const encodedFeed = encodeURIComponent(feedpath);
252
288
  await client.request(`/sites/${siteUrl}/sitemaps/${encodedFeed}`, { method: "DELETE" });
253
289
  }
254
-
255
- exports.GSCApiError = GSCApiError;
256
- exports.createGSCClient = createGSCClient;
257
- exports.createTokenManager = createTokenManager;
258
- exports.deleteSitemap = deleteSitemap;
259
- exports.exchangeRefreshToken = exchangeRefreshToken;
260
- exports.getServiceAccountToken = getServiceAccountToken;
261
- exports.inspectUrl = inspectUrl;
262
- exports.inspectUrlDirect = inspectUrlDirect;
263
- exports.listSitemaps = listSitemaps;
264
- exports.querySearchAnalytics = querySearchAnalytics;
265
- exports.querySearchAnalyticsAll = querySearchAnalyticsAll;
266
- exports.submitSitemap = submitSitemap;
267
- //# sourceMappingURL=index.cjs.map
290
+ // Annotate the CommonJS export names for ESM import in node:
291
+ 0 && (module.exports = {
292
+ GSCApiError,
293
+ createGSCClient,
294
+ createTokenManager,
295
+ deleteSitemap,
296
+ exchangeRefreshToken,
297
+ getServiceAccountToken,
298
+ inspectUrl,
299
+ inspectUrlDirect,
300
+ listSitemaps,
301
+ querySearchAnalytics,
302
+ querySearchAnalyticsAll,
303
+ submitSitemap
304
+ });
268
305
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/auth.ts","../src/client.ts","../src/analytics.ts","../src/inspection.ts","../src/sitemaps.ts"],"names":["createTokenBucket","getWaitTime","sleep","consumeToken"],"mappings":"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","file":"index.cjs","sourcesContent":["// ============================================================================\n// @power-seo/search-console — Types\n// ============================================================================\n\n// --- Auth Types ---\n\nexport interface OAuthCredentials {\n clientId: string;\n clientSecret: string;\n refreshToken: string;\n}\n\nexport interface ServiceAccountCredentials {\n clientEmail: string;\n privateKeyId: string;\n signJwt: (payload: JwtPayload) => Promise<string>;\n}\n\nexport interface JwtPayload {\n iss: string;\n scope: string;\n aud: string;\n exp: number;\n iat: number;\n}\n\nexport interface TokenResult {\n accessToken: string;\n expiresAt: number;\n}\n\nexport interface TokenManager {\n getToken: () => Promise<string>;\n invalidate: () => void;\n}\n\n// --- Client Types ---\n\nexport interface GSCClientConfig {\n auth: TokenManager;\n siteUrl: string;\n rateLimitPerMinute?: number;\n maxRetries?: number;\n baseUrl?: string;\n}\n\nexport interface GSCClient {\n request: <T>(path: string, options?: RequestOptions) => Promise<T>;\n siteUrl: string;\n}\n\nexport interface RequestOptions {\n method?: string;\n body?: unknown;\n signal?: globalThis.AbortSignal;\n}\n\n// --- Error ---\n\nexport class GSCApiError extends Error {\n readonly status: number;\n readonly code: string;\n readonly retryable: boolean;\n\n constructor(message: string, status: number, code: string) {\n super(message);\n this.name = 'GSCApiError';\n this.status = status;\n this.code = code;\n this.retryable = status === 429 || status >= 500;\n }\n}\n\n// --- Analytics Types ---\n\nexport type SearchType = 'web' | 'image' | 'video' | 'news' | 'discover' | 'googleNews';\nexport type Dimension = 'query' | 'page' | 'country' | 'device' | 'date' | 'searchAppearance';\nexport type AggregationType = 'auto' | 'byPage' | 'byProperty';\nexport type DataState = 'all' | 'final';\n\nexport interface DimensionFilter {\n dimension: Dimension;\n operator:\n | 'equals'\n | 'notEquals'\n | 'contains'\n | 'notContains'\n | 'includingRegex'\n | 'excludingRegex';\n expression: string;\n}\n\nexport interface DimensionFilterGroup {\n groupType?: 'and';\n filters: DimensionFilter[];\n}\n\nexport interface SearchAnalyticsRequest {\n startDate: string;\n endDate: string;\n dimensions?: Dimension[];\n searchType?: SearchType;\n dimensionFilterGroups?: DimensionFilterGroup[];\n aggregationType?: AggregationType;\n rowLimit?: number;\n startRow?: number;\n dataState?: DataState;\n}\n\nexport interface SearchAnalyticsRow {\n keys: string[];\n clicks: number;\n impressions: number;\n ctr: number;\n position: number;\n}\n\nexport interface SearchAnalyticsResponse {\n rows: SearchAnalyticsRow[];\n responseAggregationType: string;\n}\n\n// --- Inspection Types ---\n\nexport interface InspectionRequest {\n inspectionUrl: string;\n languageCode?: string;\n}\n\nexport type VerdictState = 'PASS' | 'PARTIAL' | 'FAIL' | 'VERDICT_UNSPECIFIED' | 'NEUTRAL';\nexport type CrawlState =\n | 'SUCCESSFUL'\n | 'NOT_FOUND'\n | 'SERVER_ERROR'\n | 'ROBOTS_BLOCKED'\n | 'REDIRECT_ERROR'\n | 'ACCESS_DENIED'\n | 'ACCESS_FORBIDDEN';\nexport type IndexState =\n | 'INDEXED'\n | 'NOT_INDEXED'\n | 'SUBMITTED_AND_INDEXED'\n | 'CRAWLED_NOT_INDEXED'\n | 'DISCOVERED_NOT_INDEXED'\n | 'PAGE_WITH_REDIRECT';\nexport type RobotsTxtState = 'ALLOWED' | 'DISALLOWED';\n\nexport interface IndexStatusResult {\n verdict: VerdictState;\n coverageState: IndexState;\n robotsTxtState: RobotsTxtState;\n indexingState: string;\n lastCrawlTime?: string;\n pageFetchState?: CrawlState;\n referringUrls?: string[];\n sitemap?: string[];\n}\n\nexport interface MobileUsabilityResult {\n verdict: VerdictState;\n issues?: Array<{ issueType: string; severity: string; message: string }>;\n}\n\nexport interface RichResultsResult {\n verdict: VerdictState;\n detectedItems?: Array<{\n richResultType: string;\n items: Array<{ name: string; issues?: Array<{ issueMessage: string; severity: string }> }>;\n }>;\n}\n\nexport interface InspectionResult {\n inspectionResultLink: string;\n indexStatusResult: IndexStatusResult;\n mobileUsabilityResult?: MobileUsabilityResult;\n richResultsResult?: RichResultsResult;\n}\n\n// --- Sitemap Types ---\n\nexport type SitemapType = 'sitemap' | 'atomFeed' | 'rssFeed' | 'notSitemap';\n\nexport interface SitemapEntry {\n path: string;\n lastSubmitted?: string;\n isPending: boolean;\n isSitemapsIndex: boolean;\n type: SitemapType;\n lastDownloaded?: string;\n warnings: number;\n errors: number;\n contents?: Array<{ type: string; submitted: number; indexed: number }>;\n}\n\nexport interface SitemapListResponse {\n sitemap: SitemapEntry[];\n}\n","// ============================================================================\n// @power-seo/search-console — Auth\n// ============================================================================\n\nimport type {\n OAuthCredentials,\n ServiceAccountCredentials,\n TokenResult,\n TokenManager,\n} from './types.js';\nimport { GSCApiError } from './types.js';\n\nconst TOKEN_URL = 'https://oauth2.googleapis.com/token';\nconst GSC_SCOPE = 'https://www.googleapis.com/auth/webmasters.readonly';\nconst TOKEN_BUFFER_MS = 60_000;\n\nexport async function exchangeRefreshToken(credentials: OAuthCredentials): Promise<TokenResult> {\n const body = new globalThis.URLSearchParams({\n client_id: credentials.clientId,\n client_secret: credentials.clientSecret,\n refresh_token: credentials.refreshToken,\n grant_type: 'refresh_token',\n });\n\n const response = await globalThis.fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new GSCApiError(\n `Token exchange failed: ${text}`,\n response.status,\n 'TOKEN_EXCHANGE_ERROR',\n );\n }\n\n const data = (await response.json()) as { access_token: string; expires_in: number };\n return {\n accessToken: data.access_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n}\n\nexport async function getServiceAccountToken(\n credentials: ServiceAccountCredentials,\n): Promise<TokenResult> {\n const now = Math.floor(Date.now() / 1000);\n const payload = {\n iss: credentials.clientEmail,\n scope: GSC_SCOPE,\n aud: TOKEN_URL,\n exp: now + 3600,\n iat: now,\n };\n\n const assertion = await credentials.signJwt(payload);\n\n const body = new globalThis.URLSearchParams({\n grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',\n assertion,\n });\n\n const response = await globalThis.fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new GSCApiError(\n `Service account token failed: ${text}`,\n response.status,\n 'SERVICE_ACCOUNT_ERROR',\n );\n }\n\n const data = (await response.json()) as { access_token: string; expires_in: number };\n return {\n accessToken: data.access_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n}\n\nexport function createTokenManager(fetchToken: () => Promise<TokenResult>): TokenManager {\n let cached: TokenResult | null = null;\n let pending: Promise<string> | null = null;\n\n return {\n async getToken(): Promise<string> {\n if (cached && cached.expiresAt > Date.now() + TOKEN_BUFFER_MS) {\n return cached.accessToken;\n }\n\n if (pending) {\n return pending;\n }\n\n pending = fetchToken().then((result) => {\n cached = result;\n pending = null;\n return result.accessToken;\n });\n\n return pending;\n },\n\n invalidate(): void {\n cached = null;\n pending = null;\n },\n };\n}\n","// ============================================================================\n// @power-seo/search-console — Client\n// ============================================================================\n\nimport type { GSCClientConfig, GSCClient, RequestOptions } from './types.js';\nimport { GSCApiError } from './types.js';\nimport { createTokenBucket, consumeToken, getWaitTime, sleep } from '@power-seo/core';\n\nconst DEFAULT_BASE_URL = 'https://searchconsole.googleapis.com/webmasters/v3';\nconst DEFAULT_RATE_LIMIT = 1200;\nconst DEFAULT_MAX_RETRIES = 3;\n\nexport function createGSCClient(config: GSCClientConfig): GSCClient {\n const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const bucket = createTokenBucket(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT);\n\n async function request<T>(path: string, options?: RequestOptions): Promise<T> {\n const waitTime = getWaitTime(bucket);\n if (waitTime > 0) {\n await sleep(waitTime);\n }\n consumeToken(bucket);\n\n const token = await config.auth.getToken();\n const url = `${baseUrl}${path}`;\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await globalThis.fetch(url, {\n method: options?.method ?? 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal: options?.signal,\n });\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const text = await response.text();\n const error = new GSCApiError(\n `GSC API error: ${response.status} ${text}`,\n response.status,\n `HTTP_${response.status}`,\n );\n\n if (!error.retryable || attempt === maxRetries) {\n throw error;\n }\n\n lastError = error;\n const backoff = Math.min(1000 * Math.pow(2, attempt), 30_000);\n await sleep(backoff);\n } catch (err) {\n if (err instanceof GSCApiError) {\n if (!err.retryable || attempt === maxRetries) {\n throw err;\n }\n lastError = err;\n const backoff = Math.min(1000 * Math.pow(2, attempt), 30_000);\n await sleep(backoff);\n } else {\n throw err;\n }\n }\n }\n\n throw lastError ?? new GSCApiError('Request failed', 500, 'UNKNOWN');\n }\n\n return {\n request,\n siteUrl: config.siteUrl,\n };\n}\n","// ============================================================================\n// @power-seo/search-console — Analytics\n// ============================================================================\n\nimport type {\n GSCClient,\n SearchAnalyticsRequest,\n SearchAnalyticsResponse,\n SearchAnalyticsRow,\n} from './types.js';\n\nconst MAX_ROW_LIMIT = 25000;\nconst DEFAULT_ROW_LIMIT = 1000;\n\nexport async function querySearchAnalytics(\n client: GSCClient,\n request: SearchAnalyticsRequest,\n): Promise<SearchAnalyticsResponse> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const body = {\n ...request,\n rowLimit: Math.min(request.rowLimit ?? DEFAULT_ROW_LIMIT, MAX_ROW_LIMIT),\n };\n\n return client.request<SearchAnalyticsResponse>(`/sites/${siteUrl}/searchAnalytics/query`, {\n method: 'POST',\n body,\n });\n}\n\nexport async function querySearchAnalyticsAll(\n client: GSCClient,\n request: Omit<SearchAnalyticsRequest, 'startRow' | 'rowLimit'>,\n): Promise<SearchAnalyticsRow[]> {\n const allRows: SearchAnalyticsRow[] = [];\n let startRow = 0;\n\n while (true) {\n const response = await querySearchAnalytics(client, {\n ...request,\n rowLimit: MAX_ROW_LIMIT,\n startRow,\n });\n\n const rows = response.rows ?? [];\n allRows.push(...rows);\n\n if (rows.length < MAX_ROW_LIMIT) {\n break;\n }\n\n startRow += rows.length;\n }\n\n return allRows;\n}\n","// ============================================================================\n// @power-seo/search-console — URL Inspection\n// ============================================================================\n\nimport type { GSCClient, InspectionRequest, InspectionResult } from './types.js';\n\nconst INSPECTION_BASE = 'https://searchconsole.googleapis.com/v1/urlInspection/index:inspect';\n\nexport async function inspectUrl(\n client: GSCClient,\n request: InspectionRequest,\n): Promise<InspectionResult> {\n const body = {\n inspectionUrl: request.inspectionUrl,\n siteUrl: client.siteUrl,\n languageCode: request.languageCode ?? 'en',\n };\n\n const token = await client.request<{ inspectionResult: InspectionResult }>('', {\n method: 'POST',\n body,\n });\n\n // The URL Inspection API has a different base URL, so we use a direct fetch.\n // However, since the client handles auth and retries, we override for the standard path approach.\n // The API endpoint doesn't follow the webmasters/v3 pattern.\n // We'll use the client's request method with a custom approach.\n\n // Actually, let's do a direct fetch since the base URL differs:\n return token.inspectionResult;\n}\n\nexport async function inspectUrlDirect(\n getToken: () => Promise<string>,\n siteUrl: string,\n inspectionUrl: string,\n languageCode?: string,\n): Promise<InspectionResult> {\n const token = await getToken();\n\n const response = await globalThis.fetch(INSPECTION_BASE, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n inspectionUrl,\n siteUrl,\n languageCode: languageCode ?? 'en',\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`URL Inspection API error: ${response.status} ${text}`);\n }\n\n const data = (await response.json()) as { inspectionResult: InspectionResult };\n return data.inspectionResult;\n}\n","// ============================================================================\n// @power-seo/search-console — Sitemaps\n// ============================================================================\n\nimport type { GSCClient, SitemapEntry, SitemapListResponse } from './types.js';\n\nexport async function listSitemaps(client: GSCClient): Promise<SitemapEntry[]> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const response = await client.request<SitemapListResponse>(`/sites/${siteUrl}/sitemaps`);\n return response.sitemap ?? [];\n}\n\nexport async function submitSitemap(client: GSCClient, feedpath: string): Promise<void> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const encodedFeed = encodeURIComponent(feedpath);\n await client.request<void>(`/sites/${siteUrl}/sitemaps/${encodedFeed}`, { method: 'PUT' });\n}\n\nexport async function deleteSitemap(client: GSCClient, feedpath: string): Promise<void> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const encodedFeed = encodeURIComponent(feedpath);\n await client.request<void>(`/sites/${siteUrl}/sitemaps/${encodedFeed}`, { method: 'DELETE' });\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/auth.ts","../src/client.ts","../src/analytics.ts","../src/inspection.ts","../src/sitemaps.ts"],"sourcesContent":["// @power-seo/search-console — Main Entry Point\n// ----------------------------------------------------------------------------\n\n// Types\nexport type {\n OAuthCredentials,\n ServiceAccountCredentials,\n JwtPayload,\n TokenResult,\n TokenManager,\n GSCClientConfig,\n GSCClient,\n RequestOptions,\n SearchType,\n Dimension,\n AggregationType,\n DataState,\n DimensionFilter,\n DimensionFilterGroup,\n SearchAnalyticsRequest,\n SearchAnalyticsRow,\n SearchAnalyticsResponse,\n InspectionRequest,\n VerdictState,\n CrawlState,\n IndexState,\n RobotsTxtState,\n IndexStatusResult,\n MobileUsabilityResult,\n RichResultsResult,\n InspectionResult,\n SitemapType,\n SitemapEntry,\n SitemapListResponse,\n} from './types.js';\n\n// Error class\nexport { GSCApiError } from './types.js';\n\n// Auth\nexport { exchangeRefreshToken, getServiceAccountToken, createTokenManager } from './auth.js';\n\n// Client\nexport { createGSCClient } from './client.js';\n\n// Analytics\nexport { querySearchAnalytics, querySearchAnalyticsAll } from './analytics.js';\n\n// URL Inspection\nexport { inspectUrl, inspectUrlDirect } from './inspection.js';\n\n// Sitemaps\nexport { listSitemaps, submitSitemap, deleteSitemap } from './sitemaps.js';\n","// @power-seo/search-console — Types\n// ----------------------------------------------------------------------------\n\n// --- Auth Types ---\n\nexport interface OAuthCredentials {\n clientId: string;\n clientSecret: string;\n refreshToken: string;\n}\n\nexport interface ServiceAccountCredentials {\n clientEmail: string;\n privateKeyId: string;\n signJwt: (payload: JwtPayload) => Promise<string>;\n}\n\nexport interface JwtPayload {\n iss: string;\n scope: string;\n aud: string;\n exp: number;\n iat: number;\n}\n\nexport interface TokenResult {\n accessToken: string;\n expiresAt: number;\n}\n\nexport interface TokenManager {\n getToken: () => Promise<string>;\n invalidate: () => void;\n}\n\n// --- Client Types ---\n\nexport interface GSCClientConfig {\n auth: TokenManager;\n siteUrl: string;\n rateLimitPerMinute?: number;\n maxRetries?: number;\n baseUrl?: string;\n}\n\nexport interface GSCClient {\n request: <T>(path: string, options?: RequestOptions) => Promise<T>;\n siteUrl: string;\n}\n\nexport interface RequestOptions {\n method?: string;\n body?: unknown;\n signal?: globalThis.AbortSignal;\n}\n\n// --- Error ---\n\nexport class GSCApiError extends Error {\n readonly status: number;\n readonly code: string;\n readonly retryable: boolean;\n\n constructor(message: string, status: number, code: string) {\n super(message);\n this.name = 'GSCApiError';\n this.status = status;\n this.code = code;\n this.retryable = status === 429 || status >= 500;\n }\n}\n\n// --- Analytics Types ---\n\nexport type SearchType = 'web' | 'image' | 'video' | 'news' | 'discover' | 'googleNews';\nexport type Dimension = 'query' | 'page' | 'country' | 'device' | 'date' | 'searchAppearance';\nexport type AggregationType = 'auto' | 'byPage' | 'byProperty';\nexport type DataState = 'all' | 'final';\n\nexport interface DimensionFilter {\n dimension: Dimension;\n operator:\n | 'equals'\n | 'notEquals'\n | 'contains'\n | 'notContains'\n | 'includingRegex'\n | 'excludingRegex';\n expression: string;\n}\n\nexport interface DimensionFilterGroup {\n groupType?: 'and';\n filters: DimensionFilter[];\n}\n\nexport interface SearchAnalyticsRequest {\n startDate: string;\n endDate: string;\n dimensions?: Dimension[];\n searchType?: SearchType;\n dimensionFilterGroups?: DimensionFilterGroup[];\n aggregationType?: AggregationType;\n rowLimit?: number;\n startRow?: number;\n dataState?: DataState;\n}\n\nexport interface SearchAnalyticsRow {\n keys: string[];\n clicks: number;\n impressions: number;\n ctr: number;\n position: number;\n}\n\nexport interface SearchAnalyticsResponse {\n rows: SearchAnalyticsRow[];\n responseAggregationType: string;\n}\n\n// --- Inspection Types ---\n\nexport interface InspectionRequest {\n inspectionUrl: string;\n languageCode?: string;\n}\n\nexport type VerdictState = 'PASS' | 'PARTIAL' | 'FAIL' | 'VERDICT_UNSPECIFIED' | 'NEUTRAL';\nexport type CrawlState =\n | 'SUCCESSFUL'\n | 'NOT_FOUND'\n | 'SERVER_ERROR'\n | 'ROBOTS_BLOCKED'\n | 'REDIRECT_ERROR'\n | 'ACCESS_DENIED'\n | 'ACCESS_FORBIDDEN';\nexport type IndexState =\n | 'INDEXED'\n | 'NOT_INDEXED'\n | 'SUBMITTED_AND_INDEXED'\n | 'CRAWLED_NOT_INDEXED'\n | 'DISCOVERED_NOT_INDEXED'\n | 'PAGE_WITH_REDIRECT';\nexport type RobotsTxtState = 'ALLOWED' | 'DISALLOWED';\n\nexport interface IndexStatusResult {\n verdict: VerdictState;\n coverageState: IndexState;\n robotsTxtState: RobotsTxtState;\n indexingState: string;\n lastCrawlTime?: string;\n pageFetchState?: CrawlState;\n referringUrls?: string[];\n sitemap?: string[];\n}\n\nexport interface MobileUsabilityResult {\n verdict: VerdictState;\n issues?: Array<{ issueType: string; severity: string; message: string }>;\n}\n\nexport interface RichResultsResult {\n verdict: VerdictState;\n detectedItems?: Array<{\n richResultType: string;\n items: Array<{ name: string; issues?: Array<{ issueMessage: string; severity: string }> }>;\n }>;\n}\n\nexport interface InspectionResult {\n inspectionResultLink: string;\n indexStatusResult: IndexStatusResult;\n mobileUsabilityResult?: MobileUsabilityResult;\n richResultsResult?: RichResultsResult;\n}\n\n// --- Sitemap Types ---\n\nexport type SitemapType = 'sitemap' | 'atomFeed' | 'rssFeed' | 'notSitemap';\n\nexport interface SitemapEntry {\n path: string;\n lastSubmitted?: string;\n isPending: boolean;\n isSitemapsIndex: boolean;\n type: SitemapType;\n lastDownloaded?: string;\n warnings: number;\n errors: number;\n contents?: Array<{ type: string; submitted: number; indexed: number }>;\n}\n\nexport interface SitemapListResponse {\n sitemap: SitemapEntry[];\n}\n","// @power-seo/search-console — Auth\n// ----------------------------------------------------------------------------\n\nimport type {\n OAuthCredentials,\n ServiceAccountCredentials,\n TokenResult,\n TokenManager,\n} from './types.js';\nimport { GSCApiError } from './types.js';\n\nconst TOKEN_URL = 'https://oauth2.googleapis.com/token';\nconst GSC_SCOPE = 'https://www.googleapis.com/auth/webmasters.readonly';\nconst TOKEN_BUFFER_MS = 60_000;\n\nexport async function exchangeRefreshToken(credentials: OAuthCredentials): Promise<TokenResult> {\n const body = new globalThis.URLSearchParams({\n client_id: credentials.clientId,\n client_secret: credentials.clientSecret,\n refresh_token: credentials.refreshToken,\n grant_type: 'refresh_token',\n });\n\n const response = await globalThis.fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new GSCApiError(\n `Token exchange failed: ${text}`,\n response.status,\n 'TOKEN_EXCHANGE_ERROR',\n );\n }\n\n const data = (await response.json()) as { access_token: string; expires_in: number };\n return {\n accessToken: data.access_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n}\n\nexport async function getServiceAccountToken(\n credentials: ServiceAccountCredentials,\n): Promise<TokenResult> {\n const now = Math.floor(Date.now() / 1000);\n const payload = {\n iss: credentials.clientEmail,\n scope: GSC_SCOPE,\n aud: TOKEN_URL,\n exp: now + 3600,\n iat: now,\n };\n\n const assertion = await credentials.signJwt(payload);\n\n const body = new globalThis.URLSearchParams({\n grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',\n assertion,\n });\n\n const response = await globalThis.fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new GSCApiError(\n `Service account token failed: ${text}`,\n response.status,\n 'SERVICE_ACCOUNT_ERROR',\n );\n }\n\n const data = (await response.json()) as { access_token: string; expires_in: number };\n return {\n accessToken: data.access_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n}\n\nexport function createTokenManager(fetchToken: () => Promise<TokenResult>): TokenManager {\n let cached: TokenResult | null = null;\n let pending: Promise<string> | null = null;\n\n return {\n async getToken(): Promise<string> {\n if (cached && cached.expiresAt > Date.now() + TOKEN_BUFFER_MS) {\n return cached.accessToken;\n }\n\n if (pending) {\n return pending;\n }\n\n pending = fetchToken().then((result) => {\n cached = result;\n pending = null;\n return result.accessToken;\n });\n\n return pending;\n },\n\n invalidate(): void {\n cached = null;\n pending = null;\n },\n };\n}\n","// @power-seo/search-console — Client\n// ----------------------------------------------------------------------------\n\nimport type { GSCClientConfig, GSCClient, RequestOptions } from './types.js';\nimport { GSCApiError } from './types.js';\nimport { createTokenBucket, consumeToken, getWaitTime, sleep } from '@power-seo/core';\n\nconst DEFAULT_BASE_URL = 'https://searchconsole.googleapis.com/webmasters/v3';\nconst DEFAULT_RATE_LIMIT = 1200;\nconst DEFAULT_MAX_RETRIES = 3;\n\nexport function createGSCClient(config: GSCClientConfig): GSCClient {\n const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const bucket = createTokenBucket(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT);\n\n async function request<T>(path: string, options?: RequestOptions): Promise<T> {\n const waitTime = getWaitTime(bucket);\n if (waitTime > 0) {\n await sleep(waitTime);\n }\n consumeToken(bucket);\n\n const token = await config.auth.getToken();\n const url = `${baseUrl}${path}`;\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await globalThis.fetch(url, {\n method: options?.method ?? 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal: options?.signal,\n });\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const text = await response.text();\n const error = new GSCApiError(\n `GSC API error: ${response.status} ${text}`,\n response.status,\n `HTTP_${response.status}`,\n );\n\n if (!error.retryable || attempt === maxRetries) {\n throw error;\n }\n\n lastError = error;\n const backoff = Math.min(1000 * Math.pow(2, attempt), 30_000);\n await sleep(backoff);\n } catch (err) {\n if (err instanceof GSCApiError) {\n if (!err.retryable || attempt === maxRetries) {\n throw err;\n }\n lastError = err;\n const backoff = Math.min(1000 * Math.pow(2, attempt), 30_000);\n await sleep(backoff);\n } else {\n throw err;\n }\n }\n }\n\n throw lastError ?? new GSCApiError('Request failed', 500, 'UNKNOWN');\n }\n\n return {\n request,\n siteUrl: config.siteUrl,\n };\n}\n","// @power-seo/search-console — Analytics\n// ----------------------------------------------------------------------------\n\nimport type {\n GSCClient,\n SearchAnalyticsRequest,\n SearchAnalyticsResponse,\n SearchAnalyticsRow,\n} from './types.js';\n\nconst MAX_ROW_LIMIT = 25000;\nconst DEFAULT_ROW_LIMIT = 1000;\n\nexport async function querySearchAnalytics(\n client: GSCClient,\n request: SearchAnalyticsRequest,\n): Promise<SearchAnalyticsResponse> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const body = {\n ...request,\n rowLimit: Math.min(request.rowLimit ?? DEFAULT_ROW_LIMIT, MAX_ROW_LIMIT),\n };\n\n return client.request<SearchAnalyticsResponse>(`/sites/${siteUrl}/searchAnalytics/query`, {\n method: 'POST',\n body,\n });\n}\n\nexport async function querySearchAnalyticsAll(\n client: GSCClient,\n request: Omit<SearchAnalyticsRequest, 'startRow' | 'rowLimit'>,\n): Promise<SearchAnalyticsRow[]> {\n const allRows: SearchAnalyticsRow[] = [];\n let startRow = 0;\n\n while (true) {\n const response = await querySearchAnalytics(client, {\n ...request,\n rowLimit: MAX_ROW_LIMIT,\n startRow,\n });\n\n const rows = response.rows ?? [];\n allRows.push(...rows);\n\n if (rows.length < MAX_ROW_LIMIT) {\n break;\n }\n\n startRow += rows.length;\n }\n\n return allRows;\n}\n","// @power-seo/search-console — URL Inspection\n// ----------------------------------------------------------------------------\n\nimport type { GSCClient, InspectionRequest, InspectionResult } from './types.js';\n\nconst INSPECTION_BASE = 'https://searchconsole.googleapis.com/v1/urlInspection/index:inspect';\n\nexport async function inspectUrl(\n client: GSCClient,\n request: InspectionRequest,\n): Promise<InspectionResult> {\n const body = {\n inspectionUrl: request.inspectionUrl,\n siteUrl: client.siteUrl,\n languageCode: request.languageCode ?? 'en',\n };\n\n const token = await client.request<{ inspectionResult: InspectionResult }>('', {\n method: 'POST',\n body,\n });\n\n // The URL Inspection API has a different base URL, so we use a direct fetch.\n // However, since the client handles auth and retries, we override for the standard path approach.\n // The API endpoint doesn't follow the webmasters/v3 pattern.\n // We'll use the client's request method with a custom approach.\n\n // Actually, let's do a direct fetch since the base URL differs:\n return token.inspectionResult;\n}\n\nexport async function inspectUrlDirect(\n getToken: () => Promise<string>,\n siteUrl: string,\n inspectionUrl: string,\n languageCode?: string,\n): Promise<InspectionResult> {\n const token = await getToken();\n\n const response = await globalThis.fetch(INSPECTION_BASE, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n inspectionUrl,\n siteUrl,\n languageCode: languageCode ?? 'en',\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`URL Inspection API error: ${response.status} ${text}`);\n }\n\n const data = (await response.json()) as { inspectionResult: InspectionResult };\n return data.inspectionResult;\n}\n","// @power-seo/search-console — Sitemaps\n// ----------------------------------------------------------------------------\n\nimport type { GSCClient, SitemapEntry, SitemapListResponse } from './types.js';\n\nexport async function listSitemaps(client: GSCClient): Promise<SitemapEntry[]> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const response = await client.request<SitemapListResponse>(`/sites/${siteUrl}/sitemaps`);\n return response.sitemap ?? [];\n}\n\nexport async function submitSitemap(client: GSCClient, feedpath: string): Promise<void> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const encodedFeed = encodeURIComponent(feedpath);\n await client.request<void>(`/sites/${siteUrl}/sitemaps/${encodedFeed}`, { method: 'PUT' });\n}\n\nexport async function deleteSitemap(client: GSCClient, feedpath: string): Promise<void> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const encodedFeed = encodeURIComponent(feedpath);\n await client.request<void>(`/sites/${siteUrl}/sitemaps/${encodedFeed}`, { method: 'DELETE' });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC0DO,IAAM,cAAN,cAA0B,MAAM;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,QAAgB,MAAc;AACzD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,YAAY,WAAW,OAAO,UAAU;AAAA,EAC/C;AACF;;;AC3DA,IAAM,YAAY;AAClB,IAAM,YAAY;AAClB,IAAM,kBAAkB;AAExB,eAAsB,qBAAqB,aAAqD;AAC9F,QAAM,OAAO,IAAI,WAAW,gBAAgB;AAAA,IAC1C,WAAW,YAAY;AAAA,IACvB,eAAe,YAAY;AAAA,IAC3B,eAAe,YAAY;AAAA,IAC3B,YAAY;AAAA,EACd,CAAC;AAED,QAAM,WAAW,MAAM,WAAW,MAAM,WAAW;AAAA,IACjD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oCAAoC;AAAA,IAC/D,MAAM,KAAK,SAAS;AAAA,EACtB,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAM,IAAI;AAAA,MACR,0BAA0B,IAAI;AAAA,MAC9B,SAAS;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,SAAO;AAAA,IACL,aAAa,KAAK;AAAA,IAClB,WAAW,KAAK,IAAI,IAAI,KAAK,aAAa;AAAA,EAC5C;AACF;AAEA,eAAsB,uBACpB,aACsB;AACtB,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,QAAM,UAAU;AAAA,IACd,KAAK,YAAY;AAAA,IACjB,OAAO;AAAA,IACP,KAAK;AAAA,IACL,KAAK,MAAM;AAAA,IACX,KAAK;AAAA,EACP;AAEA,QAAM,YAAY,MAAM,YAAY,QAAQ,OAAO;AAEnD,QAAM,OAAO,IAAI,WAAW,gBAAgB;AAAA,IAC1C,YAAY;AAAA,IACZ;AAAA,EACF,CAAC;AAED,QAAM,WAAW,MAAM,WAAW,MAAM,WAAW;AAAA,IACjD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,oCAAoC;AAAA,IAC/D,MAAM,KAAK,SAAS;AAAA,EACtB,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAM,IAAI;AAAA,MACR,iCAAiC,IAAI;AAAA,MACrC,SAAS;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,SAAO;AAAA,IACL,aAAa,KAAK;AAAA,IAClB,WAAW,KAAK,IAAI,IAAI,KAAK,aAAa;AAAA,EAC5C;AACF;AAEO,SAAS,mBAAmB,YAAsD;AACvF,MAAI,SAA6B;AACjC,MAAI,UAAkC;AAEtC,SAAO;AAAA,IACL,MAAM,WAA4B;AAChC,UAAI,UAAU,OAAO,YAAY,KAAK,IAAI,IAAI,iBAAiB;AAC7D,eAAO,OAAO;AAAA,MAChB;AAEA,UAAI,SAAS;AACX,eAAO;AAAA,MACT;AAEA,gBAAU,WAAW,EAAE,KAAK,CAAC,WAAW;AACtC,iBAAS;AACT,kBAAU;AACV,eAAO,OAAO;AAAA,MAChB,CAAC;AAED,aAAO;AAAA,IACT;AAAA,IAEA,aAAmB;AACjB,eAAS;AACT,gBAAU;AAAA,IACZ;AAAA,EACF;AACF;;;AC7GA,kBAAoE;AAEpE,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAErB,SAAS,gBAAgB,QAAoC;AAClE,QAAM,UAAU,OAAO,WAAW;AAClC,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,aAAS,+BAAkB,OAAO,sBAAsB,kBAAkB;AAEhF,iBAAe,QAAW,MAAc,SAAsC;AAC5E,UAAM,eAAW,yBAAY,MAAM;AACnC,QAAI,WAAW,GAAG;AAChB,gBAAM,mBAAM,QAAQ;AAAA,IACtB;AACA,kCAAa,MAAM;AAEnB,UAAM,QAAQ,MAAM,OAAO,KAAK,SAAS;AACzC,UAAM,MAAM,GAAG,OAAO,GAAG,IAAI;AAE7B,QAAI,YAA0B;AAE9B,aAAS,UAAU,GAAG,WAAW,YAAY,WAAW;AACtD,UAAI;AACF,cAAM,WAAW,MAAM,WAAW,MAAM,KAAK;AAAA,UAC3C,QAAQ,SAAS,UAAU;AAAA,UAC3B,SAAS;AAAA,YACP,eAAe,UAAU,KAAK;AAAA,YAC9B,gBAAgB;AAAA,UAClB;AAAA,UACA,MAAM,SAAS,OAAO,KAAK,UAAU,QAAQ,IAAI,IAAI;AAAA,UACrD,QAAQ,SAAS;AAAA,QACnB,CAAC;AAED,YAAI,SAAS,IAAI;AACf,iBAAQ,MAAM,SAAS,KAAK;AAAA,QAC9B;AAEA,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,cAAM,QAAQ,IAAI;AAAA,UAChB,kBAAkB,SAAS,MAAM,IAAI,IAAI;AAAA,UACzC,SAAS;AAAA,UACT,QAAQ,SAAS,MAAM;AAAA,QACzB;AAEA,YAAI,CAAC,MAAM,aAAa,YAAY,YAAY;AAC9C,gBAAM;AAAA,QACR;AAEA,oBAAY;AACZ,cAAM,UAAU,KAAK,IAAI,MAAO,KAAK,IAAI,GAAG,OAAO,GAAG,GAAM;AAC5D,kBAAM,mBAAM,OAAO;AAAA,MACrB,SAAS,KAAK;AACZ,YAAI,eAAe,aAAa;AAC9B,cAAI,CAAC,IAAI,aAAa,YAAY,YAAY;AAC5C,kBAAM;AAAA,UACR;AACA,sBAAY;AACZ,gBAAM,UAAU,KAAK,IAAI,MAAO,KAAK,IAAI,GAAG,OAAO,GAAG,GAAM;AAC5D,oBAAM,mBAAM,OAAO;AAAA,QACrB,OAAO;AACL,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,IAAI,YAAY,kBAAkB,KAAK,SAAS;AAAA,EACrE;AAEA,SAAO;AAAA,IACL;AAAA,IACA,SAAS,OAAO;AAAA,EAClB;AACF;;;ACrEA,IAAM,gBAAgB;AACtB,IAAM,oBAAoB;AAE1B,eAAsB,qBACpB,QACA,SACkC;AAClC,QAAM,UAAU,mBAAmB,OAAO,OAAO;AACjD,QAAM,OAAO;AAAA,IACX,GAAG;AAAA,IACH,UAAU,KAAK,IAAI,QAAQ,YAAY,mBAAmB,aAAa;AAAA,EACzE;AAEA,SAAO,OAAO,QAAiC,UAAU,OAAO,0BAA0B;AAAA,IACxF,QAAQ;AAAA,IACR;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,wBACpB,QACA,SAC+B;AAC/B,QAAM,UAAgC,CAAC;AACvC,MAAI,WAAW;AAEf,SAAO,MAAM;AACX,UAAM,WAAW,MAAM,qBAAqB,QAAQ;AAAA,MAClD,GAAG;AAAA,MACH,UAAU;AAAA,MACV;AAAA,IACF,CAAC;AAED,UAAM,OAAO,SAAS,QAAQ,CAAC;AAC/B,YAAQ,KAAK,GAAG,IAAI;AAEpB,QAAI,KAAK,SAAS,eAAe;AAC/B;AAAA,IACF;AAEA,gBAAY,KAAK;AAAA,EACnB;AAEA,SAAO;AACT;;;ACjDA,IAAM,kBAAkB;AAExB,eAAsB,WACpB,QACA,SAC2B;AAC3B,QAAM,OAAO;AAAA,IACX,eAAe,QAAQ;AAAA,IACvB,SAAS,OAAO;AAAA,IAChB,cAAc,QAAQ,gBAAgB;AAAA,EACxC;AAEA,QAAM,QAAQ,MAAM,OAAO,QAAgD,IAAI;AAAA,IAC7E,QAAQ;AAAA,IACR;AAAA,EACF,CAAC;AAQD,SAAO,MAAM;AACf;AAEA,eAAsB,iBACpB,UACA,SACA,eACA,cAC2B;AAC3B,QAAM,QAAQ,MAAM,SAAS;AAE7B,QAAM,WAAW,MAAM,WAAW,MAAM,iBAAiB;AAAA,IACvD,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,eAAe,UAAU,KAAK;AAAA,MAC9B,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB;AAAA,MACA;AAAA,MACA,cAAc,gBAAgB;AAAA,IAChC,CAAC;AAAA,EACH,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,UAAM,IAAI,MAAM,6BAA6B,SAAS,MAAM,IAAI,IAAI,EAAE;AAAA,EACxE;AAEA,QAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,SAAO,KAAK;AACd;;;ACtDA,eAAsB,aAAa,QAA4C;AAC7E,QAAM,UAAU,mBAAmB,OAAO,OAAO;AACjD,QAAM,WAAW,MAAM,OAAO,QAA6B,UAAU,OAAO,WAAW;AACvF,SAAO,SAAS,WAAW,CAAC;AAC9B;AAEA,eAAsB,cAAc,QAAmB,UAAiC;AACtF,QAAM,UAAU,mBAAmB,OAAO,OAAO;AACjD,QAAM,cAAc,mBAAmB,QAAQ;AAC/C,QAAM,OAAO,QAAc,UAAU,OAAO,aAAa,WAAW,IAAI,EAAE,QAAQ,MAAM,CAAC;AAC3F;AAEA,eAAsB,cAAc,QAAmB,UAAiC;AACtF,QAAM,UAAU,mBAAmB,OAAO,OAAO;AACjD,QAAM,cAAc,mBAAmB,QAAQ;AAC/C,QAAM,OAAO,QAAc,UAAU,OAAO,aAAa,WAAW,IAAI,EAAE,QAAQ,SAAS,CAAC;AAC9F;","names":[]}
package/dist/index.js CHANGED
@@ -1,5 +1,3 @@
1
- import { createTokenBucket, getWaitTime, sleep, consumeToken } from '@power-seo/core';
2
-
3
1
  // src/types.ts
4
2
  var GSCApiError = class extends Error {
5
3
  status;
@@ -101,6 +99,9 @@ function createTokenManager(fetchToken) {
101
99
  }
102
100
  };
103
101
  }
102
+
103
+ // src/client.ts
104
+ import { createTokenBucket, consumeToken, getWaitTime, sleep } from "@power-seo/core";
104
105
  var DEFAULT_BASE_URL = "https://searchconsole.googleapis.com/webmasters/v3";
105
106
  var DEFAULT_RATE_LIMIT = 1200;
106
107
  var DEFAULT_MAX_RETRIES = 3;
@@ -249,7 +250,18 @@ async function deleteSitemap(client, feedpath) {
249
250
  const encodedFeed = encodeURIComponent(feedpath);
250
251
  await client.request(`/sites/${siteUrl}/sitemaps/${encodedFeed}`, { method: "DELETE" });
251
252
  }
252
-
253
- export { GSCApiError, createGSCClient, createTokenManager, deleteSitemap, exchangeRefreshToken, getServiceAccountToken, inspectUrl, inspectUrlDirect, listSitemaps, querySearchAnalytics, querySearchAnalyticsAll, submitSitemap };
254
- //# sourceMappingURL=index.js.map
253
+ export {
254
+ GSCApiError,
255
+ createGSCClient,
256
+ createTokenManager,
257
+ deleteSitemap,
258
+ exchangeRefreshToken,
259
+ getServiceAccountToken,
260
+ inspectUrl,
261
+ inspectUrlDirect,
262
+ listSitemaps,
263
+ querySearchAnalytics,
264
+ querySearchAnalyticsAll,
265
+ submitSitemap
266
+ };
255
267
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/auth.ts","../src/client.ts","../src/analytics.ts","../src/inspection.ts","../src/sitemaps.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// ============================================================================\n// @power-seo/search-console — Types\n// ============================================================================\n\n// --- Auth Types ---\n\nexport interface OAuthCredentials {\n clientId: string;\n clientSecret: string;\n refreshToken: string;\n}\n\nexport interface ServiceAccountCredentials {\n clientEmail: string;\n privateKeyId: string;\n signJwt: (payload: JwtPayload) => Promise<string>;\n}\n\nexport interface JwtPayload {\n iss: string;\n scope: string;\n aud: string;\n exp: number;\n iat: number;\n}\n\nexport interface TokenResult {\n accessToken: string;\n expiresAt: number;\n}\n\nexport interface TokenManager {\n getToken: () => Promise<string>;\n invalidate: () => void;\n}\n\n// --- Client Types ---\n\nexport interface GSCClientConfig {\n auth: TokenManager;\n siteUrl: string;\n rateLimitPerMinute?: number;\n maxRetries?: number;\n baseUrl?: string;\n}\n\nexport interface GSCClient {\n request: <T>(path: string, options?: RequestOptions) => Promise<T>;\n siteUrl: string;\n}\n\nexport interface RequestOptions {\n method?: string;\n body?: unknown;\n signal?: globalThis.AbortSignal;\n}\n\n// --- Error ---\n\nexport class GSCApiError extends Error {\n readonly status: number;\n readonly code: string;\n readonly retryable: boolean;\n\n constructor(message: string, status: number, code: string) {\n super(message);\n this.name = 'GSCApiError';\n this.status = status;\n this.code = code;\n this.retryable = status === 429 || status >= 500;\n }\n}\n\n// --- Analytics Types ---\n\nexport type SearchType = 'web' | 'image' | 'video' | 'news' | 'discover' | 'googleNews';\nexport type Dimension = 'query' | 'page' | 'country' | 'device' | 'date' | 'searchAppearance';\nexport type AggregationType = 'auto' | 'byPage' | 'byProperty';\nexport type DataState = 'all' | 'final';\n\nexport interface DimensionFilter {\n dimension: Dimension;\n operator:\n | 'equals'\n | 'notEquals'\n | 'contains'\n | 'notContains'\n | 'includingRegex'\n | 'excludingRegex';\n expression: string;\n}\n\nexport interface DimensionFilterGroup {\n groupType?: 'and';\n filters: DimensionFilter[];\n}\n\nexport interface SearchAnalyticsRequest {\n startDate: string;\n endDate: string;\n dimensions?: Dimension[];\n searchType?: SearchType;\n dimensionFilterGroups?: DimensionFilterGroup[];\n aggregationType?: AggregationType;\n rowLimit?: number;\n startRow?: number;\n dataState?: DataState;\n}\n\nexport interface SearchAnalyticsRow {\n keys: string[];\n clicks: number;\n impressions: number;\n ctr: number;\n position: number;\n}\n\nexport interface SearchAnalyticsResponse {\n rows: SearchAnalyticsRow[];\n responseAggregationType: string;\n}\n\n// --- Inspection Types ---\n\nexport interface InspectionRequest {\n inspectionUrl: string;\n languageCode?: string;\n}\n\nexport type VerdictState = 'PASS' | 'PARTIAL' | 'FAIL' | 'VERDICT_UNSPECIFIED' | 'NEUTRAL';\nexport type CrawlState =\n | 'SUCCESSFUL'\n | 'NOT_FOUND'\n | 'SERVER_ERROR'\n | 'ROBOTS_BLOCKED'\n | 'REDIRECT_ERROR'\n | 'ACCESS_DENIED'\n | 'ACCESS_FORBIDDEN';\nexport type IndexState =\n | 'INDEXED'\n | 'NOT_INDEXED'\n | 'SUBMITTED_AND_INDEXED'\n | 'CRAWLED_NOT_INDEXED'\n | 'DISCOVERED_NOT_INDEXED'\n | 'PAGE_WITH_REDIRECT';\nexport type RobotsTxtState = 'ALLOWED' | 'DISALLOWED';\n\nexport interface IndexStatusResult {\n verdict: VerdictState;\n coverageState: IndexState;\n robotsTxtState: RobotsTxtState;\n indexingState: string;\n lastCrawlTime?: string;\n pageFetchState?: CrawlState;\n referringUrls?: string[];\n sitemap?: string[];\n}\n\nexport interface MobileUsabilityResult {\n verdict: VerdictState;\n issues?: Array<{ issueType: string; severity: string; message: string }>;\n}\n\nexport interface RichResultsResult {\n verdict: VerdictState;\n detectedItems?: Array<{\n richResultType: string;\n items: Array<{ name: string; issues?: Array<{ issueMessage: string; severity: string }> }>;\n }>;\n}\n\nexport interface InspectionResult {\n inspectionResultLink: string;\n indexStatusResult: IndexStatusResult;\n mobileUsabilityResult?: MobileUsabilityResult;\n richResultsResult?: RichResultsResult;\n}\n\n// --- Sitemap Types ---\n\nexport type SitemapType = 'sitemap' | 'atomFeed' | 'rssFeed' | 'notSitemap';\n\nexport interface SitemapEntry {\n path: string;\n lastSubmitted?: string;\n isPending: boolean;\n isSitemapsIndex: boolean;\n type: SitemapType;\n lastDownloaded?: string;\n warnings: number;\n errors: number;\n contents?: Array<{ type: string; submitted: number; indexed: number }>;\n}\n\nexport interface SitemapListResponse {\n sitemap: SitemapEntry[];\n}\n","// ============================================================================\n// @power-seo/search-console — Auth\n// ============================================================================\n\nimport type {\n OAuthCredentials,\n ServiceAccountCredentials,\n TokenResult,\n TokenManager,\n} from './types.js';\nimport { GSCApiError } from './types.js';\n\nconst TOKEN_URL = 'https://oauth2.googleapis.com/token';\nconst GSC_SCOPE = 'https://www.googleapis.com/auth/webmasters.readonly';\nconst TOKEN_BUFFER_MS = 60_000;\n\nexport async function exchangeRefreshToken(credentials: OAuthCredentials): Promise<TokenResult> {\n const body = new globalThis.URLSearchParams({\n client_id: credentials.clientId,\n client_secret: credentials.clientSecret,\n refresh_token: credentials.refreshToken,\n grant_type: 'refresh_token',\n });\n\n const response = await globalThis.fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new GSCApiError(\n `Token exchange failed: ${text}`,\n response.status,\n 'TOKEN_EXCHANGE_ERROR',\n );\n }\n\n const data = (await response.json()) as { access_token: string; expires_in: number };\n return {\n accessToken: data.access_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n}\n\nexport async function getServiceAccountToken(\n credentials: ServiceAccountCredentials,\n): Promise<TokenResult> {\n const now = Math.floor(Date.now() / 1000);\n const payload = {\n iss: credentials.clientEmail,\n scope: GSC_SCOPE,\n aud: TOKEN_URL,\n exp: now + 3600,\n iat: now,\n };\n\n const assertion = await credentials.signJwt(payload);\n\n const body = new globalThis.URLSearchParams({\n grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',\n assertion,\n });\n\n const response = await globalThis.fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new GSCApiError(\n `Service account token failed: ${text}`,\n response.status,\n 'SERVICE_ACCOUNT_ERROR',\n );\n }\n\n const data = (await response.json()) as { access_token: string; expires_in: number };\n return {\n accessToken: data.access_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n}\n\nexport function createTokenManager(fetchToken: () => Promise<TokenResult>): TokenManager {\n let cached: TokenResult | null = null;\n let pending: Promise<string> | null = null;\n\n return {\n async getToken(): Promise<string> {\n if (cached && cached.expiresAt > Date.now() + TOKEN_BUFFER_MS) {\n return cached.accessToken;\n }\n\n if (pending) {\n return pending;\n }\n\n pending = fetchToken().then((result) => {\n cached = result;\n pending = null;\n return result.accessToken;\n });\n\n return pending;\n },\n\n invalidate(): void {\n cached = null;\n pending = null;\n },\n };\n}\n","// ============================================================================\n// @power-seo/search-console — Client\n// ============================================================================\n\nimport type { GSCClientConfig, GSCClient, RequestOptions } from './types.js';\nimport { GSCApiError } from './types.js';\nimport { createTokenBucket, consumeToken, getWaitTime, sleep } from '@power-seo/core';\n\nconst DEFAULT_BASE_URL = 'https://searchconsole.googleapis.com/webmasters/v3';\nconst DEFAULT_RATE_LIMIT = 1200;\nconst DEFAULT_MAX_RETRIES = 3;\n\nexport function createGSCClient(config: GSCClientConfig): GSCClient {\n const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const bucket = createTokenBucket(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT);\n\n async function request<T>(path: string, options?: RequestOptions): Promise<T> {\n const waitTime = getWaitTime(bucket);\n if (waitTime > 0) {\n await sleep(waitTime);\n }\n consumeToken(bucket);\n\n const token = await config.auth.getToken();\n const url = `${baseUrl}${path}`;\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await globalThis.fetch(url, {\n method: options?.method ?? 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal: options?.signal,\n });\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const text = await response.text();\n const error = new GSCApiError(\n `GSC API error: ${response.status} ${text}`,\n response.status,\n `HTTP_${response.status}`,\n );\n\n if (!error.retryable || attempt === maxRetries) {\n throw error;\n }\n\n lastError = error;\n const backoff = Math.min(1000 * Math.pow(2, attempt), 30_000);\n await sleep(backoff);\n } catch (err) {\n if (err instanceof GSCApiError) {\n if (!err.retryable || attempt === maxRetries) {\n throw err;\n }\n lastError = err;\n const backoff = Math.min(1000 * Math.pow(2, attempt), 30_000);\n await sleep(backoff);\n } else {\n throw err;\n }\n }\n }\n\n throw lastError ?? new GSCApiError('Request failed', 500, 'UNKNOWN');\n }\n\n return {\n request,\n siteUrl: config.siteUrl,\n };\n}\n","// ============================================================================\n// @power-seo/search-console — Analytics\n// ============================================================================\n\nimport type {\n GSCClient,\n SearchAnalyticsRequest,\n SearchAnalyticsResponse,\n SearchAnalyticsRow,\n} from './types.js';\n\nconst MAX_ROW_LIMIT = 25000;\nconst DEFAULT_ROW_LIMIT = 1000;\n\nexport async function querySearchAnalytics(\n client: GSCClient,\n request: SearchAnalyticsRequest,\n): Promise<SearchAnalyticsResponse> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const body = {\n ...request,\n rowLimit: Math.min(request.rowLimit ?? DEFAULT_ROW_LIMIT, MAX_ROW_LIMIT),\n };\n\n return client.request<SearchAnalyticsResponse>(`/sites/${siteUrl}/searchAnalytics/query`, {\n method: 'POST',\n body,\n });\n}\n\nexport async function querySearchAnalyticsAll(\n client: GSCClient,\n request: Omit<SearchAnalyticsRequest, 'startRow' | 'rowLimit'>,\n): Promise<SearchAnalyticsRow[]> {\n const allRows: SearchAnalyticsRow[] = [];\n let startRow = 0;\n\n while (true) {\n const response = await querySearchAnalytics(client, {\n ...request,\n rowLimit: MAX_ROW_LIMIT,\n startRow,\n });\n\n const rows = response.rows ?? [];\n allRows.push(...rows);\n\n if (rows.length < MAX_ROW_LIMIT) {\n break;\n }\n\n startRow += rows.length;\n }\n\n return allRows;\n}\n","// ============================================================================\n// @power-seo/search-console — URL Inspection\n// ============================================================================\n\nimport type { GSCClient, InspectionRequest, InspectionResult } from './types.js';\n\nconst INSPECTION_BASE = 'https://searchconsole.googleapis.com/v1/urlInspection/index:inspect';\n\nexport async function inspectUrl(\n client: GSCClient,\n request: InspectionRequest,\n): Promise<InspectionResult> {\n const body = {\n inspectionUrl: request.inspectionUrl,\n siteUrl: client.siteUrl,\n languageCode: request.languageCode ?? 'en',\n };\n\n const token = await client.request<{ inspectionResult: InspectionResult }>('', {\n method: 'POST',\n body,\n });\n\n // The URL Inspection API has a different base URL, so we use a direct fetch.\n // However, since the client handles auth and retries, we override for the standard path approach.\n // The API endpoint doesn't follow the webmasters/v3 pattern.\n // We'll use the client's request method with a custom approach.\n\n // Actually, let's do a direct fetch since the base URL differs:\n return token.inspectionResult;\n}\n\nexport async function inspectUrlDirect(\n getToken: () => Promise<string>,\n siteUrl: string,\n inspectionUrl: string,\n languageCode?: string,\n): Promise<InspectionResult> {\n const token = await getToken();\n\n const response = await globalThis.fetch(INSPECTION_BASE, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n inspectionUrl,\n siteUrl,\n languageCode: languageCode ?? 'en',\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`URL Inspection API error: ${response.status} ${text}`);\n }\n\n const data = (await response.json()) as { inspectionResult: InspectionResult };\n return data.inspectionResult;\n}\n","// ============================================================================\n// @power-seo/search-console — Sitemaps\n// ============================================================================\n\nimport type { GSCClient, SitemapEntry, SitemapListResponse } from './types.js';\n\nexport async function listSitemaps(client: GSCClient): Promise<SitemapEntry[]> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const response = await client.request<SitemapListResponse>(`/sites/${siteUrl}/sitemaps`);\n return response.sitemap ?? [];\n}\n\nexport async function submitSitemap(client: GSCClient, feedpath: string): Promise<void> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const encodedFeed = encodeURIComponent(feedpath);\n await client.request<void>(`/sites/${siteUrl}/sitemaps/${encodedFeed}`, { method: 'PUT' });\n}\n\nexport async function deleteSitemap(client: GSCClient, feedpath: string): Promise<void> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const encodedFeed = encodeURIComponent(feedpath);\n await client.request<void>(`/sites/${siteUrl}/sitemaps/${encodedFeed}`, { method: 'DELETE' });\n}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/auth.ts","../src/client.ts","../src/analytics.ts","../src/inspection.ts","../src/sitemaps.ts"],"sourcesContent":["// @power-seo/search-console — Types\n// ----------------------------------------------------------------------------\n\n// --- Auth Types ---\n\nexport interface OAuthCredentials {\n clientId: string;\n clientSecret: string;\n refreshToken: string;\n}\n\nexport interface ServiceAccountCredentials {\n clientEmail: string;\n privateKeyId: string;\n signJwt: (payload: JwtPayload) => Promise<string>;\n}\n\nexport interface JwtPayload {\n iss: string;\n scope: string;\n aud: string;\n exp: number;\n iat: number;\n}\n\nexport interface TokenResult {\n accessToken: string;\n expiresAt: number;\n}\n\nexport interface TokenManager {\n getToken: () => Promise<string>;\n invalidate: () => void;\n}\n\n// --- Client Types ---\n\nexport interface GSCClientConfig {\n auth: TokenManager;\n siteUrl: string;\n rateLimitPerMinute?: number;\n maxRetries?: number;\n baseUrl?: string;\n}\n\nexport interface GSCClient {\n request: <T>(path: string, options?: RequestOptions) => Promise<T>;\n siteUrl: string;\n}\n\nexport interface RequestOptions {\n method?: string;\n body?: unknown;\n signal?: globalThis.AbortSignal;\n}\n\n// --- Error ---\n\nexport class GSCApiError extends Error {\n readonly status: number;\n readonly code: string;\n readonly retryable: boolean;\n\n constructor(message: string, status: number, code: string) {\n super(message);\n this.name = 'GSCApiError';\n this.status = status;\n this.code = code;\n this.retryable = status === 429 || status >= 500;\n }\n}\n\n// --- Analytics Types ---\n\nexport type SearchType = 'web' | 'image' | 'video' | 'news' | 'discover' | 'googleNews';\nexport type Dimension = 'query' | 'page' | 'country' | 'device' | 'date' | 'searchAppearance';\nexport type AggregationType = 'auto' | 'byPage' | 'byProperty';\nexport type DataState = 'all' | 'final';\n\nexport interface DimensionFilter {\n dimension: Dimension;\n operator:\n | 'equals'\n | 'notEquals'\n | 'contains'\n | 'notContains'\n | 'includingRegex'\n | 'excludingRegex';\n expression: string;\n}\n\nexport interface DimensionFilterGroup {\n groupType?: 'and';\n filters: DimensionFilter[];\n}\n\nexport interface SearchAnalyticsRequest {\n startDate: string;\n endDate: string;\n dimensions?: Dimension[];\n searchType?: SearchType;\n dimensionFilterGroups?: DimensionFilterGroup[];\n aggregationType?: AggregationType;\n rowLimit?: number;\n startRow?: number;\n dataState?: DataState;\n}\n\nexport interface SearchAnalyticsRow {\n keys: string[];\n clicks: number;\n impressions: number;\n ctr: number;\n position: number;\n}\n\nexport interface SearchAnalyticsResponse {\n rows: SearchAnalyticsRow[];\n responseAggregationType: string;\n}\n\n// --- Inspection Types ---\n\nexport interface InspectionRequest {\n inspectionUrl: string;\n languageCode?: string;\n}\n\nexport type VerdictState = 'PASS' | 'PARTIAL' | 'FAIL' | 'VERDICT_UNSPECIFIED' | 'NEUTRAL';\nexport type CrawlState =\n | 'SUCCESSFUL'\n | 'NOT_FOUND'\n | 'SERVER_ERROR'\n | 'ROBOTS_BLOCKED'\n | 'REDIRECT_ERROR'\n | 'ACCESS_DENIED'\n | 'ACCESS_FORBIDDEN';\nexport type IndexState =\n | 'INDEXED'\n | 'NOT_INDEXED'\n | 'SUBMITTED_AND_INDEXED'\n | 'CRAWLED_NOT_INDEXED'\n | 'DISCOVERED_NOT_INDEXED'\n | 'PAGE_WITH_REDIRECT';\nexport type RobotsTxtState = 'ALLOWED' | 'DISALLOWED';\n\nexport interface IndexStatusResult {\n verdict: VerdictState;\n coverageState: IndexState;\n robotsTxtState: RobotsTxtState;\n indexingState: string;\n lastCrawlTime?: string;\n pageFetchState?: CrawlState;\n referringUrls?: string[];\n sitemap?: string[];\n}\n\nexport interface MobileUsabilityResult {\n verdict: VerdictState;\n issues?: Array<{ issueType: string; severity: string; message: string }>;\n}\n\nexport interface RichResultsResult {\n verdict: VerdictState;\n detectedItems?: Array<{\n richResultType: string;\n items: Array<{ name: string; issues?: Array<{ issueMessage: string; severity: string }> }>;\n }>;\n}\n\nexport interface InspectionResult {\n inspectionResultLink: string;\n indexStatusResult: IndexStatusResult;\n mobileUsabilityResult?: MobileUsabilityResult;\n richResultsResult?: RichResultsResult;\n}\n\n// --- Sitemap Types ---\n\nexport type SitemapType = 'sitemap' | 'atomFeed' | 'rssFeed' | 'notSitemap';\n\nexport interface SitemapEntry {\n path: string;\n lastSubmitted?: string;\n isPending: boolean;\n isSitemapsIndex: boolean;\n type: SitemapType;\n lastDownloaded?: string;\n warnings: number;\n errors: number;\n contents?: Array<{ type: string; submitted: number; indexed: number }>;\n}\n\nexport interface SitemapListResponse {\n sitemap: SitemapEntry[];\n}\n","// @power-seo/search-console — Auth\n// ----------------------------------------------------------------------------\n\nimport type {\n OAuthCredentials,\n ServiceAccountCredentials,\n TokenResult,\n TokenManager,\n} from './types.js';\nimport { GSCApiError } from './types.js';\n\nconst TOKEN_URL = 'https://oauth2.googleapis.com/token';\nconst GSC_SCOPE = 'https://www.googleapis.com/auth/webmasters.readonly';\nconst TOKEN_BUFFER_MS = 60_000;\n\nexport async function exchangeRefreshToken(credentials: OAuthCredentials): Promise<TokenResult> {\n const body = new globalThis.URLSearchParams({\n client_id: credentials.clientId,\n client_secret: credentials.clientSecret,\n refresh_token: credentials.refreshToken,\n grant_type: 'refresh_token',\n });\n\n const response = await globalThis.fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new GSCApiError(\n `Token exchange failed: ${text}`,\n response.status,\n 'TOKEN_EXCHANGE_ERROR',\n );\n }\n\n const data = (await response.json()) as { access_token: string; expires_in: number };\n return {\n accessToken: data.access_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n}\n\nexport async function getServiceAccountToken(\n credentials: ServiceAccountCredentials,\n): Promise<TokenResult> {\n const now = Math.floor(Date.now() / 1000);\n const payload = {\n iss: credentials.clientEmail,\n scope: GSC_SCOPE,\n aud: TOKEN_URL,\n exp: now + 3600,\n iat: now,\n };\n\n const assertion = await credentials.signJwt(payload);\n\n const body = new globalThis.URLSearchParams({\n grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',\n assertion,\n });\n\n const response = await globalThis.fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new GSCApiError(\n `Service account token failed: ${text}`,\n response.status,\n 'SERVICE_ACCOUNT_ERROR',\n );\n }\n\n const data = (await response.json()) as { access_token: string; expires_in: number };\n return {\n accessToken: data.access_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n };\n}\n\nexport function createTokenManager(fetchToken: () => Promise<TokenResult>): TokenManager {\n let cached: TokenResult | null = null;\n let pending: Promise<string> | null = null;\n\n return {\n async getToken(): Promise<string> {\n if (cached && cached.expiresAt > Date.now() + TOKEN_BUFFER_MS) {\n return cached.accessToken;\n }\n\n if (pending) {\n return pending;\n }\n\n pending = fetchToken().then((result) => {\n cached = result;\n pending = null;\n return result.accessToken;\n });\n\n return pending;\n },\n\n invalidate(): void {\n cached = null;\n pending = null;\n },\n };\n}\n","// @power-seo/search-console — Client\n// ----------------------------------------------------------------------------\n\nimport type { GSCClientConfig, GSCClient, RequestOptions } from './types.js';\nimport { GSCApiError } from './types.js';\nimport { createTokenBucket, consumeToken, getWaitTime, sleep } from '@power-seo/core';\n\nconst DEFAULT_BASE_URL = 'https://searchconsole.googleapis.com/webmasters/v3';\nconst DEFAULT_RATE_LIMIT = 1200;\nconst DEFAULT_MAX_RETRIES = 3;\n\nexport function createGSCClient(config: GSCClientConfig): GSCClient {\n const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const bucket = createTokenBucket(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT);\n\n async function request<T>(path: string, options?: RequestOptions): Promise<T> {\n const waitTime = getWaitTime(bucket);\n if (waitTime > 0) {\n await sleep(waitTime);\n }\n consumeToken(bucket);\n\n const token = await config.auth.getToken();\n const url = `${baseUrl}${path}`;\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await globalThis.fetch(url, {\n method: options?.method ?? 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal: options?.signal,\n });\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const text = await response.text();\n const error = new GSCApiError(\n `GSC API error: ${response.status} ${text}`,\n response.status,\n `HTTP_${response.status}`,\n );\n\n if (!error.retryable || attempt === maxRetries) {\n throw error;\n }\n\n lastError = error;\n const backoff = Math.min(1000 * Math.pow(2, attempt), 30_000);\n await sleep(backoff);\n } catch (err) {\n if (err instanceof GSCApiError) {\n if (!err.retryable || attempt === maxRetries) {\n throw err;\n }\n lastError = err;\n const backoff = Math.min(1000 * Math.pow(2, attempt), 30_000);\n await sleep(backoff);\n } else {\n throw err;\n }\n }\n }\n\n throw lastError ?? new GSCApiError('Request failed', 500, 'UNKNOWN');\n }\n\n return {\n request,\n siteUrl: config.siteUrl,\n };\n}\n","// @power-seo/search-console — Analytics\n// ----------------------------------------------------------------------------\n\nimport type {\n GSCClient,\n SearchAnalyticsRequest,\n SearchAnalyticsResponse,\n SearchAnalyticsRow,\n} from './types.js';\n\nconst MAX_ROW_LIMIT = 25000;\nconst DEFAULT_ROW_LIMIT = 1000;\n\nexport async function querySearchAnalytics(\n client: GSCClient,\n request: SearchAnalyticsRequest,\n): Promise<SearchAnalyticsResponse> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const body = {\n ...request,\n rowLimit: Math.min(request.rowLimit ?? DEFAULT_ROW_LIMIT, MAX_ROW_LIMIT),\n };\n\n return client.request<SearchAnalyticsResponse>(`/sites/${siteUrl}/searchAnalytics/query`, {\n method: 'POST',\n body,\n });\n}\n\nexport async function querySearchAnalyticsAll(\n client: GSCClient,\n request: Omit<SearchAnalyticsRequest, 'startRow' | 'rowLimit'>,\n): Promise<SearchAnalyticsRow[]> {\n const allRows: SearchAnalyticsRow[] = [];\n let startRow = 0;\n\n while (true) {\n const response = await querySearchAnalytics(client, {\n ...request,\n rowLimit: MAX_ROW_LIMIT,\n startRow,\n });\n\n const rows = response.rows ?? [];\n allRows.push(...rows);\n\n if (rows.length < MAX_ROW_LIMIT) {\n break;\n }\n\n startRow += rows.length;\n }\n\n return allRows;\n}\n","// @power-seo/search-console — URL Inspection\n// ----------------------------------------------------------------------------\n\nimport type { GSCClient, InspectionRequest, InspectionResult } from './types.js';\n\nconst INSPECTION_BASE = 'https://searchconsole.googleapis.com/v1/urlInspection/index:inspect';\n\nexport async function inspectUrl(\n client: GSCClient,\n request: InspectionRequest,\n): Promise<InspectionResult> {\n const body = {\n inspectionUrl: request.inspectionUrl,\n siteUrl: client.siteUrl,\n languageCode: request.languageCode ?? 'en',\n };\n\n const token = await client.request<{ inspectionResult: InspectionResult }>('', {\n method: 'POST',\n body,\n });\n\n // The URL Inspection API has a different base URL, so we use a direct fetch.\n // However, since the client handles auth and retries, we override for the standard path approach.\n // The API endpoint doesn't follow the webmasters/v3 pattern.\n // We'll use the client's request method with a custom approach.\n\n // Actually, let's do a direct fetch since the base URL differs:\n return token.inspectionResult;\n}\n\nexport async function inspectUrlDirect(\n getToken: () => Promise<string>,\n siteUrl: string,\n inspectionUrl: string,\n languageCode?: string,\n): Promise<InspectionResult> {\n const token = await getToken();\n\n const response = await globalThis.fetch(INSPECTION_BASE, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n inspectionUrl,\n siteUrl,\n languageCode: languageCode ?? 'en',\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`URL Inspection API error: ${response.status} ${text}`);\n }\n\n const data = (await response.json()) as { inspectionResult: InspectionResult };\n return data.inspectionResult;\n}\n","// @power-seo/search-console — Sitemaps\n// ----------------------------------------------------------------------------\n\nimport type { GSCClient, SitemapEntry, SitemapListResponse } from './types.js';\n\nexport async function listSitemaps(client: GSCClient): Promise<SitemapEntry[]> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const response = await client.request<SitemapListResponse>(`/sites/${siteUrl}/sitemaps`);\n return response.sitemap ?? [];\n}\n\nexport async function submitSitemap(client: GSCClient, feedpath: string): Promise<void> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const encodedFeed = encodeURIComponent(feedpath);\n await client.request<void>(`/sites/${siteUrl}/sitemaps/${encodedFeed}`, { method: 'PUT' });\n}\n\nexport async function deleteSitemap(client: GSCClient, feedpath: string): Promise<void> {\n const siteUrl = encodeURIComponent(client.siteUrl);\n const encodedFeed = encodeURIComponent(feedpath);\n await client.request<void>(`/sites/${siteUrl}/sitemaps/${encodedFeed}`, { method: 'DELETE' });\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@power-seo/search-console",
3
- "version": "1.0.4",
3
+ "version": "1.0.8",
4
4
  "description": "Google Search Console API client with OAuth2/service account auth, rate limiting, and retry",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -31,7 +31,7 @@
31
31
  "@power-seo/core": "workspace:*"
32
32
  },
33
33
  "devDependencies": {
34
- "rimraf": "^6.0.0",
34
+ "rimraf": "^6.1.3",
35
35
  "tsup": "^8.3.0",
36
36
  "typescript": "^5.7.0",
37
37
  "vitest": "^2.1.0"
@@ -52,5 +52,13 @@
52
52
  },
53
53
  "publishConfig": {
54
54
  "access": "public"
55
+ },
56
+ "bugs": {
57
+ "url": "https://github.com/CyberCraftBD/power-seo/issues"
58
+ },
59
+ "homepage": "https://github.com/CyberCraftBD/power-seo/tree/main/packages/search-console#readme",
60
+ "funding": {
61
+ "type": "github",
62
+ "url": "https://github.com/sponsors/cybercraftbd"
55
63
  }
56
64
  }