@adobe/mysticat-shared-seo-client 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +48 -0
- package/package.json +49 -0
- package/src/client.js +85 -0
- package/src/endpoints.js +26 -0
- package/src/index.d.ts +114 -0
- package/src/index.js +22 -0
- package/src/utils.js +31 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
## @adobe/mysticat-shared-seo-client-v1.0.0 (2026-04-01)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* **seo-client:** add mysticat-shared-seo-client package ([#1490](https://github.com/adobe/spacecat-shared/issues/1490)) ([27faade](https://github.com/adobe/spacecat-shared/commit/27faade8b3179ee213dce6044c08ebb5ceff1a19))
|
package/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Mysticat Shared - SEO Client
|
|
2
|
+
|
|
3
|
+
An SEO API client for SpaceCat services.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @adobe/mysticat-shared-seo-client
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Creating an instance from Helix UniversalContext
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
const client = SeoClient.createFrom(context);
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Constructor
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
import SeoClient from '@adobe/mysticat-shared-seo-client';
|
|
23
|
+
|
|
24
|
+
const config = {
|
|
25
|
+
apiKey: '<API_KEY>',
|
|
26
|
+
apiBaseUrl: '<API_BASE_URL>',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const client = new SeoClient(config, fetch);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Testing
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm run test
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Linting
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm run lint
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Additional Information
|
|
45
|
+
|
|
46
|
+
- **Repository**: [GitHub](https://github.com/adobe/spacecat-shared.git)
|
|
47
|
+
- **Issue Tracking**: [GitHub Issues](https://github.com/adobe/spacecat-shared/issues)
|
|
48
|
+
- **License**: Apache-2.0
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@adobe/mysticat-shared-seo-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Shared modules of the SpaceCat Services - SEO Client",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=22.0.0 <25.0.0",
|
|
8
|
+
"npm": ">=10.9.0 <12.0.0"
|
|
9
|
+
},
|
|
10
|
+
"main": "src/index.js",
|
|
11
|
+
"types": "src/index.d.ts",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "c8 mocha",
|
|
14
|
+
"lint": "eslint .",
|
|
15
|
+
"clean": "rm -rf package-lock.json node_modules"
|
|
16
|
+
},
|
|
17
|
+
"mocha": {
|
|
18
|
+
"require": "test/setup-env.js",
|
|
19
|
+
"reporter": "mocha-multi-reporters",
|
|
20
|
+
"reporter-options": "configFile=.mocha-multi.json",
|
|
21
|
+
"spec": "test/**/*.test.js"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/adobe/spacecat-shared.git"
|
|
26
|
+
},
|
|
27
|
+
"author": "",
|
|
28
|
+
"license": "Apache-2.0",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/adobe/spacecat-shared/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/adobe/spacecat-shared#readme",
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@adobe/fetch": "4.2.3",
|
|
38
|
+
"@adobe/helix-universal": "5.4.0",
|
|
39
|
+
"@adobe/spacecat-shared-utils": "1.81.1"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"chai": "6.2.2",
|
|
43
|
+
"chai-as-promised": "8.0.2",
|
|
44
|
+
"nock": "14.0.11",
|
|
45
|
+
"sinon": "21.0.3",
|
|
46
|
+
"sinon-chai": "4.0.1",
|
|
47
|
+
"typescript": "5.9.3"
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/client.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { isValidUrl } from '@adobe/spacecat-shared-utils';
|
|
14
|
+
import { context as h2, h1 } from '@adobe/fetch';
|
|
15
|
+
|
|
16
|
+
/* c8 ignore next 3 */
|
|
17
|
+
export const { fetch } = process.env.HELIX_FETCH_FORCE_HTTP1
|
|
18
|
+
? h1()
|
|
19
|
+
: h2();
|
|
20
|
+
|
|
21
|
+
const STUB_RESPONSE = { result: {}, fullAuditRef: '' };
|
|
22
|
+
|
|
23
|
+
export default class SeoClient {
|
|
24
|
+
static createFrom(context) {
|
|
25
|
+
const { SEO_API_BASE_URL: apiBaseUrl, SEO_API_KEY: apiKey } = context.env;
|
|
26
|
+
return new SeoClient({ apiBaseUrl, apiKey }, fetch, context.log);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
constructor(config, fetchAPI, log = console) {
|
|
30
|
+
const { apiKey, apiBaseUrl } = config;
|
|
31
|
+
|
|
32
|
+
if (!isValidUrl(apiBaseUrl)) {
|
|
33
|
+
throw new Error(`Invalid SEO API Base URL: ${apiBaseUrl}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (typeof fetchAPI !== 'function') {
|
|
37
|
+
throw Error('"fetchAPI" must be a function');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.apiBaseUrl = apiBaseUrl;
|
|
41
|
+
this.apiKey = apiKey;
|
|
42
|
+
this.fetchAPI = fetchAPI;
|
|
43
|
+
this.log = log;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// eslint-disable-next-line no-unused-vars, class-methods-use-this
|
|
47
|
+
async sendRequest(endpoint, queryParams = {}) {
|
|
48
|
+
return STUB_RESPONSE;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// eslint-disable-next-line no-unused-vars, class-methods-use-this
|
|
52
|
+
async getBrokenBacklinks(url, limit = 50) {
|
|
53
|
+
return STUB_RESPONSE;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// eslint-disable-next-line no-unused-vars, class-methods-use-this
|
|
57
|
+
async getTopPages(url, limit = 200) {
|
|
58
|
+
return STUB_RESPONSE;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// eslint-disable-next-line no-unused-vars, class-methods-use-this
|
|
62
|
+
async getBacklinks(url, limit = 200) {
|
|
63
|
+
return STUB_RESPONSE;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// eslint-disable-next-line no-unused-vars, class-methods-use-this
|
|
67
|
+
async getOrganicKeywords(url, options = {}) {
|
|
68
|
+
return STUB_RESPONSE;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// eslint-disable-next-line no-unused-vars, class-methods-use-this
|
|
72
|
+
async getPaidPages(url, date = new Date().toISOString().split('T')[0], limit = 200, mode = 'prefix') {
|
|
73
|
+
return STUB_RESPONSE;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// eslint-disable-next-line no-unused-vars, class-methods-use-this
|
|
77
|
+
async getMetrics(url, date = new Date().toISOString().split('T')[0]) {
|
|
78
|
+
return STUB_RESPONSE;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// eslint-disable-next-line no-unused-vars, class-methods-use-this
|
|
82
|
+
async getMetricsByCountry(url, date = new Date().toISOString().split('T')[0]) {
|
|
83
|
+
return STUB_RESPONSE;
|
|
84
|
+
}
|
|
85
|
+
}
|
package/src/endpoints.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Endpoint definitions for the SEO API.
|
|
15
|
+
* Each entry maps a method name to its API path and default query parameters.
|
|
16
|
+
* Paths and params are stubs - to be populated when implementing API calls.
|
|
17
|
+
*/
|
|
18
|
+
export const ENDPOINTS = {
|
|
19
|
+
brokenBacklinks: { path: '', defaultParams: {} },
|
|
20
|
+
topPages: { path: '', defaultParams: {} },
|
|
21
|
+
backlinks: { path: '', defaultParams: {} },
|
|
22
|
+
organicKeywords: { path: '', defaultParams: {} },
|
|
23
|
+
paidPages: { path: '', defaultParams: {} },
|
|
24
|
+
metrics: { path: '', defaultParams: {} },
|
|
25
|
+
metricsByCountry: { path: '', defaultParams: {} },
|
|
26
|
+
};
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { UniversalContext } from '@adobe/helix-universal';
|
|
14
|
+
|
|
15
|
+
export interface SeoAPIOptions {
|
|
16
|
+
select: string;
|
|
17
|
+
where: string;
|
|
18
|
+
order_by: string;
|
|
19
|
+
date: string;
|
|
20
|
+
target: string;
|
|
21
|
+
limit: number;
|
|
22
|
+
mode: string;
|
|
23
|
+
output: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default class SeoClient {
|
|
27
|
+
/**
|
|
28
|
+
* Static factory method to create an instance of SeoClient.
|
|
29
|
+
* @param {UniversalContext} context - An object containing the AWS Lambda context information
|
|
30
|
+
* @returns An instance of SeoClient.
|
|
31
|
+
*/
|
|
32
|
+
static createFrom(context: UniversalContext): SeoClient;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Constructor for creating an instance of SeoClient.
|
|
36
|
+
* @param config
|
|
37
|
+
* @param fetchAPI
|
|
38
|
+
* @param log
|
|
39
|
+
*/
|
|
40
|
+
constructor(config: object, fetchAPI, log?: Console);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Asynchronous method to send a request to the SEO API.
|
|
44
|
+
* @param endpoint
|
|
45
|
+
* @param queryParams
|
|
46
|
+
*/
|
|
47
|
+
sendRequest(endpoint: string, queryParams?: SeoAPIOptions):
|
|
48
|
+
Promise<{ result: object, fullAuditRef: string }>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Asynchronous method to get broken backlinks.
|
|
52
|
+
* @param url
|
|
53
|
+
* @param limit
|
|
54
|
+
*/
|
|
55
|
+
getBrokenBacklinks(url: string, limit?: number):
|
|
56
|
+
Promise<{ result: object, fullAuditRef: string }>;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Asynchronous method to get top pages.
|
|
60
|
+
* @param url
|
|
61
|
+
* @param limit
|
|
62
|
+
*/
|
|
63
|
+
getTopPages(url: string, limit?: number):
|
|
64
|
+
Promise<{ result: object, fullAuditRef: string }>;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Asynchronous method to get backlinks.
|
|
68
|
+
* @param url
|
|
69
|
+
* @param limit
|
|
70
|
+
*/
|
|
71
|
+
getBacklinks(url: string, limit?: number):
|
|
72
|
+
Promise<{ result: object, fullAuditRef: string }>;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Asynchronous method to get organic keywords.
|
|
76
|
+
*/
|
|
77
|
+
getOrganicKeywords(
|
|
78
|
+
url: string,
|
|
79
|
+
options?: {
|
|
80
|
+
country?: string,
|
|
81
|
+
keywordFilter?: string[],
|
|
82
|
+
limit?: number,
|
|
83
|
+
mode?: 'exact' | 'prefix',
|
|
84
|
+
excludeBranded?: boolean,
|
|
85
|
+
}):
|
|
86
|
+
Promise<{ result: object, fullAuditRef: string }>;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Asynchronous method to get paid pages for a URL.
|
|
90
|
+
* @param url - The target URL
|
|
91
|
+
* @param date - Optional date in YYYY-MM-DD format, defaults to today
|
|
92
|
+
* @param limit - Maximum number of results to return (max: 1000)
|
|
93
|
+
* @param mode - Search mode
|
|
94
|
+
*/
|
|
95
|
+
getPaidPages(url: string, date?: string, limit?: number,
|
|
96
|
+
mode?: 'exact' | 'prefix' | 'domain' | 'subdomains'):
|
|
97
|
+
Promise<{ result: object, fullAuditRef: string }>;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Asynchronous method to get metrics for a URL.
|
|
101
|
+
* @param url - The target URL
|
|
102
|
+
* @param date - Optional date in YYYY-MM-DD format, defaults to today
|
|
103
|
+
*/
|
|
104
|
+
getMetrics(url: string, date?: string):
|
|
105
|
+
Promise<{ result: object, fullAuditRef: string }>;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Asynchronous method to get metrics by country for a URL.
|
|
109
|
+
* @param url - The target URL
|
|
110
|
+
* @param date - Optional date in YYYY-MM-DD format, defaults to today
|
|
111
|
+
*/
|
|
112
|
+
getMetricsByCountry(url: string, date?: string):
|
|
113
|
+
Promise<{ result: object, fullAuditRef: string }>;
|
|
114
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import SeoClient from './client.js';
|
|
14
|
+
|
|
15
|
+
export default SeoClient;
|
|
16
|
+
export { fetch } from './client.js';
|
|
17
|
+
export { ENDPOINTS } from './endpoints.js';
|
|
18
|
+
export { buildQueryParams, parseResponse } from './utils.js';
|
|
19
|
+
|
|
20
|
+
export const ORGANIC_KEYWORDS_FIELDS = /** @type {const} */ ([]);
|
|
21
|
+
|
|
22
|
+
export const METRICS_BY_COUNTRY_FILTER_FIELDS = /** @type {const} */ ([]);
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Merges default query parameters with caller-provided overrides.
|
|
15
|
+
* @param {object} defaults - Default parameter values
|
|
16
|
+
* @param {object} overrides - Caller-provided overrides
|
|
17
|
+
* @returns {object} Merged parameters
|
|
18
|
+
*/
|
|
19
|
+
export function buildQueryParams(defaults, overrides) {
|
|
20
|
+
return { ...defaults, ...overrides };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Parses/normalizes an API response.
|
|
25
|
+
* Stub - passes through unchanged. To be extended when implementing API calls.
|
|
26
|
+
* @param {*} response - Raw API response
|
|
27
|
+
* @returns {*} Parsed response
|
|
28
|
+
*/
|
|
29
|
+
export function parseResponse(response) {
|
|
30
|
+
return response;
|
|
31
|
+
}
|