@power-seo/integrations
Advanced tools
+21
| MIT License | ||
| Copyright (c) 2026 CCBD SEO Contributors | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
+43
-14
@@ -1,4 +0,29 @@ | ||
| 'use strict'; | ||
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var core = require('@power-seo/core'); | ||
| // src/index.ts | ||
| var index_exports = {}; | ||
| __export(index_exports, { | ||
| IntegrationApiError: () => IntegrationApiError, | ||
| createAhrefsClient: () => createAhrefsClient, | ||
| createHttpClient: () => createHttpClient, | ||
| createSemrushClient: () => createSemrushClient | ||
| }); | ||
| module.exports = __toCommonJS(index_exports); | ||
@@ -18,2 +43,5 @@ // src/types.ts | ||
| }; | ||
| // src/http.ts | ||
| var import_core = require("@power-seo/core"); | ||
| var DEFAULT_RATE_LIMIT = 600; | ||
@@ -50,10 +78,10 @@ var DEFAULT_MAX_RETRIES = 3; | ||
| const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS; | ||
| const bucket = core.createTokenBucket(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT); | ||
| const bucket = (0, import_core.createTokenBucket)(config.rateLimitPerMinute ?? DEFAULT_RATE_LIMIT); | ||
| const provider = getProviderFromUrl(config.baseUrl); | ||
| async function makeRequest(url, init) { | ||
| const waitTime = core.getWaitTime(bucket); | ||
| const waitTime = (0, import_core.getWaitTime)(bucket); | ||
| if (waitTime > 0) { | ||
| await core.sleep(waitTime); | ||
| await (0, import_core.sleep)(waitTime); | ||
| } | ||
| core.consumeToken(bucket); | ||
| (0, import_core.consumeToken)(bucket); | ||
| let lastError = null; | ||
@@ -83,3 +111,3 @@ for (let attempt = 0; attempt <= maxRetries; attempt++) { | ||
| const backoff = Math.min(1e3 * Math.pow(2, attempt), 3e4); | ||
| await core.sleep(backoff); | ||
| await (0, import_core.sleep)(backoff); | ||
| } catch (err) { | ||
@@ -93,3 +121,3 @@ globalThis.clearTimeout(timeout); | ||
| const backoff = Math.min(1e3 * Math.pow(2, attempt), 3e4); | ||
| await core.sleep(backoff); | ||
| await (0, import_core.sleep)(backoff); | ||
| } else { | ||
@@ -471,8 +499,9 @@ throw err; | ||
| } | ||
| exports.IntegrationApiError = IntegrationApiError; | ||
| exports.createAhrefsClient = createAhrefsClient; | ||
| exports.createHttpClient = createHttpClient; | ||
| exports.createSemrushClient = createSemrushClient; | ||
| //# sourceMappingURL=index.cjs.map | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| IntegrationApiError, | ||
| createAhrefsClient, | ||
| createHttpClient, | ||
| createSemrushClient | ||
| }); | ||
| //# sourceMappingURL=index.cjs.map |
@@ -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: (\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"]} | ||
| {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/http.ts","../src/semrush/endpoints.ts","../src/semrush/client.ts","../src/ahrefs/endpoints.ts","../src/ahrefs/client.ts"],"sourcesContent":["// @power-seo/integrations — Main Entry Point\n// ----------------------------------------------------------------------------\n\n// Types\nexport type {\n AuthStrategy,\n HttpClientConfig,\n HttpClient,\n PaginatedResponse,\n SemrushDomainOverview,\n SemrushKeywordData,\n SemrushBacklinkData,\n SemrushKeywordDifficulty,\n SemrushRelatedKeyword,\n SemrushClient,\n SemrushPaginationOptions,\n AhrefsSiteOverview,\n AhrefsOrganicKeyword,\n AhrefsBacklink,\n AhrefsKeywordDifficulty,\n AhrefsReferringDomain,\n AhrefsClient,\n AhrefsPaginationOptions,\n} from './types.js';\n\n// Error class\nexport { IntegrationApiError } from './types.js';\n\n// HTTP Client\nexport { createHttpClient } from './http.js';\n\n// Semrush\nexport { createSemrushClient } from './semrush/client.js';\n\n// Ahrefs\nexport { createAhrefsClient } from './ahrefs/client.js';\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","// @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","// @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","// @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","// @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","// @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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACwBO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,QAAgB,UAAkB;AAC7D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,YAAY,WAAW,OAAO,UAAU;AAAA,EAC/C;AACF;;;AC/BA,kBAAoE;AAEpE,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB;AAE3B,SAAS,SACP,SACA,MACA,QACA,MACQ;AACR,QAAM,MAAM,IAAI,WAAW,IAAI,GAAG,OAAO,GAAG,IAAI,EAAE;AAClD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,aAAa,IAAI,KAAK,KAAK;AAAA,EACjC;AACA,MAAI,KAAK,SAAS,SAAS;AACzB,QAAI,aAAa,IAAI,KAAK,WAAW,KAAK,KAAK;AAAA,EACjD;AACA,SAAO,IAAI,SAAS;AACtB;AAEA,SAAS,aAAa,MAA4C;AAChE,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,QAAQ;AAAA,EACV;AACA,MAAI,KAAK,SAAS,UAAU;AAC1B,YAAQ,eAAe,IAAI,UAAU,KAAK,KAAK;AAAA,EACjD;AACA,SAAO;AACT;AAEA,SAAS,mBAAmB,SAAyB;AACnD,MAAI,QAAQ,SAAS,SAAS,EAAG,QAAO;AACxC,MAAI,QAAQ,SAAS,QAAQ,EAAG,QAAO;AACvC,SAAO;AACT;AAEO,SAAS,iBAAiB,QAAsC;AACrE,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,aAAS,+BAAkB,OAAO,sBAAsB,kBAAkB;AAChF,QAAM,WAAW,mBAAmB,OAAO,OAAO;AAElD,iBAAe,YAAe,KAAa,MAA0C;AACnF,UAAM,eAAW,yBAAY,MAAM;AACnC,QAAI,WAAW,GAAG;AAChB,gBAAM,mBAAM,QAAQ;AAAA,IACtB;AACA,kCAAa,MAAM;AAEnB,QAAI,YAA0B;AAE9B,aAAS,UAAU,GAAG,WAAW,YAAY,WAAW;AACtD,YAAM,aAAa,IAAI,WAAW,gBAAgB;AAClD,YAAM,UAAU,WAAW,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAEzE,UAAI;AACF,cAAM,WAAW,MAAM,WAAW,MAAM,KAAK;AAAA,UAC3C,GAAG;AAAA,UACH,QAAQ,WAAW;AAAA,QACrB,CAAC;AAED,mBAAW,aAAa,OAAO;AAE/B,YAAI,SAAS,IAAI;AACf,iBAAQ,MAAM,SAAS,KAAK;AAAA,QAC9B;AAEA,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,cAAM,QAAQ,IAAI;AAAA,UAChB,GAAG,QAAQ,eAAe,SAAS,MAAM,IAAI,IAAI;AAAA,UACjD,SAAS;AAAA,UACT;AAAA,QACF;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,mBAAW,aAAa,OAAO;AAC/B,YAAI,eAAe,qBAAqB;AACtC,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,oBAAoB,kBAAkB,KAAK,QAAQ;AAAA,EAC5E;AAEA,SAAO;AAAA,IACL,MAAM,IAAO,MAAc,QAA6C;AACtE,YAAM,MAAM,SAAS,OAAO,SAAS,MAAM,UAAU,CAAC,GAAG,OAAO,IAAI;AACpE,YAAM,UAAU,aAAa,OAAO,IAAI;AACxC,aAAO,YAAe,KAAK,EAAE,QAAQ,OAAO,QAAQ,CAAC;AAAA,IACvD;AAAA,IAEA,MAAM,KAAQ,MAAc,MAA4B;AACtD,YAAM,MAAM,SAAS,OAAO,SAAS,MAAM,CAAC,GAAG,OAAO,IAAI;AAC1D,YAAM,UAAU,aAAa,OAAO,IAAI;AACxC,aAAO,YAAe,KAAK;AAAA,QACzB,QAAQ;AAAA,QACR;AAAA,QACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,MACtC,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ACzHO,IAAM,mBAAmB;AAEzB,SAAS,qBAA6B;AAC3C,SAAO;AACT;AAEO,SAAS,sBAA8B;AAC5C,SAAO;AACT;AAEO,SAAS,gBAAwB;AACtC,SAAO;AACT;AAEO,SAAS,wBAAgC;AAC9C,SAAO;AACT;AAEO,SAAS,sBAA8B;AAC5C,SAAO;AACT;AAEO,SAAS,0BACd,QACA,UACwB;AACxB,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,EAClB;AACF;AAEO,SAAS,2BACd,QACA,UACA,OACA,QACwB;AACxB,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,eAAe,OAAO,KAAK;AAAA,IAC3B,gBAAgB,OAAO,MAAM;AAAA,IAC7B,gBAAgB;AAAA,EAClB;AACF;AAEO,SAAS,qBACd,QACA,OACA,QACwB;AACxB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,eAAe,OAAO,KAAK;AAAA,IAC3B,gBAAgB,OAAO,MAAM;AAAA,IAC7B,gBAAgB;AAAA,EAClB;AACF;AAEO,SAAS,6BACd,UACA,UACwB;AACxB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,SAAS,KAAK,GAAG;AAAA,IACzB;AAAA,IACA,gBAAgB;AAAA,EAClB;AACF;AAEO,SAAS,2BACd,SACA,UACwB;AACxB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR;AAAA,IACA,gBAAgB;AAAA,EAClB;AACF;;;ACrDA,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AAElB,SAAS,oBACd,QACA,QACe;AACf,QAAM,OAAO,iBAAiB;AAAA,IAC5B,SAAS;AAAA,IACT,MAAM,EAAE,MAAM,SAAS,WAAW,OAAO,OAAO,OAAO;AAAA,IACvD,GAAG;AAAA,EACL,CAAC;AAED,SAAO;AAAA,IACL,MAAM,kBAAkB,QAAQ,WAAW,kBAAkB;AAC3D,YAAM,SAAS,0BAA0B,QAAQ,QAAQ;AACzD,YAAM,MAAM,MAAM,KAAK;AAAA,QACrB,mBAAmB;AAAA,QACnB;AAAA,MACF;AACA,YAAM,QAAQ,IAAI,KAAK,CAAC;AACxB,aAAO;AAAA,QACL;AAAA,QACA,iBAAiB,OAAO,MAAM;AAAA,QAC9B,gBAAgB,OAAO,MAAM;AAAA,QAC7B,aAAa,OAAO,MAAM;AAAA,QAC1B,cAAc,OAAO,MAAM;AAAA,QAC3B,aAAa,OAAO,MAAM;AAAA,QAC1B,UAAU,OAAO,MAAM;AAAA,QACvB,WAAW,OAAO,MAAM;AAAA,QACxB,gBAAgB,OAAO,MAAM;AAAA,MAC/B;AAAA,IACF;AAAA,IAEA,MAAM,mBAAmB,QAAQ,SAAoC;AACnE,YAAM,QAAQ,SAAS,SAAS;AAChC,YAAM,SAAS,SAAS,UAAU;AAClC,YAAM,WAAW,SAAS,YAAY;AACtC,YAAM,SAAS,2BAA2B,QAAQ,UAAU,OAAO,MAAM;AACzE,YAAM,MAAM,MAAM,KAAK;AAAA,QACrB,oBAAoB;AAAA,QACpB;AAAA,MACF;AACA,YAAM,QAA8B,IAAI,QAAQ,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,QAC9D,SAAS,EAAE;AAAA,QACX,UAAU,EAAE;AAAA,QACZ,kBAAkB,EAAE;AAAA,QACpB,cAAc,EAAE;AAAA,QAChB,KAAK,EAAE;AAAA,QACP,KAAK,EAAE;AAAA,QACP,SAAS,EAAE;AAAA,QACX,gBAAgB,EAAE;AAAA,QAClB,aAAa,EAAE;AAAA,QACf,aAAa,EAAE;AAAA,MACjB,EAAE;AACF,aAAO;AAAA,QACL;AAAA,QACA,OAAO,IAAI,SAAS;AAAA,QACpB;AAAA,QACA;AAAA,QACA,SAAS,KAAK,WAAW;AAAA,MAC3B;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,QAAQ,SAAoC;AAC7D,YAAM,QAAQ,SAAS,SAAS;AAChC,YAAM,SAAS,SAAS,UAAU;AAClC,YAAM,SAAS,qBAAqB,QAAQ,OAAO,MAAM;AACzD,YAAM,MAAM,MAAM,KAAK;AAAA,QACrB,cAAc;AAAA,QACd;AAAA,MACF;AACA,YAAM,QAA+B,IAAI,QAAQ,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,QAC/D,WAAW,EAAE;AAAA,QACb,WAAW,EAAE;AAAA,QACb,YAAY,EAAE;AAAA,QACd,YAAY,EAAE;AAAA,QACd,WAAW,EAAE;AAAA,QACb,UAAU,EAAE;AAAA,QACZ,sBAAsB,EAAE;AAAA,MAC1B,EAAE;AACF,aAAO;AAAA,QACL;AAAA,QACA,OAAO,IAAI,SAAS;AAAA,QACpB;AAAA,QACA;AAAA,QACA,SAAS,KAAK,WAAW;AAAA,MAC3B;AAAA,IACF;AAAA,IAEA,MAAM,qBAAqB,UAAU,WAAW,kBAAkB;AAChE,YAAM,SAAS,6BAA6B,UAAU,QAAQ;AAC9D,YAAM,MAAM,MAAM,KAAK;AAAA,QACrB,sBAAsB;AAAA,QACtB;AAAA,MACF;AACA,cAAQ,IAAI,QAAQ,CAAC,GAAG;AAAA,QACtB,CAAC,OAAiC;AAAA,UAChC,SAAS,EAAE;AAAA,UACX,YAAY,EAAE;AAAA,UACd,cAAc,EAAE;AAAA,UAChB,KAAK,EAAE;AAAA,UACP,aAAa,EAAE;AAAA,UACf,SAAS,EAAE;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,mBAAmB,SAAS,WAAW,kBAAkB;AAC7D,YAAM,SAAS,2BAA2B,SAAS,QAAQ;AAC3D,YAAM,MAAM,MAAM,KAAK;AAAA,QACrB,oBAAoB;AAAA,QACpB;AAAA,MACF;AACA,cAAQ,IAAI,QAAQ,CAAC,GAAG;AAAA,QACtB,CAAC,OAA8B;AAAA,UAC7B,SAAS,EAAE;AAAA,UACX,cAAc,EAAE;AAAA,UAChB,KAAK,EAAE;AAAA,UACP,aAAa,EAAE;AAAA,UACf,SAAS,EAAE;AAAA,UACX,WAAW,EAAE;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AChKO,IAAM,kBAAkB;AAExB,SAAS,mBAA2B;AACzC,SAAO;AACT;AAEO,SAASA,uBAA8B;AAC5C,SAAO;AACT;AAEO,SAASC,iBAAwB;AACtC,SAAO;AACT;AAEO,SAASC,yBAAgC;AAC9C,SAAO;AACT;AAEO,SAAS,uBAA+B;AAC7C,SAAO;AACT;AAEO,SAAS,wBAAwB,QAAwC;AAC9E,SAAO,EAAE,QAAQ,QAAQ,MAAM,SAAS;AAC1C;AAEO,SAASC,4BACd,QACA,OACA,QACwB;AACxB,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO,OAAO,KAAK;AAAA,IACnB,QAAQ,OAAO,MAAM;AAAA,EACvB;AACF;AAEO,SAASC,sBACd,QACA,OACA,QACwB;AACxB,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO,OAAO,KAAK;AAAA,IACnB,QAAQ,OAAO,MAAM;AAAA,EACvB;AACF;AAEO,SAASC,8BAA6B,UAA4C;AACvF,SAAO;AAAA,IACL,UAAU,SAAS,KAAK,GAAG;AAAA,EAC7B;AACF;AAEO,SAAS,4BACd,QACA,OACA,QACwB;AACxB,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO,OAAO,KAAK;AAAA,IACnB,QAAQ,OAAO,MAAM;AAAA,EACvB;AACF;;;ACnCA,IAAMC,iBAAgB;AAEf,SAAS,mBACd,UACA,QACc;AACd,QAAM,OAAO,iBAAiB;AAAA,IAC5B,SAAS;AAAA,IACT,MAAM,EAAE,MAAM,UAAU,OAAO,SAAS;AAAA,IACxC,GAAG;AAAA,EACL,CAAC;AAED,SAAO;AAAA,IACL,MAAM,gBAAgB,QAAQ;AAC5B,YAAM,SAAS,wBAAwB,MAAM;AAC7C,YAAM,MAAM,MAAM,KAAK;AAAA,QACrB,iBAAiB;AAAA,QACjB;AAAA,MACF;AACA,YAAM,QAAQ,IAAI,KAAK,CAAC;AACxB,aAAO;AAAA,QACL;AAAA,QACA,cAAc,OAAO,iBAAiB;AAAA,QACtC,WAAW,OAAO,cAAc;AAAA,QAChC,WAAW,OAAO,aAAa;AAAA,QAC/B,kBAAkB,OAAO,qBAAqB;AAAA,QAC9C,iBAAiB,OAAO,oBAAoB;AAAA,QAC5C,gBAAgB,OAAO,mBAAmB;AAAA,QAC1C,cAAc,OAAO,iBAAiB;AAAA,MACxC;AAAA,IACF;AAAA,IAEA,MAAM,mBAAmB,QAAQ,SAAmC;AAClE,YAAM,QAAQ,SAAS,SAASA;AAChC,YAAM,SAAS,SAAS,UAAU;AAClC,YAAM,SAASC,4BAA2B,QAAQ,OAAO,MAAM;AAC/D,YAAM,MAAM,MAAM,KAAK;AAAA,QACrBC,qBAAoB;AAAA,QACpB;AAAA,MACF;AACA,YAAM,QAAgC,IAAI,QAAQ,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,QAChE,SAAS,EAAE;AAAA,QACX,UAAU,EAAE;AAAA,QACZ,cAAc,EAAE;AAAA,QAChB,KAAK,EAAE;AAAA,QACP,KAAK,EAAE;AAAA,QACP,SAAS,EAAE;AAAA,QACX,gBAAgB,EAAE;AAAA,QAClB,YAAY,EAAE;AAAA,MAChB,EAAE;AACF,aAAO;AAAA,QACL;AAAA,QACA,OAAO,IAAI,SAAS;AAAA,QACpB;AAAA,QACA;AAAA,QACA,SAAS,KAAK,WAAW;AAAA,MAC3B;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,QAAQ,SAAmC;AAC5D,YAAM,QAAQ,SAAS,SAASF;AAChC,YAAM,SAAS,SAAS,UAAU;AAClC,YAAM,SAASG,sBAAqB,QAAQ,OAAO,MAAM;AACzD,YAAM,MAAM,MAAM,KAAK,IAA0CC,eAAc,GAAG,MAAM;AACxF,YAAM,QAA0B,IAAI,QAAQ,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,QAC1D,WAAW,EAAE;AAAA,QACb,WAAW,EAAE;AAAA,QACb,YAAY,EAAE;AAAA,QACd,cAAc,EAAE;AAAA,QAChB,WAAW,EAAE;AAAA,QACb,YAAY,EAAE;AAAA,QACd,WAAW,EAAE;AAAA,QACb,UAAU,EAAE;AAAA,MACd,EAAE;AACF,aAAO;AAAA,QACL;AAAA,QACA,OAAO,IAAI,SAAS;AAAA,QACpB;AAAA,QACA;AAAA,QACA,SAAS,KAAK,WAAW;AAAA,MAC3B;AAAA,IACF;AAAA,IAEA,MAAM,qBAAqB,UAAU;AACnC,YAAM,SAASC,8BAA6B,QAAQ;AACpD,YAAM,MAAM,MAAM,KAAK;AAAA,QACrBC,uBAAsB;AAAA,QACtB;AAAA,MACF;AACA,cAAQ,IAAI,QAAQ,CAAC,GAAG;AAAA,QACtB,CAAC,OAAgC;AAAA,UAC/B,SAAS,EAAE;AAAA,UACX,YAAY,EAAE;AAAA,UACd,cAAc,EAAE;AAAA,UAChB,KAAK,EAAE;AAAA,UACP,QAAQ,EAAE;AAAA,UACV,cAAc,EAAE;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,oBAAoB,QAAQ,SAAmC;AACnE,YAAM,QAAQ,SAAS,SAASN;AAChC,YAAM,SAAS,SAAS,UAAU;AAClC,YAAM,SAAS,4BAA4B,QAAQ,OAAO,MAAM;AAChE,YAAM,MAAM,MAAM,KAAK;AAAA,QACrB,qBAAqB;AAAA,QACrB;AAAA,MACF;AACA,YAAM,QAAiC,IAAI,QAAQ,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,QACjE,QAAQ,EAAE;AAAA,QACV,cAAc,EAAE;AAAA,QAChB,WAAW,EAAE;AAAA,QACb,WAAW,EAAE;AAAA,QACb,UAAU,EAAE;AAAA,QACZ,YAAY,EAAE;AAAA,MAChB,EAAE;AACF,aAAO;AAAA,QACL;AAAA,QACA,OAAO,IAAI,SAAS;AAAA,QACpB;AAAA,QACA;AAAA,QACA,SAAS,KAAK,WAAW;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AACF;","names":["organicKeywordsPath","backlinksPath","keywordDifficultyPath","buildOrganicKeywordsParams","buildBacklinksParams","buildKeywordDifficultyParams","DEFAULT_LIMIT","buildOrganicKeywordsParams","organicKeywordsPath","buildBacklinksParams","backlinksPath","buildKeywordDifficultyParams","keywordDifficultyPath"]} |
+9
-5
@@ -1,3 +0,1 @@ | ||
| import { createTokenBucket, getWaitTime, sleep, consumeToken } from '@power-seo/core'; | ||
| // src/types.ts | ||
@@ -16,2 +14,5 @@ var IntegrationApiError = class extends Error { | ||
| }; | ||
| // src/http.ts | ||
| import { createTokenBucket, consumeToken, getWaitTime, sleep } from "@power-seo/core"; | ||
| var DEFAULT_RATE_LIMIT = 600; | ||
@@ -466,5 +467,8 @@ var DEFAULT_MAX_RETRIES = 3; | ||
| } | ||
| export { IntegrationApiError, createAhrefsClient, createHttpClient, createSemrushClient }; | ||
| //# sourceMappingURL=index.js.map | ||
| export { | ||
| IntegrationApiError, | ||
| createAhrefsClient, | ||
| createHttpClient, | ||
| createSemrushClient | ||
| }; | ||
| //# sourceMappingURL=index.js.map |
@@ -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: (\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"]} | ||
| {"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"],"sourcesContent":["// @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","// @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","// @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","// @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","// @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","// @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"],"mappings":"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","names":["organicKeywordsPath","backlinksPath","keywordDifficultyPath","buildOrganicKeywordsParams","buildBacklinksParams","buildKeywordDifficultyParams","DEFAULT_LIMIT","buildOrganicKeywordsParams","organicKeywordsPath","buildBacklinksParams","backlinksPath","buildKeywordDifficultyParams","keywordDifficultyPath"]} |
+22
-14
| { | ||
| "name": "@power-seo/integrations", | ||
| "version": "1.0.4", | ||
| "version": "1.0.7", | ||
| "description": "Third-party SEO tool API clients for Semrush and Ahrefs with shared HTTP client", | ||
@@ -20,17 +20,7 @@ "license": "MIT", | ||
| ], | ||
| "scripts": { | ||
| "build": "tsup", | ||
| "dev": "tsup --watch", | ||
| "test": "vitest run", | ||
| "test:watch": "vitest", | ||
| "typecheck": "tsc --noEmit", | ||
| "lint": "eslint src/", | ||
| "lint:fix": "eslint src/ --fix", | ||
| "clean": "rimraf dist" | ||
| }, | ||
| "dependencies": { | ||
| "@power-seo/core": "workspace:*" | ||
| "@power-seo/core": "1.0.3" | ||
| }, | ||
| "devDependencies": { | ||
| "rimraf": "^6.0.0", | ||
| "rimraf": "^6.1.3", | ||
| "tsup": "^8.3.0", | ||
@@ -57,3 +47,21 @@ "typescript": "^5.7.0", | ||
| "access": "public" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/CyberCraftBD/power-seo/issues" | ||
| }, | ||
| "homepage": "https://github.com/CyberCraftBD/power-seo/tree/main/packages/integrations#readme", | ||
| "funding": { | ||
| "type": "github", | ||
| "url": "https://github.com/sponsors/cybercraftbd" | ||
| }, | ||
| "scripts": { | ||
| "build": "tsup", | ||
| "dev": "tsup --watch", | ||
| "test": "vitest run", | ||
| "test:watch": "vitest", | ||
| "typecheck": "tsc --noEmit", | ||
| "lint": "eslint src/", | ||
| "lint:fix": "eslint src/ --fix", | ||
| "clean": "rimraf dist" | ||
| } | ||
| } | ||
| } |
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
No website
QualityPackage does not have a website.
9
12.5%1114
3.15%0
-100%0
-100%122912
-4.81%Updated