@power-seo/integrations
Advanced tools
+31
-28
@@ -267,10 +267,12 @@ 'use strict'; | ||
| ); | ||
| return (raw.data ?? []).map((r) => ({ | ||
| keyword: r.Ph, | ||
| difficulty: r.Kd, | ||
| searchVolume: r.Nq, | ||
| cpc: r.Cp, | ||
| competition: r.Co, | ||
| results: r.Nr | ||
| })); | ||
| return (raw.data ?? []).map( | ||
| (r) => ({ | ||
| keyword: r.Ph, | ||
| difficulty: r.Kd, | ||
| searchVolume: r.Nq, | ||
| cpc: r.Cp, | ||
| competition: r.Co, | ||
| results: r.Nr | ||
| }) | ||
| ); | ||
| }, | ||
@@ -283,10 +285,12 @@ async getRelatedKeywords(keyword, database = DEFAULT_DATABASE) { | ||
| ); | ||
| return (raw.data ?? []).map((r) => ({ | ||
| keyword: r.Ph, | ||
| searchVolume: r.Nq, | ||
| cpc: r.Cp, | ||
| competition: r.Co, | ||
| results: r.Nr, | ||
| relatedTo: r.Rr | ||
| })); | ||
| return (raw.data ?? []).map( | ||
| (r) => ({ | ||
| keyword: r.Ph, | ||
| searchVolume: r.Nq, | ||
| cpc: r.Cp, | ||
| competition: r.Co, | ||
| results: r.Nr, | ||
| relatedTo: r.Rr | ||
| }) | ||
| ); | ||
| } | ||
@@ -403,6 +407,3 @@ }; | ||
| const params = buildBacklinksParams2(domain, limit, offset); | ||
| const raw = await http.get( | ||
| backlinksPath2(), | ||
| params | ||
| ); | ||
| const raw = await http.get(backlinksPath2(), params); | ||
| const data = (raw.data ?? []).map((r) => ({ | ||
@@ -432,10 +433,12 @@ sourceUrl: r.url_from, | ||
| ); | ||
| return (raw.data ?? []).map((r) => ({ | ||
| keyword: r.keyword, | ||
| difficulty: r.difficulty, | ||
| searchVolume: r.volume, | ||
| cpc: r.cpc, | ||
| clicks: r.clicks, | ||
| globalVolume: r.global_volume | ||
| })); | ||
| return (raw.data ?? []).map( | ||
| (r) => ({ | ||
| keyword: r.keyword, | ||
| difficulty: r.difficulty, | ||
| searchVolume: r.volume, | ||
| cpc: r.cpc, | ||
| clicks: r.clicks, | ||
| globalVolume: r.global_volume | ||
| }) | ||
| ); | ||
| }, | ||
@@ -442,0 +445,0 @@ async getReferringDomains(domain, options) { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/types.ts","../src/http.ts","../src/semrush/endpoints.ts","../src/semrush/client.ts","../src/ahrefs/endpoints.ts","../src/ahrefs/client.ts"],"names":["createTokenBucket","getWaitTime","sleep","consumeToken","organicKeywordsPath","backlinksPath","keywordDifficultyPath","buildOrganicKeywordsParams","buildBacklinksParams","buildKeywordDifficultyParams","DEFAULT_LIMIT"],"mappings":"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","file":"index.cjs","sourcesContent":["// ============================================================================\n// @power-seo/integrations — Types\n// ============================================================================\n\n// --- HTTP Client Types ---\n\nexport type AuthStrategy =\n | { type: 'query'; paramName: string; value: string }\n | { type: 'bearer'; token: string };\n\nexport interface HttpClientConfig {\n baseUrl: string;\n auth: AuthStrategy;\n rateLimitPerMinute?: number;\n maxRetries?: number;\n timeoutMs?: number;\n}\n\nexport interface HttpClient {\n get: <T>(path: string, params?: Record<string, string>) => Promise<T>;\n post: <T>(path: string, body?: unknown) => Promise<T>;\n}\n\n// --- Error ---\n\nexport class IntegrationApiError extends Error {\n readonly status: number;\n readonly provider: string;\n readonly retryable: boolean;\n\n constructor(message: string, status: number, provider: string) {\n super(message);\n this.name = 'IntegrationApiError';\n this.status = status;\n this.provider = provider;\n this.retryable = status === 429 || status >= 500;\n }\n}\n\n// --- Pagination ---\n\nexport interface PaginatedResponse<T> {\n data: T[];\n total: number;\n offset: number;\n limit: number;\n hasMore: boolean;\n}\n\n// --- Semrush Types ---\n\nexport interface SemrushDomainOverview {\n domain: string;\n organicKeywords: number;\n organicTraffic: number;\n organicCost: number;\n paidKeywords: number;\n paidTraffic: number;\n paidCost: number;\n backlinks: number;\n authorityScore: number;\n}\n\nexport interface SemrushKeywordData {\n keyword: string;\n position: number;\n previousPosition: number;\n searchVolume: number;\n cpc: number;\n url: string;\n traffic: number;\n trafficPercent: number;\n trafficCost: number;\n competition: number;\n}\n\nexport interface SemrushBacklinkData {\n sourceUrl: string;\n targetUrl: string;\n anchorText: string;\n isNoFollow: boolean;\n firstSeen: string;\n lastSeen: string;\n sourceAuthorityScore: number;\n}\n\nexport interface SemrushKeywordDifficulty {\n keyword: string;\n difficulty: number;\n searchVolume: number;\n cpc: number;\n competition: number;\n results: number;\n}\n\nexport interface SemrushRelatedKeyword {\n keyword: string;\n searchVolume: number;\n cpc: number;\n competition: number;\n results: number;\n relatedTo: string;\n}\n\nexport interface SemrushClient {\n getDomainOverview: (domain: string, database?: string) => Promise<SemrushDomainOverview>;\n getOrganicKeywords: (domain: string, options?: SemrushPaginationOptions) => Promise<PaginatedResponse<SemrushKeywordData>>;\n getBacklinks: (domain: string, options?: SemrushPaginationOptions) => Promise<PaginatedResponse<SemrushBacklinkData>>;\n getKeywordDifficulty: (keywords: string[], database?: string) => Promise<SemrushKeywordDifficulty[]>;\n getRelatedKeywords: (keyword: string, database?: string) => Promise<SemrushRelatedKeyword[]>;\n}\n\nexport interface SemrushPaginationOptions {\n limit?: number;\n offset?: number;\n database?: string;\n}\n\n// --- Ahrefs Types ---\n\nexport interface AhrefsSiteOverview {\n domain: string;\n domainRating: number;\n urlRating: number;\n backlinks: number;\n referringDomains: number;\n organicKeywords: number;\n organicTraffic: number;\n trafficValue: number;\n}\n\nexport interface AhrefsOrganicKeyword {\n keyword: string;\n position: number;\n searchVolume: number;\n cpc: number;\n url: string;\n traffic: number;\n trafficPercent: number;\n difficulty: number;\n}\n\nexport interface AhrefsBacklink {\n sourceUrl: string;\n targetUrl: string;\n anchorText: string;\n domainRating: number;\n urlRating: number;\n isDoFollow: boolean;\n firstSeen: string;\n lastSeen: string;\n}\n\nexport interface AhrefsKeywordDifficulty {\n keyword: string;\n difficulty: number;\n searchVolume: number;\n cpc: number;\n clicks: number;\n globalVolume: number;\n}\n\nexport interface AhrefsReferringDomain {\n domain: string;\n domainRating: number;\n backlinks: number;\n firstSeen: string;\n lastSeen: string;\n isDoFollow: boolean;\n}\n\nexport interface AhrefsClient {\n getSiteOverview: (domain: string) => Promise<AhrefsSiteOverview>;\n getOrganicKeywords: (domain: string, options?: AhrefsPaginationOptions) => Promise<PaginatedResponse<AhrefsOrganicKeyword>>;\n getBacklinks: (domain: string, options?: AhrefsPaginationOptions) => Promise<PaginatedResponse<AhrefsBacklink>>;\n getKeywordDifficulty: (keywords: string[]) => Promise<AhrefsKeywordDifficulty[]>;\n getReferringDomains: (domain: string, options?: AhrefsPaginationOptions) => Promise<PaginatedResponse<AhrefsReferringDomain>>;\n}\n\nexport interface AhrefsPaginationOptions {\n limit?: number;\n offset?: number;\n}\n","// ============================================================================\n// @power-seo/integrations — Shared HTTP Client\n// ============================================================================\n\nimport type { HttpClientConfig, HttpClient, AuthStrategy } from './types.js';\nimport { IntegrationApiError } from './types.js';\nimport { createTokenBucket, consumeToken, getWaitTime, sleep } from '@power-seo/core';\n\nconst DEFAULT_RATE_LIMIT = 600;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nfunction buildUrl(\n baseUrl: string,\n path: string,\n params: Record<string, string>,\n auth: AuthStrategy,\n): string {\n const url = new globalThis.URL(`${baseUrl}${path}`);\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value);\n }\n if (auth.type === 'query') {\n url.searchParams.set(auth.paramName, auth.value);\n }\n return url.toString();\n}\n\nfunction buildHeaders(auth: AuthStrategy): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n if (auth.type === 'bearer') {\n headers['Authorization'] = `Bearer ${auth.token}`;\n }\n return headers;\n}\n\nfunction getProviderFromUrl(baseUrl: string): string {\n if (baseUrl.includes('semrush')) return 'semrush';\n if (baseUrl.includes('ahrefs')) return 'ahrefs';\n return 'unknown';\n}\n\nexport function createHttpClient(config: HttpClientConfig): HttpClient {\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const bucket = createTokenBucket(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT);\n const provider = getProviderFromUrl(config.baseUrl);\n\n async function makeRequest<T>(\n url: string,\n init: globalThis.RequestInit,\n ): Promise<T> {\n const waitTime = getWaitTime(bucket);\n if (waitTime > 0) {\n await sleep(waitTime);\n }\n consumeToken(bucket);\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const controller = new globalThis.AbortController();\n const timeout = globalThis.setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await globalThis.fetch(url, {\n ...init,\n signal: controller.signal,\n });\n\n globalThis.clearTimeout(timeout);\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const text = await response.text();\n const error = new IntegrationApiError(\n `${provider} API error: ${response.status} ${text}`,\n response.status,\n provider,\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 globalThis.clearTimeout(timeout);\n if (err instanceof IntegrationApiError) {\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 IntegrationApiError('Request failed', 500, provider);\n }\n\n return {\n async get<T>(path: string, params?: Record<string, string>): Promise<T> {\n const url = buildUrl(config.baseUrl, path, params ?? {}, config.auth);\n const headers = buildHeaders(config.auth);\n return makeRequest<T>(url, { method: 'GET', headers });\n },\n\n async post<T>(path: string, body?: unknown): Promise<T> {\n const url = buildUrl(config.baseUrl, path, {}, config.auth);\n const headers = buildHeaders(config.auth);\n return makeRequest<T>(url, {\n method: 'POST',\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n },\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Semrush Endpoints\n// ============================================================================\n\nexport const SEMRUSH_BASE_URL = 'https://api.semrush.com';\n\nexport function domainOverviewPath(): string {\n return '/analytics/v1/';\n}\n\nexport function organicKeywordsPath(): string {\n return '/analytics/v1/';\n}\n\nexport function backlinksPath(): string {\n return '/analytics/v1/';\n}\n\nexport function keywordDifficultyPath(): string {\n return '/analytics/v1/';\n}\n\nexport function relatedKeywordsPath(): string {\n return '/analytics/v1/';\n}\n\nexport function buildDomainOverviewParams(domain: string, database: string): Record<string, string> {\n return {\n type: 'domain_ranks',\n domain,\n database,\n export_columns: 'Or,Ot,Oc,Ad,At,Ac,Bk,As',\n };\n}\n\nexport function buildOrganicKeywordsParams(\n domain: string,\n database: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n type: 'domain_organic',\n domain,\n database,\n display_limit: String(limit),\n display_offset: String(offset),\n export_columns: 'Ph,Po,Pp,Nq,Cp,Ur,Tr,Tc,Co,Td',\n };\n}\n\nexport function buildBacklinksParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n type: 'backlinks',\n target: domain,\n target_type: 'root_domain',\n display_limit: String(limit),\n display_offset: String(offset),\n export_columns: 'source_url,target_url,anchor,nofollow,first_seen,last_seen,source_ascore',\n };\n}\n\nexport function buildKeywordDifficultyParams(\n keywords: string[],\n database: string,\n): Record<string, string> {\n return {\n type: 'phrase_all',\n phrase: keywords.join(';'),\n database,\n export_columns: 'Ph,Kd,Nq,Cp,Co,Nr',\n };\n}\n\nexport function buildRelatedKeywordsParams(\n keyword: string,\n database: string,\n): Record<string, string> {\n return {\n type: 'phrase_related',\n phrase: keyword,\n database,\n export_columns: 'Ph,Nq,Cp,Co,Nr,Rr',\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Semrush Client\n// ============================================================================\n\nimport type {\n SemrushClient,\n SemrushDomainOverview,\n SemrushKeywordData,\n SemrushBacklinkData,\n SemrushKeywordDifficulty,\n SemrushRelatedKeyword,\n PaginatedResponse,\n SemrushPaginationOptions,\n HttpClientConfig,\n} from '../types.js';\nimport { createHttpClient } from '../http.js';\nimport {\n SEMRUSH_BASE_URL,\n domainOverviewPath,\n organicKeywordsPath,\n backlinksPath,\n keywordDifficultyPath,\n relatedKeywordsPath,\n buildDomainOverviewParams,\n buildOrganicKeywordsParams,\n buildBacklinksParams,\n buildKeywordDifficultyParams,\n buildRelatedKeywordsParams,\n} from './endpoints.js';\nimport type {\n SemrushRawDomainResponse,\n SemrushApiResponse,\n SemrushRawKeywordResponse,\n SemrushRawBacklinkResponse,\n SemrushRawKeywordDifficultyResponse,\n SemrushRawRelatedKeywordResponse,\n} from './types.js';\n\nconst DEFAULT_LIMIT = 100;\nconst DEFAULT_DATABASE = 'us';\n\nexport function createSemrushClient(\n apiKey: string,\n config?: Partial<Omit<HttpClientConfig, 'baseUrl' | 'auth'>>,\n): SemrushClient {\n const http = createHttpClient({\n baseUrl: SEMRUSH_BASE_URL,\n auth: { type: 'query', paramName: 'key', value: apiKey },\n ...config,\n });\n\n return {\n async getDomainOverview(domain, database = DEFAULT_DATABASE) {\n const params = buildDomainOverviewParams(domain, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawDomainResponse>>(\n domainOverviewPath(),\n params,\n );\n const entry = raw.data[0];\n return {\n domain,\n organicKeywords: entry?.Or ?? 0,\n organicTraffic: entry?.Ot ?? 0,\n organicCost: entry?.Oc ?? 0,\n paidKeywords: entry?.Ad ?? 0,\n paidTraffic: entry?.At ?? 0,\n paidCost: entry?.Ac ?? 0,\n backlinks: entry?.Bk ?? 0,\n authorityScore: entry?.As ?? 0,\n } satisfies SemrushDomainOverview;\n },\n\n async getOrganicKeywords(domain, options?: SemrushPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const database = options?.database ?? DEFAULT_DATABASE;\n const params = buildOrganicKeywordsParams(domain, database, limit, offset);\n const raw = await http.get<SemrushApiResponse<SemrushRawKeywordResponse>>(\n organicKeywordsPath(),\n params,\n );\n const data: SemrushKeywordData[] = (raw.data ?? []).map((r) => ({\n keyword: r.Ph,\n position: r.Po,\n previousPosition: r.Pp,\n searchVolume: r.Nq,\n cpc: r.Cp,\n url: r.Ur,\n traffic: r.Tr,\n trafficPercent: r.Td,\n trafficCost: r.Tc,\n competition: r.Co,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<SemrushKeywordData>;\n },\n\n async getBacklinks(domain, options?: SemrushPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildBacklinksParams(domain, limit, offset);\n const raw = await http.get<SemrushApiResponse<SemrushRawBacklinkResponse>>(\n backlinksPath(),\n params,\n );\n const data: SemrushBacklinkData[] = (raw.data ?? []).map((r) => ({\n sourceUrl: r.source_url,\n targetUrl: r.target_url,\n anchorText: r.anchor,\n isNoFollow: r.nofollow,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n sourceAuthorityScore: r.source_ascore,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<SemrushBacklinkData>;\n },\n\n async getKeywordDifficulty(keywords, database = DEFAULT_DATABASE) {\n const params = buildKeywordDifficultyParams(keywords, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawKeywordDifficultyResponse>>(\n keywordDifficultyPath(),\n params,\n );\n return (raw.data ?? []).map((r): SemrushKeywordDifficulty => ({\n keyword: r.Ph,\n difficulty: r.Kd,\n searchVolume: r.Nq,\n cpc: r.Cp,\n competition: r.Co,\n results: r.Nr,\n }));\n },\n\n async getRelatedKeywords(keyword, database = DEFAULT_DATABASE) {\n const params = buildRelatedKeywordsParams(keyword, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawRelatedKeywordResponse>>(\n relatedKeywordsPath(),\n params,\n );\n return (raw.data ?? []).map((r): SemrushRelatedKeyword => ({\n keyword: r.Ph,\n searchVolume: r.Nq,\n cpc: r.Cp,\n competition: r.Co,\n results: r.Nr,\n relatedTo: r.Rr,\n }));\n },\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Ahrefs Endpoints\n// ============================================================================\n\nexport const AHREFS_BASE_URL = 'https://api.ahrefs.com/v3';\n\nexport function siteOverviewPath(): string {\n return '/site-explorer/overview';\n}\n\nexport function organicKeywordsPath(): string {\n return '/site-explorer/organic-keywords';\n}\n\nexport function backlinksPath(): string {\n return '/site-explorer/backlinks';\n}\n\nexport function keywordDifficultyPath(): string {\n return '/keywords-explorer/keyword-difficulty';\n}\n\nexport function referringDomainsPath(): string {\n return '/site-explorer/referring-domains';\n}\n\nexport function buildSiteOverviewParams(domain: string): Record<string, string> {\n return { target: domain, mode: 'domain' };\n}\n\nexport function buildOrganicKeywordsParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n\nexport function buildBacklinksParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n\nexport function buildKeywordDifficultyParams(\n keywords: string[],\n): Record<string, string> {\n return {\n keywords: keywords.join(','),\n };\n}\n\nexport function buildReferringDomainsParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Ahrefs Client\n// ============================================================================\n\nimport type {\n AhrefsClient,\n AhrefsSiteOverview,\n AhrefsOrganicKeyword,\n AhrefsBacklink,\n AhrefsKeywordDifficulty,\n AhrefsReferringDomain,\n PaginatedResponse,\n AhrefsPaginationOptions,\n HttpClientConfig,\n} from '../types.js';\nimport { createHttpClient } from '../http.js';\nimport {\n AHREFS_BASE_URL,\n siteOverviewPath,\n organicKeywordsPath,\n backlinksPath,\n keywordDifficultyPath,\n referringDomainsPath,\n buildSiteOverviewParams,\n buildOrganicKeywordsParams,\n buildBacklinksParams,\n buildKeywordDifficultyParams,\n buildReferringDomainsParams,\n} from './endpoints.js';\nimport type {\n AhrefsRawSiteOverview,\n AhrefsApiResponse,\n AhrefsRawOrganicKeyword,\n AhrefsRawBacklink,\n AhrefsRawKeywordDifficulty,\n AhrefsRawReferringDomain,\n} from './types.js';\n\nconst DEFAULT_LIMIT = 100;\n\nexport function createAhrefsClient(\n apiToken: string,\n config?: Partial<Omit<HttpClientConfig, 'baseUrl' | 'auth'>>,\n): AhrefsClient {\n const http = createHttpClient({\n baseUrl: AHREFS_BASE_URL,\n auth: { type: 'bearer', token: apiToken },\n ...config,\n });\n\n return {\n async getSiteOverview(domain) {\n const params = buildSiteOverviewParams(domain);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawSiteOverview>>(\n siteOverviewPath(),\n params,\n );\n const entry = raw.data[0];\n return {\n domain,\n domainRating: entry?.domain_rating ?? 0,\n urlRating: entry?.url_rating ?? 0,\n backlinks: entry?.backlinks ?? 0,\n referringDomains: entry?.referring_domains ?? 0,\n organicKeywords: entry?.organic_keywords ?? 0,\n organicTraffic: entry?.organic_traffic ?? 0,\n trafficValue: entry?.traffic_value ?? 0,\n } satisfies AhrefsSiteOverview;\n },\n\n async getOrganicKeywords(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildOrganicKeywordsParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawOrganicKeyword>>(\n organicKeywordsPath(),\n params,\n );\n const data: AhrefsOrganicKeyword[] = (raw.data ?? []).map((r) => ({\n keyword: r.keyword,\n position: r.position,\n searchVolume: r.volume,\n cpc: r.cpc,\n url: r.url,\n traffic: r.traffic,\n trafficPercent: r.traffic_percent,\n difficulty: r.difficulty,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsOrganicKeyword>;\n },\n\n async getBacklinks(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildBacklinksParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawBacklink>>(\n backlinksPath(),\n params,\n );\n const data: AhrefsBacklink[] = (raw.data ?? []).map((r) => ({\n sourceUrl: r.url_from,\n targetUrl: r.url_to,\n anchorText: r.anchor,\n domainRating: r.domain_rating,\n urlRating: r.url_rating,\n isDoFollow: r.is_dofollow,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsBacklink>;\n },\n\n async getKeywordDifficulty(keywords) {\n const params = buildKeywordDifficultyParams(keywords);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawKeywordDifficulty>>(\n keywordDifficultyPath(),\n params,\n );\n return (raw.data ?? []).map((r): AhrefsKeywordDifficulty => ({\n keyword: r.keyword,\n difficulty: r.difficulty,\n searchVolume: r.volume,\n cpc: r.cpc,\n clicks: r.clicks,\n globalVolume: r.global_volume,\n }));\n },\n\n async getReferringDomains(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildReferringDomainsParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawReferringDomain>>(\n referringDomainsPath(),\n params,\n );\n const data: AhrefsReferringDomain[] = (raw.data ?? []).map((r) => ({\n domain: r.domain,\n domainRating: r.domain_rating,\n backlinks: r.backlinks,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n isDoFollow: r.is_dofollow,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsReferringDomain>;\n },\n };\n}\n"]} | ||
| {"version":3,"sources":["../src/types.ts","../src/http.ts","../src/semrush/endpoints.ts","../src/semrush/client.ts","../src/ahrefs/endpoints.ts","../src/ahrefs/client.ts"],"names":["createTokenBucket","getWaitTime","sleep","consumeToken","organicKeywordsPath","backlinksPath","keywordDifficultyPath","buildOrganicKeywordsParams","buildBacklinksParams","buildKeywordDifficultyParams","DEFAULT_LIMIT"],"mappings":"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","file":"index.cjs","sourcesContent":["// ============================================================================\n// @power-seo/integrations — Types\n// ============================================================================\n\n// --- HTTP Client Types ---\n\nexport type AuthStrategy =\n | { type: 'query'; paramName: string; value: string }\n | { type: 'bearer'; token: string };\n\nexport interface HttpClientConfig {\n baseUrl: string;\n auth: AuthStrategy;\n rateLimitPerMinute?: number;\n maxRetries?: number;\n timeoutMs?: number;\n}\n\nexport interface HttpClient {\n get: <T>(path: string, params?: Record<string, string>) => Promise<T>;\n post: <T>(path: string, body?: unknown) => Promise<T>;\n}\n\n// --- Error ---\n\nexport class IntegrationApiError extends Error {\n readonly status: number;\n readonly provider: string;\n readonly retryable: boolean;\n\n constructor(message: string, status: number, provider: string) {\n super(message);\n this.name = 'IntegrationApiError';\n this.status = status;\n this.provider = provider;\n this.retryable = status === 429 || status >= 500;\n }\n}\n\n// --- Pagination ---\n\nexport interface PaginatedResponse<T> {\n data: T[];\n total: number;\n offset: number;\n limit: number;\n hasMore: boolean;\n}\n\n// --- Semrush Types ---\n\nexport interface SemrushDomainOverview {\n domain: string;\n organicKeywords: number;\n organicTraffic: number;\n organicCost: number;\n paidKeywords: number;\n paidTraffic: number;\n paidCost: number;\n backlinks: number;\n authorityScore: number;\n}\n\nexport interface SemrushKeywordData {\n keyword: string;\n position: number;\n previousPosition: number;\n searchVolume: number;\n cpc: number;\n url: string;\n traffic: number;\n trafficPercent: number;\n trafficCost: number;\n competition: number;\n}\n\nexport interface SemrushBacklinkData {\n sourceUrl: string;\n targetUrl: string;\n anchorText: string;\n isNoFollow: boolean;\n firstSeen: string;\n lastSeen: string;\n sourceAuthorityScore: number;\n}\n\nexport interface SemrushKeywordDifficulty {\n keyword: string;\n difficulty: number;\n searchVolume: number;\n cpc: number;\n competition: number;\n results: number;\n}\n\nexport interface SemrushRelatedKeyword {\n keyword: string;\n searchVolume: number;\n cpc: number;\n competition: number;\n results: number;\n relatedTo: string;\n}\n\nexport interface SemrushClient {\n getDomainOverview: (domain: string, database?: string) => Promise<SemrushDomainOverview>;\n getOrganicKeywords: (\n domain: string,\n options?: SemrushPaginationOptions,\n ) => Promise<PaginatedResponse<SemrushKeywordData>>;\n getBacklinks: (\n domain: string,\n options?: SemrushPaginationOptions,\n ) => Promise<PaginatedResponse<SemrushBacklinkData>>;\n getKeywordDifficulty: (\n keywords: string[],\n database?: string,\n ) => Promise<SemrushKeywordDifficulty[]>;\n getRelatedKeywords: (keyword: string, database?: string) => Promise<SemrushRelatedKeyword[]>;\n}\n\nexport interface SemrushPaginationOptions {\n limit?: number;\n offset?: number;\n database?: string;\n}\n\n// --- Ahrefs Types ---\n\nexport interface AhrefsSiteOverview {\n domain: string;\n domainRating: number;\n urlRating: number;\n backlinks: number;\n referringDomains: number;\n organicKeywords: number;\n organicTraffic: number;\n trafficValue: number;\n}\n\nexport interface AhrefsOrganicKeyword {\n keyword: string;\n position: number;\n searchVolume: number;\n cpc: number;\n url: string;\n traffic: number;\n trafficPercent: number;\n difficulty: number;\n}\n\nexport interface AhrefsBacklink {\n sourceUrl: string;\n targetUrl: string;\n anchorText: string;\n domainRating: number;\n urlRating: number;\n isDoFollow: boolean;\n firstSeen: string;\n lastSeen: string;\n}\n\nexport interface AhrefsKeywordDifficulty {\n keyword: string;\n difficulty: number;\n searchVolume: number;\n cpc: number;\n clicks: number;\n globalVolume: number;\n}\n\nexport interface AhrefsReferringDomain {\n domain: string;\n domainRating: number;\n backlinks: number;\n firstSeen: string;\n lastSeen: string;\n isDoFollow: boolean;\n}\n\nexport interface AhrefsClient {\n getSiteOverview: (domain: string) => Promise<AhrefsSiteOverview>;\n getOrganicKeywords: (\n domain: string,\n options?: AhrefsPaginationOptions,\n ) => Promise<PaginatedResponse<AhrefsOrganicKeyword>>;\n getBacklinks: (\n domain: string,\n options?: AhrefsPaginationOptions,\n ) => Promise<PaginatedResponse<AhrefsBacklink>>;\n getKeywordDifficulty: (keywords: string[]) => Promise<AhrefsKeywordDifficulty[]>;\n getReferringDomains: (\n domain: string,\n options?: AhrefsPaginationOptions,\n ) => Promise<PaginatedResponse<AhrefsReferringDomain>>;\n}\n\nexport interface AhrefsPaginationOptions {\n limit?: number;\n offset?: number;\n}\n","// ============================================================================\n// @power-seo/integrations — Shared HTTP Client\n// ============================================================================\n\nimport type { HttpClientConfig, HttpClient, AuthStrategy } from './types.js';\nimport { IntegrationApiError } from './types.js';\nimport { createTokenBucket, consumeToken, getWaitTime, sleep } from '@power-seo/core';\n\nconst DEFAULT_RATE_LIMIT = 600;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nfunction buildUrl(\n baseUrl: string,\n path: string,\n params: Record<string, string>,\n auth: AuthStrategy,\n): string {\n const url = new globalThis.URL(`${baseUrl}${path}`);\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value);\n }\n if (auth.type === 'query') {\n url.searchParams.set(auth.paramName, auth.value);\n }\n return url.toString();\n}\n\nfunction buildHeaders(auth: AuthStrategy): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n if (auth.type === 'bearer') {\n headers['Authorization'] = `Bearer ${auth.token}`;\n }\n return headers;\n}\n\nfunction getProviderFromUrl(baseUrl: string): string {\n if (baseUrl.includes('semrush')) return 'semrush';\n if (baseUrl.includes('ahrefs')) return 'ahrefs';\n return 'unknown';\n}\n\nexport function createHttpClient(config: HttpClientConfig): HttpClient {\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const bucket = createTokenBucket(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT);\n const provider = getProviderFromUrl(config.baseUrl);\n\n async function makeRequest<T>(url: string, init: globalThis.RequestInit): Promise<T> {\n const waitTime = getWaitTime(bucket);\n if (waitTime > 0) {\n await sleep(waitTime);\n }\n consumeToken(bucket);\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const controller = new globalThis.AbortController();\n const timeout = globalThis.setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await globalThis.fetch(url, {\n ...init,\n signal: controller.signal,\n });\n\n globalThis.clearTimeout(timeout);\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const text = await response.text();\n const error = new IntegrationApiError(\n `${provider} API error: ${response.status} ${text}`,\n response.status,\n provider,\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 globalThis.clearTimeout(timeout);\n if (err instanceof IntegrationApiError) {\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 IntegrationApiError('Request failed', 500, provider);\n }\n\n return {\n async get<T>(path: string, params?: Record<string, string>): Promise<T> {\n const url = buildUrl(config.baseUrl, path, params ?? {}, config.auth);\n const headers = buildHeaders(config.auth);\n return makeRequest<T>(url, { method: 'GET', headers });\n },\n\n async post<T>(path: string, body?: unknown): Promise<T> {\n const url = buildUrl(config.baseUrl, path, {}, config.auth);\n const headers = buildHeaders(config.auth);\n return makeRequest<T>(url, {\n method: 'POST',\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n },\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Semrush Endpoints\n// ============================================================================\n\nexport const SEMRUSH_BASE_URL = 'https://api.semrush.com';\n\nexport function domainOverviewPath(): string {\n return '/analytics/v1/';\n}\n\nexport function organicKeywordsPath(): string {\n return '/analytics/v1/';\n}\n\nexport function backlinksPath(): string {\n return '/analytics/v1/';\n}\n\nexport function keywordDifficultyPath(): string {\n return '/analytics/v1/';\n}\n\nexport function relatedKeywordsPath(): string {\n return '/analytics/v1/';\n}\n\nexport function buildDomainOverviewParams(\n domain: string,\n database: string,\n): Record<string, string> {\n return {\n type: 'domain_ranks',\n domain,\n database,\n export_columns: 'Or,Ot,Oc,Ad,At,Ac,Bk,As',\n };\n}\n\nexport function buildOrganicKeywordsParams(\n domain: string,\n database: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n type: 'domain_organic',\n domain,\n database,\n display_limit: String(limit),\n display_offset: String(offset),\n export_columns: 'Ph,Po,Pp,Nq,Cp,Ur,Tr,Tc,Co,Td',\n };\n}\n\nexport function buildBacklinksParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n type: 'backlinks',\n target: domain,\n target_type: 'root_domain',\n display_limit: String(limit),\n display_offset: String(offset),\n export_columns: 'source_url,target_url,anchor,nofollow,first_seen,last_seen,source_ascore',\n };\n}\n\nexport function buildKeywordDifficultyParams(\n keywords: string[],\n database: string,\n): Record<string, string> {\n return {\n type: 'phrase_all',\n phrase: keywords.join(';'),\n database,\n export_columns: 'Ph,Kd,Nq,Cp,Co,Nr',\n };\n}\n\nexport function buildRelatedKeywordsParams(\n keyword: string,\n database: string,\n): Record<string, string> {\n return {\n type: 'phrase_related',\n phrase: keyword,\n database,\n export_columns: 'Ph,Nq,Cp,Co,Nr,Rr',\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Semrush Client\n// ============================================================================\n\nimport type {\n SemrushClient,\n SemrushDomainOverview,\n SemrushKeywordData,\n SemrushBacklinkData,\n SemrushKeywordDifficulty,\n SemrushRelatedKeyword,\n PaginatedResponse,\n SemrushPaginationOptions,\n HttpClientConfig,\n} from '../types.js';\nimport { createHttpClient } from '../http.js';\nimport {\n SEMRUSH_BASE_URL,\n domainOverviewPath,\n organicKeywordsPath,\n backlinksPath,\n keywordDifficultyPath,\n relatedKeywordsPath,\n buildDomainOverviewParams,\n buildOrganicKeywordsParams,\n buildBacklinksParams,\n buildKeywordDifficultyParams,\n buildRelatedKeywordsParams,\n} from './endpoints.js';\nimport type {\n SemrushRawDomainResponse,\n SemrushApiResponse,\n SemrushRawKeywordResponse,\n SemrushRawBacklinkResponse,\n SemrushRawKeywordDifficultyResponse,\n SemrushRawRelatedKeywordResponse,\n} from './types.js';\n\nconst DEFAULT_LIMIT = 100;\nconst DEFAULT_DATABASE = 'us';\n\nexport function createSemrushClient(\n apiKey: string,\n config?: Partial<Omit<HttpClientConfig, 'baseUrl' | 'auth'>>,\n): SemrushClient {\n const http = createHttpClient({\n baseUrl: SEMRUSH_BASE_URL,\n auth: { type: 'query', paramName: 'key', value: apiKey },\n ...config,\n });\n\n return {\n async getDomainOverview(domain, database = DEFAULT_DATABASE) {\n const params = buildDomainOverviewParams(domain, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawDomainResponse>>(\n domainOverviewPath(),\n params,\n );\n const entry = raw.data[0];\n return {\n domain,\n organicKeywords: entry?.Or ?? 0,\n organicTraffic: entry?.Ot ?? 0,\n organicCost: entry?.Oc ?? 0,\n paidKeywords: entry?.Ad ?? 0,\n paidTraffic: entry?.At ?? 0,\n paidCost: entry?.Ac ?? 0,\n backlinks: entry?.Bk ?? 0,\n authorityScore: entry?.As ?? 0,\n } satisfies SemrushDomainOverview;\n },\n\n async getOrganicKeywords(domain, options?: SemrushPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const database = options?.database ?? DEFAULT_DATABASE;\n const params = buildOrganicKeywordsParams(domain, database, limit, offset);\n const raw = await http.get<SemrushApiResponse<SemrushRawKeywordResponse>>(\n organicKeywordsPath(),\n params,\n );\n const data: SemrushKeywordData[] = (raw.data ?? []).map((r) => ({\n keyword: r.Ph,\n position: r.Po,\n previousPosition: r.Pp,\n searchVolume: r.Nq,\n cpc: r.Cp,\n url: r.Ur,\n traffic: r.Tr,\n trafficPercent: r.Td,\n trafficCost: r.Tc,\n competition: r.Co,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<SemrushKeywordData>;\n },\n\n async getBacklinks(domain, options?: SemrushPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildBacklinksParams(domain, limit, offset);\n const raw = await http.get<SemrushApiResponse<SemrushRawBacklinkResponse>>(\n backlinksPath(),\n params,\n );\n const data: SemrushBacklinkData[] = (raw.data ?? []).map((r) => ({\n sourceUrl: r.source_url,\n targetUrl: r.target_url,\n anchorText: r.anchor,\n isNoFollow: r.nofollow,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n sourceAuthorityScore: r.source_ascore,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<SemrushBacklinkData>;\n },\n\n async getKeywordDifficulty(keywords, database = DEFAULT_DATABASE) {\n const params = buildKeywordDifficultyParams(keywords, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawKeywordDifficultyResponse>>(\n keywordDifficultyPath(),\n params,\n );\n return (raw.data ?? []).map(\n (r): SemrushKeywordDifficulty => ({\n keyword: r.Ph,\n difficulty: r.Kd,\n searchVolume: r.Nq,\n cpc: r.Cp,\n competition: r.Co,\n results: r.Nr,\n }),\n );\n },\n\n async getRelatedKeywords(keyword, database = DEFAULT_DATABASE) {\n const params = buildRelatedKeywordsParams(keyword, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawRelatedKeywordResponse>>(\n relatedKeywordsPath(),\n params,\n );\n return (raw.data ?? []).map(\n (r): SemrushRelatedKeyword => ({\n keyword: r.Ph,\n searchVolume: r.Nq,\n cpc: r.Cp,\n competition: r.Co,\n results: r.Nr,\n relatedTo: r.Rr,\n }),\n );\n },\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Ahrefs Endpoints\n// ============================================================================\n\nexport const AHREFS_BASE_URL = 'https://api.ahrefs.com/v3';\n\nexport function siteOverviewPath(): string {\n return '/site-explorer/overview';\n}\n\nexport function organicKeywordsPath(): string {\n return '/site-explorer/organic-keywords';\n}\n\nexport function backlinksPath(): string {\n return '/site-explorer/backlinks';\n}\n\nexport function keywordDifficultyPath(): string {\n return '/keywords-explorer/keyword-difficulty';\n}\n\nexport function referringDomainsPath(): string {\n return '/site-explorer/referring-domains';\n}\n\nexport function buildSiteOverviewParams(domain: string): Record<string, string> {\n return { target: domain, mode: 'domain' };\n}\n\nexport function buildOrganicKeywordsParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n\nexport function buildBacklinksParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n\nexport function buildKeywordDifficultyParams(keywords: string[]): Record<string, string> {\n return {\n keywords: keywords.join(','),\n };\n}\n\nexport function buildReferringDomainsParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Ahrefs Client\n// ============================================================================\n\nimport type {\n AhrefsClient,\n AhrefsSiteOverview,\n AhrefsOrganicKeyword,\n AhrefsBacklink,\n AhrefsKeywordDifficulty,\n AhrefsReferringDomain,\n PaginatedResponse,\n AhrefsPaginationOptions,\n HttpClientConfig,\n} from '../types.js';\nimport { createHttpClient } from '../http.js';\nimport {\n AHREFS_BASE_URL,\n siteOverviewPath,\n organicKeywordsPath,\n backlinksPath,\n keywordDifficultyPath,\n referringDomainsPath,\n buildSiteOverviewParams,\n buildOrganicKeywordsParams,\n buildBacklinksParams,\n buildKeywordDifficultyParams,\n buildReferringDomainsParams,\n} from './endpoints.js';\nimport type {\n AhrefsRawSiteOverview,\n AhrefsApiResponse,\n AhrefsRawOrganicKeyword,\n AhrefsRawBacklink,\n AhrefsRawKeywordDifficulty,\n AhrefsRawReferringDomain,\n} from './types.js';\n\nconst DEFAULT_LIMIT = 100;\n\nexport function createAhrefsClient(\n apiToken: string,\n config?: Partial<Omit<HttpClientConfig, 'baseUrl' | 'auth'>>,\n): AhrefsClient {\n const http = createHttpClient({\n baseUrl: AHREFS_BASE_URL,\n auth: { type: 'bearer', token: apiToken },\n ...config,\n });\n\n return {\n async getSiteOverview(domain) {\n const params = buildSiteOverviewParams(domain);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawSiteOverview>>(\n siteOverviewPath(),\n params,\n );\n const entry = raw.data[0];\n return {\n domain,\n domainRating: entry?.domain_rating ?? 0,\n urlRating: entry?.url_rating ?? 0,\n backlinks: entry?.backlinks ?? 0,\n referringDomains: entry?.referring_domains ?? 0,\n organicKeywords: entry?.organic_keywords ?? 0,\n organicTraffic: entry?.organic_traffic ?? 0,\n trafficValue: entry?.traffic_value ?? 0,\n } satisfies AhrefsSiteOverview;\n },\n\n async getOrganicKeywords(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildOrganicKeywordsParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawOrganicKeyword>>(\n organicKeywordsPath(),\n params,\n );\n const data: AhrefsOrganicKeyword[] = (raw.data ?? []).map((r) => ({\n keyword: r.keyword,\n position: r.position,\n searchVolume: r.volume,\n cpc: r.cpc,\n url: r.url,\n traffic: r.traffic,\n trafficPercent: r.traffic_percent,\n difficulty: r.difficulty,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsOrganicKeyword>;\n },\n\n async getBacklinks(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildBacklinksParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawBacklink>>(backlinksPath(), params);\n const data: AhrefsBacklink[] = (raw.data ?? []).map((r) => ({\n sourceUrl: r.url_from,\n targetUrl: r.url_to,\n anchorText: r.anchor,\n domainRating: r.domain_rating,\n urlRating: r.url_rating,\n isDoFollow: r.is_dofollow,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsBacklink>;\n },\n\n async getKeywordDifficulty(keywords) {\n const params = buildKeywordDifficultyParams(keywords);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawKeywordDifficulty>>(\n keywordDifficultyPath(),\n params,\n );\n return (raw.data ?? []).map(\n (r): AhrefsKeywordDifficulty => ({\n keyword: r.keyword,\n difficulty: r.difficulty,\n searchVolume: r.volume,\n cpc: r.cpc,\n clicks: r.clicks,\n globalVolume: r.global_volume,\n }),\n );\n },\n\n async getReferringDomains(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildReferringDomainsParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawReferringDomain>>(\n referringDomainsPath(),\n params,\n );\n const data: AhrefsReferringDomain[] = (raw.data ?? []).map((r) => ({\n domain: r.domain,\n domainRating: r.domain_rating,\n backlinks: r.backlinks,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n isDoFollow: r.is_dofollow,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsReferringDomain>;\n },\n };\n}\n"]} |
+31
-28
@@ -265,10 +265,12 @@ import { createTokenBucket, getWaitTime, sleep, consumeToken } from '@power-seo/core'; | ||
| ); | ||
| return (raw.data ?? []).map((r) => ({ | ||
| keyword: r.Ph, | ||
| difficulty: r.Kd, | ||
| searchVolume: r.Nq, | ||
| cpc: r.Cp, | ||
| competition: r.Co, | ||
| results: r.Nr | ||
| })); | ||
| return (raw.data ?? []).map( | ||
| (r) => ({ | ||
| keyword: r.Ph, | ||
| difficulty: r.Kd, | ||
| searchVolume: r.Nq, | ||
| cpc: r.Cp, | ||
| competition: r.Co, | ||
| results: r.Nr | ||
| }) | ||
| ); | ||
| }, | ||
@@ -281,10 +283,12 @@ async getRelatedKeywords(keyword, database = DEFAULT_DATABASE) { | ||
| ); | ||
| return (raw.data ?? []).map((r) => ({ | ||
| keyword: r.Ph, | ||
| searchVolume: r.Nq, | ||
| cpc: r.Cp, | ||
| competition: r.Co, | ||
| results: r.Nr, | ||
| relatedTo: r.Rr | ||
| })); | ||
| return (raw.data ?? []).map( | ||
| (r) => ({ | ||
| keyword: r.Ph, | ||
| searchVolume: r.Nq, | ||
| cpc: r.Cp, | ||
| competition: r.Co, | ||
| results: r.Nr, | ||
| relatedTo: r.Rr | ||
| }) | ||
| ); | ||
| } | ||
@@ -401,6 +405,3 @@ }; | ||
| const params = buildBacklinksParams2(domain, limit, offset); | ||
| const raw = await http.get( | ||
| backlinksPath2(), | ||
| params | ||
| ); | ||
| const raw = await http.get(backlinksPath2(), params); | ||
| const data = (raw.data ?? []).map((r) => ({ | ||
@@ -430,10 +431,12 @@ sourceUrl: r.url_from, | ||
| ); | ||
| return (raw.data ?? []).map((r) => ({ | ||
| keyword: r.keyword, | ||
| difficulty: r.difficulty, | ||
| searchVolume: r.volume, | ||
| cpc: r.cpc, | ||
| clicks: r.clicks, | ||
| globalVolume: r.global_volume | ||
| })); | ||
| return (raw.data ?? []).map( | ||
| (r) => ({ | ||
| keyword: r.keyword, | ||
| difficulty: r.difficulty, | ||
| searchVolume: r.volume, | ||
| cpc: r.cpc, | ||
| clicks: r.clicks, | ||
| globalVolume: r.global_volume | ||
| }) | ||
| ); | ||
| }, | ||
@@ -440,0 +443,0 @@ async getReferringDomains(domain, options) { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/types.ts","../src/http.ts","../src/semrush/endpoints.ts","../src/semrush/client.ts","../src/ahrefs/endpoints.ts","../src/ahrefs/client.ts"],"names":["organicKeywordsPath","backlinksPath","keywordDifficultyPath","buildOrganicKeywordsParams","buildBacklinksParams","buildKeywordDifficultyParams","DEFAULT_LIMIT"],"mappings":"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","file":"index.js","sourcesContent":["// ============================================================================\n// @power-seo/integrations — Types\n// ============================================================================\n\n// --- HTTP Client Types ---\n\nexport type AuthStrategy =\n | { type: 'query'; paramName: string; value: string }\n | { type: 'bearer'; token: string };\n\nexport interface HttpClientConfig {\n baseUrl: string;\n auth: AuthStrategy;\n rateLimitPerMinute?: number;\n maxRetries?: number;\n timeoutMs?: number;\n}\n\nexport interface HttpClient {\n get: <T>(path: string, params?: Record<string, string>) => Promise<T>;\n post: <T>(path: string, body?: unknown) => Promise<T>;\n}\n\n// --- Error ---\n\nexport class IntegrationApiError extends Error {\n readonly status: number;\n readonly provider: string;\n readonly retryable: boolean;\n\n constructor(message: string, status: number, provider: string) {\n super(message);\n this.name = 'IntegrationApiError';\n this.status = status;\n this.provider = provider;\n this.retryable = status === 429 || status >= 500;\n }\n}\n\n// --- Pagination ---\n\nexport interface PaginatedResponse<T> {\n data: T[];\n total: number;\n offset: number;\n limit: number;\n hasMore: boolean;\n}\n\n// --- Semrush Types ---\n\nexport interface SemrushDomainOverview {\n domain: string;\n organicKeywords: number;\n organicTraffic: number;\n organicCost: number;\n paidKeywords: number;\n paidTraffic: number;\n paidCost: number;\n backlinks: number;\n authorityScore: number;\n}\n\nexport interface SemrushKeywordData {\n keyword: string;\n position: number;\n previousPosition: number;\n searchVolume: number;\n cpc: number;\n url: string;\n traffic: number;\n trafficPercent: number;\n trafficCost: number;\n competition: number;\n}\n\nexport interface SemrushBacklinkData {\n sourceUrl: string;\n targetUrl: string;\n anchorText: string;\n isNoFollow: boolean;\n firstSeen: string;\n lastSeen: string;\n sourceAuthorityScore: number;\n}\n\nexport interface SemrushKeywordDifficulty {\n keyword: string;\n difficulty: number;\n searchVolume: number;\n cpc: number;\n competition: number;\n results: number;\n}\n\nexport interface SemrushRelatedKeyword {\n keyword: string;\n searchVolume: number;\n cpc: number;\n competition: number;\n results: number;\n relatedTo: string;\n}\n\nexport interface SemrushClient {\n getDomainOverview: (domain: string, database?: string) => Promise<SemrushDomainOverview>;\n getOrganicKeywords: (domain: string, options?: SemrushPaginationOptions) => Promise<PaginatedResponse<SemrushKeywordData>>;\n getBacklinks: (domain: string, options?: SemrushPaginationOptions) => Promise<PaginatedResponse<SemrushBacklinkData>>;\n getKeywordDifficulty: (keywords: string[], database?: string) => Promise<SemrushKeywordDifficulty[]>;\n getRelatedKeywords: (keyword: string, database?: string) => Promise<SemrushRelatedKeyword[]>;\n}\n\nexport interface SemrushPaginationOptions {\n limit?: number;\n offset?: number;\n database?: string;\n}\n\n// --- Ahrefs Types ---\n\nexport interface AhrefsSiteOverview {\n domain: string;\n domainRating: number;\n urlRating: number;\n backlinks: number;\n referringDomains: number;\n organicKeywords: number;\n organicTraffic: number;\n trafficValue: number;\n}\n\nexport interface AhrefsOrganicKeyword {\n keyword: string;\n position: number;\n searchVolume: number;\n cpc: number;\n url: string;\n traffic: number;\n trafficPercent: number;\n difficulty: number;\n}\n\nexport interface AhrefsBacklink {\n sourceUrl: string;\n targetUrl: string;\n anchorText: string;\n domainRating: number;\n urlRating: number;\n isDoFollow: boolean;\n firstSeen: string;\n lastSeen: string;\n}\n\nexport interface AhrefsKeywordDifficulty {\n keyword: string;\n difficulty: number;\n searchVolume: number;\n cpc: number;\n clicks: number;\n globalVolume: number;\n}\n\nexport interface AhrefsReferringDomain {\n domain: string;\n domainRating: number;\n backlinks: number;\n firstSeen: string;\n lastSeen: string;\n isDoFollow: boolean;\n}\n\nexport interface AhrefsClient {\n getSiteOverview: (domain: string) => Promise<AhrefsSiteOverview>;\n getOrganicKeywords: (domain: string, options?: AhrefsPaginationOptions) => Promise<PaginatedResponse<AhrefsOrganicKeyword>>;\n getBacklinks: (domain: string, options?: AhrefsPaginationOptions) => Promise<PaginatedResponse<AhrefsBacklink>>;\n getKeywordDifficulty: (keywords: string[]) => Promise<AhrefsKeywordDifficulty[]>;\n getReferringDomains: (domain: string, options?: AhrefsPaginationOptions) => Promise<PaginatedResponse<AhrefsReferringDomain>>;\n}\n\nexport interface AhrefsPaginationOptions {\n limit?: number;\n offset?: number;\n}\n","// ============================================================================\n// @power-seo/integrations — Shared HTTP Client\n// ============================================================================\n\nimport type { HttpClientConfig, HttpClient, AuthStrategy } from './types.js';\nimport { IntegrationApiError } from './types.js';\nimport { createTokenBucket, consumeToken, getWaitTime, sleep } from '@power-seo/core';\n\nconst DEFAULT_RATE_LIMIT = 600;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nfunction buildUrl(\n baseUrl: string,\n path: string,\n params: Record<string, string>,\n auth: AuthStrategy,\n): string {\n const url = new globalThis.URL(`${baseUrl}${path}`);\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value);\n }\n if (auth.type === 'query') {\n url.searchParams.set(auth.paramName, auth.value);\n }\n return url.toString();\n}\n\nfunction buildHeaders(auth: AuthStrategy): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n if (auth.type === 'bearer') {\n headers['Authorization'] = `Bearer ${auth.token}`;\n }\n return headers;\n}\n\nfunction getProviderFromUrl(baseUrl: string): string {\n if (baseUrl.includes('semrush')) return 'semrush';\n if (baseUrl.includes('ahrefs')) return 'ahrefs';\n return 'unknown';\n}\n\nexport function createHttpClient(config: HttpClientConfig): HttpClient {\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const bucket = createTokenBucket(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT);\n const provider = getProviderFromUrl(config.baseUrl);\n\n async function makeRequest<T>(\n url: string,\n init: globalThis.RequestInit,\n ): Promise<T> {\n const waitTime = getWaitTime(bucket);\n if (waitTime > 0) {\n await sleep(waitTime);\n }\n consumeToken(bucket);\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const controller = new globalThis.AbortController();\n const timeout = globalThis.setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await globalThis.fetch(url, {\n ...init,\n signal: controller.signal,\n });\n\n globalThis.clearTimeout(timeout);\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const text = await response.text();\n const error = new IntegrationApiError(\n `${provider} API error: ${response.status} ${text}`,\n response.status,\n provider,\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 globalThis.clearTimeout(timeout);\n if (err instanceof IntegrationApiError) {\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 IntegrationApiError('Request failed', 500, provider);\n }\n\n return {\n async get<T>(path: string, params?: Record<string, string>): Promise<T> {\n const url = buildUrl(config.baseUrl, path, params ?? {}, config.auth);\n const headers = buildHeaders(config.auth);\n return makeRequest<T>(url, { method: 'GET', headers });\n },\n\n async post<T>(path: string, body?: unknown): Promise<T> {\n const url = buildUrl(config.baseUrl, path, {}, config.auth);\n const headers = buildHeaders(config.auth);\n return makeRequest<T>(url, {\n method: 'POST',\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n },\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Semrush Endpoints\n// ============================================================================\n\nexport const SEMRUSH_BASE_URL = 'https://api.semrush.com';\n\nexport function domainOverviewPath(): string {\n return '/analytics/v1/';\n}\n\nexport function organicKeywordsPath(): string {\n return '/analytics/v1/';\n}\n\nexport function backlinksPath(): string {\n return '/analytics/v1/';\n}\n\nexport function keywordDifficultyPath(): string {\n return '/analytics/v1/';\n}\n\nexport function relatedKeywordsPath(): string {\n return '/analytics/v1/';\n}\n\nexport function buildDomainOverviewParams(domain: string, database: string): Record<string, string> {\n return {\n type: 'domain_ranks',\n domain,\n database,\n export_columns: 'Or,Ot,Oc,Ad,At,Ac,Bk,As',\n };\n}\n\nexport function buildOrganicKeywordsParams(\n domain: string,\n database: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n type: 'domain_organic',\n domain,\n database,\n display_limit: String(limit),\n display_offset: String(offset),\n export_columns: 'Ph,Po,Pp,Nq,Cp,Ur,Tr,Tc,Co,Td',\n };\n}\n\nexport function buildBacklinksParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n type: 'backlinks',\n target: domain,\n target_type: 'root_domain',\n display_limit: String(limit),\n display_offset: String(offset),\n export_columns: 'source_url,target_url,anchor,nofollow,first_seen,last_seen,source_ascore',\n };\n}\n\nexport function buildKeywordDifficultyParams(\n keywords: string[],\n database: string,\n): Record<string, string> {\n return {\n type: 'phrase_all',\n phrase: keywords.join(';'),\n database,\n export_columns: 'Ph,Kd,Nq,Cp,Co,Nr',\n };\n}\n\nexport function buildRelatedKeywordsParams(\n keyword: string,\n database: string,\n): Record<string, string> {\n return {\n type: 'phrase_related',\n phrase: keyword,\n database,\n export_columns: 'Ph,Nq,Cp,Co,Nr,Rr',\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Semrush Client\n// ============================================================================\n\nimport type {\n SemrushClient,\n SemrushDomainOverview,\n SemrushKeywordData,\n SemrushBacklinkData,\n SemrushKeywordDifficulty,\n SemrushRelatedKeyword,\n PaginatedResponse,\n SemrushPaginationOptions,\n HttpClientConfig,\n} from '../types.js';\nimport { createHttpClient } from '../http.js';\nimport {\n SEMRUSH_BASE_URL,\n domainOverviewPath,\n organicKeywordsPath,\n backlinksPath,\n keywordDifficultyPath,\n relatedKeywordsPath,\n buildDomainOverviewParams,\n buildOrganicKeywordsParams,\n buildBacklinksParams,\n buildKeywordDifficultyParams,\n buildRelatedKeywordsParams,\n} from './endpoints.js';\nimport type {\n SemrushRawDomainResponse,\n SemrushApiResponse,\n SemrushRawKeywordResponse,\n SemrushRawBacklinkResponse,\n SemrushRawKeywordDifficultyResponse,\n SemrushRawRelatedKeywordResponse,\n} from './types.js';\n\nconst DEFAULT_LIMIT = 100;\nconst DEFAULT_DATABASE = 'us';\n\nexport function createSemrushClient(\n apiKey: string,\n config?: Partial<Omit<HttpClientConfig, 'baseUrl' | 'auth'>>,\n): SemrushClient {\n const http = createHttpClient({\n baseUrl: SEMRUSH_BASE_URL,\n auth: { type: 'query', paramName: 'key', value: apiKey },\n ...config,\n });\n\n return {\n async getDomainOverview(domain, database = DEFAULT_DATABASE) {\n const params = buildDomainOverviewParams(domain, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawDomainResponse>>(\n domainOverviewPath(),\n params,\n );\n const entry = raw.data[0];\n return {\n domain,\n organicKeywords: entry?.Or ?? 0,\n organicTraffic: entry?.Ot ?? 0,\n organicCost: entry?.Oc ?? 0,\n paidKeywords: entry?.Ad ?? 0,\n paidTraffic: entry?.At ?? 0,\n paidCost: entry?.Ac ?? 0,\n backlinks: entry?.Bk ?? 0,\n authorityScore: entry?.As ?? 0,\n } satisfies SemrushDomainOverview;\n },\n\n async getOrganicKeywords(domain, options?: SemrushPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const database = options?.database ?? DEFAULT_DATABASE;\n const params = buildOrganicKeywordsParams(domain, database, limit, offset);\n const raw = await http.get<SemrushApiResponse<SemrushRawKeywordResponse>>(\n organicKeywordsPath(),\n params,\n );\n const data: SemrushKeywordData[] = (raw.data ?? []).map((r) => ({\n keyword: r.Ph,\n position: r.Po,\n previousPosition: r.Pp,\n searchVolume: r.Nq,\n cpc: r.Cp,\n url: r.Ur,\n traffic: r.Tr,\n trafficPercent: r.Td,\n trafficCost: r.Tc,\n competition: r.Co,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<SemrushKeywordData>;\n },\n\n async getBacklinks(domain, options?: SemrushPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildBacklinksParams(domain, limit, offset);\n const raw = await http.get<SemrushApiResponse<SemrushRawBacklinkResponse>>(\n backlinksPath(),\n params,\n );\n const data: SemrushBacklinkData[] = (raw.data ?? []).map((r) => ({\n sourceUrl: r.source_url,\n targetUrl: r.target_url,\n anchorText: r.anchor,\n isNoFollow: r.nofollow,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n sourceAuthorityScore: r.source_ascore,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<SemrushBacklinkData>;\n },\n\n async getKeywordDifficulty(keywords, database = DEFAULT_DATABASE) {\n const params = buildKeywordDifficultyParams(keywords, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawKeywordDifficultyResponse>>(\n keywordDifficultyPath(),\n params,\n );\n return (raw.data ?? []).map((r): SemrushKeywordDifficulty => ({\n keyword: r.Ph,\n difficulty: r.Kd,\n searchVolume: r.Nq,\n cpc: r.Cp,\n competition: r.Co,\n results: r.Nr,\n }));\n },\n\n async getRelatedKeywords(keyword, database = DEFAULT_DATABASE) {\n const params = buildRelatedKeywordsParams(keyword, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawRelatedKeywordResponse>>(\n relatedKeywordsPath(),\n params,\n );\n return (raw.data ?? []).map((r): SemrushRelatedKeyword => ({\n keyword: r.Ph,\n searchVolume: r.Nq,\n cpc: r.Cp,\n competition: r.Co,\n results: r.Nr,\n relatedTo: r.Rr,\n }));\n },\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Ahrefs Endpoints\n// ============================================================================\n\nexport const AHREFS_BASE_URL = 'https://api.ahrefs.com/v3';\n\nexport function siteOverviewPath(): string {\n return '/site-explorer/overview';\n}\n\nexport function organicKeywordsPath(): string {\n return '/site-explorer/organic-keywords';\n}\n\nexport function backlinksPath(): string {\n return '/site-explorer/backlinks';\n}\n\nexport function keywordDifficultyPath(): string {\n return '/keywords-explorer/keyword-difficulty';\n}\n\nexport function referringDomainsPath(): string {\n return '/site-explorer/referring-domains';\n}\n\nexport function buildSiteOverviewParams(domain: string): Record<string, string> {\n return { target: domain, mode: 'domain' };\n}\n\nexport function buildOrganicKeywordsParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n\nexport function buildBacklinksParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n\nexport function buildKeywordDifficultyParams(\n keywords: string[],\n): Record<string, string> {\n return {\n keywords: keywords.join(','),\n };\n}\n\nexport function buildReferringDomainsParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Ahrefs Client\n// ============================================================================\n\nimport type {\n AhrefsClient,\n AhrefsSiteOverview,\n AhrefsOrganicKeyword,\n AhrefsBacklink,\n AhrefsKeywordDifficulty,\n AhrefsReferringDomain,\n PaginatedResponse,\n AhrefsPaginationOptions,\n HttpClientConfig,\n} from '../types.js';\nimport { createHttpClient } from '../http.js';\nimport {\n AHREFS_BASE_URL,\n siteOverviewPath,\n organicKeywordsPath,\n backlinksPath,\n keywordDifficultyPath,\n referringDomainsPath,\n buildSiteOverviewParams,\n buildOrganicKeywordsParams,\n buildBacklinksParams,\n buildKeywordDifficultyParams,\n buildReferringDomainsParams,\n} from './endpoints.js';\nimport type {\n AhrefsRawSiteOverview,\n AhrefsApiResponse,\n AhrefsRawOrganicKeyword,\n AhrefsRawBacklink,\n AhrefsRawKeywordDifficulty,\n AhrefsRawReferringDomain,\n} from './types.js';\n\nconst DEFAULT_LIMIT = 100;\n\nexport function createAhrefsClient(\n apiToken: string,\n config?: Partial<Omit<HttpClientConfig, 'baseUrl' | 'auth'>>,\n): AhrefsClient {\n const http = createHttpClient({\n baseUrl: AHREFS_BASE_URL,\n auth: { type: 'bearer', token: apiToken },\n ...config,\n });\n\n return {\n async getSiteOverview(domain) {\n const params = buildSiteOverviewParams(domain);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawSiteOverview>>(\n siteOverviewPath(),\n params,\n );\n const entry = raw.data[0];\n return {\n domain,\n domainRating: entry?.domain_rating ?? 0,\n urlRating: entry?.url_rating ?? 0,\n backlinks: entry?.backlinks ?? 0,\n referringDomains: entry?.referring_domains ?? 0,\n organicKeywords: entry?.organic_keywords ?? 0,\n organicTraffic: entry?.organic_traffic ?? 0,\n trafficValue: entry?.traffic_value ?? 0,\n } satisfies AhrefsSiteOverview;\n },\n\n async getOrganicKeywords(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildOrganicKeywordsParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawOrganicKeyword>>(\n organicKeywordsPath(),\n params,\n );\n const data: AhrefsOrganicKeyword[] = (raw.data ?? []).map((r) => ({\n keyword: r.keyword,\n position: r.position,\n searchVolume: r.volume,\n cpc: r.cpc,\n url: r.url,\n traffic: r.traffic,\n trafficPercent: r.traffic_percent,\n difficulty: r.difficulty,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsOrganicKeyword>;\n },\n\n async getBacklinks(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildBacklinksParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawBacklink>>(\n backlinksPath(),\n params,\n );\n const data: AhrefsBacklink[] = (raw.data ?? []).map((r) => ({\n sourceUrl: r.url_from,\n targetUrl: r.url_to,\n anchorText: r.anchor,\n domainRating: r.domain_rating,\n urlRating: r.url_rating,\n isDoFollow: r.is_dofollow,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsBacklink>;\n },\n\n async getKeywordDifficulty(keywords) {\n const params = buildKeywordDifficultyParams(keywords);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawKeywordDifficulty>>(\n keywordDifficultyPath(),\n params,\n );\n return (raw.data ?? []).map((r): AhrefsKeywordDifficulty => ({\n keyword: r.keyword,\n difficulty: r.difficulty,\n searchVolume: r.volume,\n cpc: r.cpc,\n clicks: r.clicks,\n globalVolume: r.global_volume,\n }));\n },\n\n async getReferringDomains(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildReferringDomainsParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawReferringDomain>>(\n referringDomainsPath(),\n params,\n );\n const data: AhrefsReferringDomain[] = (raw.data ?? []).map((r) => ({\n domain: r.domain,\n domainRating: r.domain_rating,\n backlinks: r.backlinks,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n isDoFollow: r.is_dofollow,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsReferringDomain>;\n },\n };\n}\n"]} | ||
| {"version":3,"sources":["../src/types.ts","../src/http.ts","../src/semrush/endpoints.ts","../src/semrush/client.ts","../src/ahrefs/endpoints.ts","../src/ahrefs/client.ts"],"names":["organicKeywordsPath","backlinksPath","keywordDifficultyPath","buildOrganicKeywordsParams","buildBacklinksParams","buildKeywordDifficultyParams","DEFAULT_LIMIT"],"mappings":"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","file":"index.js","sourcesContent":["// ============================================================================\n// @power-seo/integrations — Types\n// ============================================================================\n\n// --- HTTP Client Types ---\n\nexport type AuthStrategy =\n | { type: 'query'; paramName: string; value: string }\n | { type: 'bearer'; token: string };\n\nexport interface HttpClientConfig {\n baseUrl: string;\n auth: AuthStrategy;\n rateLimitPerMinute?: number;\n maxRetries?: number;\n timeoutMs?: number;\n}\n\nexport interface HttpClient {\n get: <T>(path: string, params?: Record<string, string>) => Promise<T>;\n post: <T>(path: string, body?: unknown) => Promise<T>;\n}\n\n// --- Error ---\n\nexport class IntegrationApiError extends Error {\n readonly status: number;\n readonly provider: string;\n readonly retryable: boolean;\n\n constructor(message: string, status: number, provider: string) {\n super(message);\n this.name = 'IntegrationApiError';\n this.status = status;\n this.provider = provider;\n this.retryable = status === 429 || status >= 500;\n }\n}\n\n// --- Pagination ---\n\nexport interface PaginatedResponse<T> {\n data: T[];\n total: number;\n offset: number;\n limit: number;\n hasMore: boolean;\n}\n\n// --- Semrush Types ---\n\nexport interface SemrushDomainOverview {\n domain: string;\n organicKeywords: number;\n organicTraffic: number;\n organicCost: number;\n paidKeywords: number;\n paidTraffic: number;\n paidCost: number;\n backlinks: number;\n authorityScore: number;\n}\n\nexport interface SemrushKeywordData {\n keyword: string;\n position: number;\n previousPosition: number;\n searchVolume: number;\n cpc: number;\n url: string;\n traffic: number;\n trafficPercent: number;\n trafficCost: number;\n competition: number;\n}\n\nexport interface SemrushBacklinkData {\n sourceUrl: string;\n targetUrl: string;\n anchorText: string;\n isNoFollow: boolean;\n firstSeen: string;\n lastSeen: string;\n sourceAuthorityScore: number;\n}\n\nexport interface SemrushKeywordDifficulty {\n keyword: string;\n difficulty: number;\n searchVolume: number;\n cpc: number;\n competition: number;\n results: number;\n}\n\nexport interface SemrushRelatedKeyword {\n keyword: string;\n searchVolume: number;\n cpc: number;\n competition: number;\n results: number;\n relatedTo: string;\n}\n\nexport interface SemrushClient {\n getDomainOverview: (domain: string, database?: string) => Promise<SemrushDomainOverview>;\n getOrganicKeywords: (\n domain: string,\n options?: SemrushPaginationOptions,\n ) => Promise<PaginatedResponse<SemrushKeywordData>>;\n getBacklinks: (\n domain: string,\n options?: SemrushPaginationOptions,\n ) => Promise<PaginatedResponse<SemrushBacklinkData>>;\n getKeywordDifficulty: (\n keywords: string[],\n database?: string,\n ) => Promise<SemrushKeywordDifficulty[]>;\n getRelatedKeywords: (keyword: string, database?: string) => Promise<SemrushRelatedKeyword[]>;\n}\n\nexport interface SemrushPaginationOptions {\n limit?: number;\n offset?: number;\n database?: string;\n}\n\n// --- Ahrefs Types ---\n\nexport interface AhrefsSiteOverview {\n domain: string;\n domainRating: number;\n urlRating: number;\n backlinks: number;\n referringDomains: number;\n organicKeywords: number;\n organicTraffic: number;\n trafficValue: number;\n}\n\nexport interface AhrefsOrganicKeyword {\n keyword: string;\n position: number;\n searchVolume: number;\n cpc: number;\n url: string;\n traffic: number;\n trafficPercent: number;\n difficulty: number;\n}\n\nexport interface AhrefsBacklink {\n sourceUrl: string;\n targetUrl: string;\n anchorText: string;\n domainRating: number;\n urlRating: number;\n isDoFollow: boolean;\n firstSeen: string;\n lastSeen: string;\n}\n\nexport interface AhrefsKeywordDifficulty {\n keyword: string;\n difficulty: number;\n searchVolume: number;\n cpc: number;\n clicks: number;\n globalVolume: number;\n}\n\nexport interface AhrefsReferringDomain {\n domain: string;\n domainRating: number;\n backlinks: number;\n firstSeen: string;\n lastSeen: string;\n isDoFollow: boolean;\n}\n\nexport interface AhrefsClient {\n getSiteOverview: (domain: string) => Promise<AhrefsSiteOverview>;\n getOrganicKeywords: (\n domain: string,\n options?: AhrefsPaginationOptions,\n ) => Promise<PaginatedResponse<AhrefsOrganicKeyword>>;\n getBacklinks: (\n domain: string,\n options?: AhrefsPaginationOptions,\n ) => Promise<PaginatedResponse<AhrefsBacklink>>;\n getKeywordDifficulty: (keywords: string[]) => Promise<AhrefsKeywordDifficulty[]>;\n getReferringDomains: (\n domain: string,\n options?: AhrefsPaginationOptions,\n ) => Promise<PaginatedResponse<AhrefsReferringDomain>>;\n}\n\nexport interface AhrefsPaginationOptions {\n limit?: number;\n offset?: number;\n}\n","// ============================================================================\n// @power-seo/integrations — Shared HTTP Client\n// ============================================================================\n\nimport type { HttpClientConfig, HttpClient, AuthStrategy } from './types.js';\nimport { IntegrationApiError } from './types.js';\nimport { createTokenBucket, consumeToken, getWaitTime, sleep } from '@power-seo/core';\n\nconst DEFAULT_RATE_LIMIT = 600;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nfunction buildUrl(\n baseUrl: string,\n path: string,\n params: Record<string, string>,\n auth: AuthStrategy,\n): string {\n const url = new globalThis.URL(`${baseUrl}${path}`);\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value);\n }\n if (auth.type === 'query') {\n url.searchParams.set(auth.paramName, auth.value);\n }\n return url.toString();\n}\n\nfunction buildHeaders(auth: AuthStrategy): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n if (auth.type === 'bearer') {\n headers['Authorization'] = `Bearer ${auth.token}`;\n }\n return headers;\n}\n\nfunction getProviderFromUrl(baseUrl: string): string {\n if (baseUrl.includes('semrush')) return 'semrush';\n if (baseUrl.includes('ahrefs')) return 'ahrefs';\n return 'unknown';\n}\n\nexport function createHttpClient(config: HttpClientConfig): HttpClient {\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const bucket = createTokenBucket(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT);\n const provider = getProviderFromUrl(config.baseUrl);\n\n async function makeRequest<T>(url: string, init: globalThis.RequestInit): Promise<T> {\n const waitTime = getWaitTime(bucket);\n if (waitTime > 0) {\n await sleep(waitTime);\n }\n consumeToken(bucket);\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const controller = new globalThis.AbortController();\n const timeout = globalThis.setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await globalThis.fetch(url, {\n ...init,\n signal: controller.signal,\n });\n\n globalThis.clearTimeout(timeout);\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n const text = await response.text();\n const error = new IntegrationApiError(\n `${provider} API error: ${response.status} ${text}`,\n response.status,\n provider,\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 globalThis.clearTimeout(timeout);\n if (err instanceof IntegrationApiError) {\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 IntegrationApiError('Request failed', 500, provider);\n }\n\n return {\n async get<T>(path: string, params?: Record<string, string>): Promise<T> {\n const url = buildUrl(config.baseUrl, path, params ?? {}, config.auth);\n const headers = buildHeaders(config.auth);\n return makeRequest<T>(url, { method: 'GET', headers });\n },\n\n async post<T>(path: string, body?: unknown): Promise<T> {\n const url = buildUrl(config.baseUrl, path, {}, config.auth);\n const headers = buildHeaders(config.auth);\n return makeRequest<T>(url, {\n method: 'POST',\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n },\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Semrush Endpoints\n// ============================================================================\n\nexport const SEMRUSH_BASE_URL = 'https://api.semrush.com';\n\nexport function domainOverviewPath(): string {\n return '/analytics/v1/';\n}\n\nexport function organicKeywordsPath(): string {\n return '/analytics/v1/';\n}\n\nexport function backlinksPath(): string {\n return '/analytics/v1/';\n}\n\nexport function keywordDifficultyPath(): string {\n return '/analytics/v1/';\n}\n\nexport function relatedKeywordsPath(): string {\n return '/analytics/v1/';\n}\n\nexport function buildDomainOverviewParams(\n domain: string,\n database: string,\n): Record<string, string> {\n return {\n type: 'domain_ranks',\n domain,\n database,\n export_columns: 'Or,Ot,Oc,Ad,At,Ac,Bk,As',\n };\n}\n\nexport function buildOrganicKeywordsParams(\n domain: string,\n database: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n type: 'domain_organic',\n domain,\n database,\n display_limit: String(limit),\n display_offset: String(offset),\n export_columns: 'Ph,Po,Pp,Nq,Cp,Ur,Tr,Tc,Co,Td',\n };\n}\n\nexport function buildBacklinksParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n type: 'backlinks',\n target: domain,\n target_type: 'root_domain',\n display_limit: String(limit),\n display_offset: String(offset),\n export_columns: 'source_url,target_url,anchor,nofollow,first_seen,last_seen,source_ascore',\n };\n}\n\nexport function buildKeywordDifficultyParams(\n keywords: string[],\n database: string,\n): Record<string, string> {\n return {\n type: 'phrase_all',\n phrase: keywords.join(';'),\n database,\n export_columns: 'Ph,Kd,Nq,Cp,Co,Nr',\n };\n}\n\nexport function buildRelatedKeywordsParams(\n keyword: string,\n database: string,\n): Record<string, string> {\n return {\n type: 'phrase_related',\n phrase: keyword,\n database,\n export_columns: 'Ph,Nq,Cp,Co,Nr,Rr',\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Semrush Client\n// ============================================================================\n\nimport type {\n SemrushClient,\n SemrushDomainOverview,\n SemrushKeywordData,\n SemrushBacklinkData,\n SemrushKeywordDifficulty,\n SemrushRelatedKeyword,\n PaginatedResponse,\n SemrushPaginationOptions,\n HttpClientConfig,\n} from '../types.js';\nimport { createHttpClient } from '../http.js';\nimport {\n SEMRUSH_BASE_URL,\n domainOverviewPath,\n organicKeywordsPath,\n backlinksPath,\n keywordDifficultyPath,\n relatedKeywordsPath,\n buildDomainOverviewParams,\n buildOrganicKeywordsParams,\n buildBacklinksParams,\n buildKeywordDifficultyParams,\n buildRelatedKeywordsParams,\n} from './endpoints.js';\nimport type {\n SemrushRawDomainResponse,\n SemrushApiResponse,\n SemrushRawKeywordResponse,\n SemrushRawBacklinkResponse,\n SemrushRawKeywordDifficultyResponse,\n SemrushRawRelatedKeywordResponse,\n} from './types.js';\n\nconst DEFAULT_LIMIT = 100;\nconst DEFAULT_DATABASE = 'us';\n\nexport function createSemrushClient(\n apiKey: string,\n config?: Partial<Omit<HttpClientConfig, 'baseUrl' | 'auth'>>,\n): SemrushClient {\n const http = createHttpClient({\n baseUrl: SEMRUSH_BASE_URL,\n auth: { type: 'query', paramName: 'key', value: apiKey },\n ...config,\n });\n\n return {\n async getDomainOverview(domain, database = DEFAULT_DATABASE) {\n const params = buildDomainOverviewParams(domain, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawDomainResponse>>(\n domainOverviewPath(),\n params,\n );\n const entry = raw.data[0];\n return {\n domain,\n organicKeywords: entry?.Or ?? 0,\n organicTraffic: entry?.Ot ?? 0,\n organicCost: entry?.Oc ?? 0,\n paidKeywords: entry?.Ad ?? 0,\n paidTraffic: entry?.At ?? 0,\n paidCost: entry?.Ac ?? 0,\n backlinks: entry?.Bk ?? 0,\n authorityScore: entry?.As ?? 0,\n } satisfies SemrushDomainOverview;\n },\n\n async getOrganicKeywords(domain, options?: SemrushPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const database = options?.database ?? DEFAULT_DATABASE;\n const params = buildOrganicKeywordsParams(domain, database, limit, offset);\n const raw = await http.get<SemrushApiResponse<SemrushRawKeywordResponse>>(\n organicKeywordsPath(),\n params,\n );\n const data: SemrushKeywordData[] = (raw.data ?? []).map((r) => ({\n keyword: r.Ph,\n position: r.Po,\n previousPosition: r.Pp,\n searchVolume: r.Nq,\n cpc: r.Cp,\n url: r.Ur,\n traffic: r.Tr,\n trafficPercent: r.Td,\n trafficCost: r.Tc,\n competition: r.Co,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<SemrushKeywordData>;\n },\n\n async getBacklinks(domain, options?: SemrushPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildBacklinksParams(domain, limit, offset);\n const raw = await http.get<SemrushApiResponse<SemrushRawBacklinkResponse>>(\n backlinksPath(),\n params,\n );\n const data: SemrushBacklinkData[] = (raw.data ?? []).map((r) => ({\n sourceUrl: r.source_url,\n targetUrl: r.target_url,\n anchorText: r.anchor,\n isNoFollow: r.nofollow,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n sourceAuthorityScore: r.source_ascore,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<SemrushBacklinkData>;\n },\n\n async getKeywordDifficulty(keywords, database = DEFAULT_DATABASE) {\n const params = buildKeywordDifficultyParams(keywords, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawKeywordDifficultyResponse>>(\n keywordDifficultyPath(),\n params,\n );\n return (raw.data ?? []).map(\n (r): SemrushKeywordDifficulty => ({\n keyword: r.Ph,\n difficulty: r.Kd,\n searchVolume: r.Nq,\n cpc: r.Cp,\n competition: r.Co,\n results: r.Nr,\n }),\n );\n },\n\n async getRelatedKeywords(keyword, database = DEFAULT_DATABASE) {\n const params = buildRelatedKeywordsParams(keyword, database);\n const raw = await http.get<SemrushApiResponse<SemrushRawRelatedKeywordResponse>>(\n relatedKeywordsPath(),\n params,\n );\n return (raw.data ?? []).map(\n (r): SemrushRelatedKeyword => ({\n keyword: r.Ph,\n searchVolume: r.Nq,\n cpc: r.Cp,\n competition: r.Co,\n results: r.Nr,\n relatedTo: r.Rr,\n }),\n );\n },\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Ahrefs Endpoints\n// ============================================================================\n\nexport const AHREFS_BASE_URL = 'https://api.ahrefs.com/v3';\n\nexport function siteOverviewPath(): string {\n return '/site-explorer/overview';\n}\n\nexport function organicKeywordsPath(): string {\n return '/site-explorer/organic-keywords';\n}\n\nexport function backlinksPath(): string {\n return '/site-explorer/backlinks';\n}\n\nexport function keywordDifficultyPath(): string {\n return '/keywords-explorer/keyword-difficulty';\n}\n\nexport function referringDomainsPath(): string {\n return '/site-explorer/referring-domains';\n}\n\nexport function buildSiteOverviewParams(domain: string): Record<string, string> {\n return { target: domain, mode: 'domain' };\n}\n\nexport function buildOrganicKeywordsParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n\nexport function buildBacklinksParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n\nexport function buildKeywordDifficultyParams(keywords: string[]): Record<string, string> {\n return {\n keywords: keywords.join(','),\n };\n}\n\nexport function buildReferringDomainsParams(\n domain: string,\n limit: number,\n offset: number,\n): Record<string, string> {\n return {\n target: domain,\n mode: 'domain',\n limit: String(limit),\n offset: String(offset),\n };\n}\n","// ============================================================================\n// @power-seo/integrations — Ahrefs Client\n// ============================================================================\n\nimport type {\n AhrefsClient,\n AhrefsSiteOverview,\n AhrefsOrganicKeyword,\n AhrefsBacklink,\n AhrefsKeywordDifficulty,\n AhrefsReferringDomain,\n PaginatedResponse,\n AhrefsPaginationOptions,\n HttpClientConfig,\n} from '../types.js';\nimport { createHttpClient } from '../http.js';\nimport {\n AHREFS_BASE_URL,\n siteOverviewPath,\n organicKeywordsPath,\n backlinksPath,\n keywordDifficultyPath,\n referringDomainsPath,\n buildSiteOverviewParams,\n buildOrganicKeywordsParams,\n buildBacklinksParams,\n buildKeywordDifficultyParams,\n buildReferringDomainsParams,\n} from './endpoints.js';\nimport type {\n AhrefsRawSiteOverview,\n AhrefsApiResponse,\n AhrefsRawOrganicKeyword,\n AhrefsRawBacklink,\n AhrefsRawKeywordDifficulty,\n AhrefsRawReferringDomain,\n} from './types.js';\n\nconst DEFAULT_LIMIT = 100;\n\nexport function createAhrefsClient(\n apiToken: string,\n config?: Partial<Omit<HttpClientConfig, 'baseUrl' | 'auth'>>,\n): AhrefsClient {\n const http = createHttpClient({\n baseUrl: AHREFS_BASE_URL,\n auth: { type: 'bearer', token: apiToken },\n ...config,\n });\n\n return {\n async getSiteOverview(domain) {\n const params = buildSiteOverviewParams(domain);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawSiteOverview>>(\n siteOverviewPath(),\n params,\n );\n const entry = raw.data[0];\n return {\n domain,\n domainRating: entry?.domain_rating ?? 0,\n urlRating: entry?.url_rating ?? 0,\n backlinks: entry?.backlinks ?? 0,\n referringDomains: entry?.referring_domains ?? 0,\n organicKeywords: entry?.organic_keywords ?? 0,\n organicTraffic: entry?.organic_traffic ?? 0,\n trafficValue: entry?.traffic_value ?? 0,\n } satisfies AhrefsSiteOverview;\n },\n\n async getOrganicKeywords(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildOrganicKeywordsParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawOrganicKeyword>>(\n organicKeywordsPath(),\n params,\n );\n const data: AhrefsOrganicKeyword[] = (raw.data ?? []).map((r) => ({\n keyword: r.keyword,\n position: r.position,\n searchVolume: r.volume,\n cpc: r.cpc,\n url: r.url,\n traffic: r.traffic,\n trafficPercent: r.traffic_percent,\n difficulty: r.difficulty,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsOrganicKeyword>;\n },\n\n async getBacklinks(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildBacklinksParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawBacklink>>(backlinksPath(), params);\n const data: AhrefsBacklink[] = (raw.data ?? []).map((r) => ({\n sourceUrl: r.url_from,\n targetUrl: r.url_to,\n anchorText: r.anchor,\n domainRating: r.domain_rating,\n urlRating: r.url_rating,\n isDoFollow: r.is_dofollow,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsBacklink>;\n },\n\n async getKeywordDifficulty(keywords) {\n const params = buildKeywordDifficultyParams(keywords);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawKeywordDifficulty>>(\n keywordDifficultyPath(),\n params,\n );\n return (raw.data ?? []).map(\n (r): AhrefsKeywordDifficulty => ({\n keyword: r.keyword,\n difficulty: r.difficulty,\n searchVolume: r.volume,\n cpc: r.cpc,\n clicks: r.clicks,\n globalVolume: r.global_volume,\n }),\n );\n },\n\n async getReferringDomains(domain, options?: AhrefsPaginationOptions) {\n const limit = options?.limit ?? DEFAULT_LIMIT;\n const offset = options?.offset ?? 0;\n const params = buildReferringDomainsParams(domain, limit, offset);\n const raw = await http.get<AhrefsApiResponse<AhrefsRawReferringDomain>>(\n referringDomainsPath(),\n params,\n );\n const data: AhrefsReferringDomain[] = (raw.data ?? []).map((r) => ({\n domain: r.domain,\n domainRating: r.domain_rating,\n backlinks: r.backlinks,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n isDoFollow: r.is_dofollow,\n }));\n return {\n data,\n total: raw.total ?? 0,\n offset,\n limit,\n hasMore: data.length === limit,\n } satisfies PaginatedResponse<AhrefsReferringDomain>;\n },\n };\n}\n"]} |
+1
-1
| { | ||
| "name": "@power-seo/integrations", | ||
| "version": "1.0.1", | ||
| "version": "1.0.2", | ||
| "description": "Third-party SEO tool API clients for Semrush and Ahrefs with shared HTTP client", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
129018
0.37%1080
0.56%