🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@power-seo/integrations

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@power-seo/integrations - npm Package Compare versions

Comparing version
1.0.4
to
1.0.7
+21
LICENSE
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":"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","names":["organicKeywordsPath","backlinksPath","keywordDifficultyPath","buildOrganicKeywordsParams","buildBacklinksParams","buildKeywordDifficultyParams","DEFAULT_LIMIT","buildOrganicKeywordsParams","organicKeywordsPath","buildBacklinksParams","backlinksPath","buildKeywordDifficultyParams","keywordDifficultyPath"]}

@@ -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"]}
{
"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"
}
}
}