@respira/wordpress-mcp-server 7.2.18 → 7.4.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/dist/acf-tools.d.ts +0 -10
- package/dist/acf-tools.d.ts.map +1 -1
- package/dist/acf-tools.js +0 -15
- package/dist/acf-tools.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +31 -36
- package/dist/config.js.map +1 -1
- package/dist/server.d.ts +0 -47
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1155 -605
- package/dist/server.js.map +1 -1
- package/dist/wordpress-client.d.ts +61 -29
- package/dist/wordpress-client.d.ts.map +1 -1
- package/dist/wordpress-client.js +271 -148
- package/dist/wordpress-client.js.map +1 -1
- package/package.json +2 -2
- package/skills/activity-report-composer/README.md +38 -0
- package/skills/activity-report-composer/SKILL.md +167 -0
- package/skills/activity-report-composer/metadata.json +42 -0
- package/skills/brand-voice-synthesizer/README.md +43 -0
- package/skills/brand-voice-synthesizer/SKILL.md +259 -0
- package/skills/brand-voice-synthesizer/metadata.json +46 -0
- package/skills/build-oxygen6-page/SKILL.md +59 -0
- package/skills/conversion-audit/README.md +37 -0
- package/skills/conversion-audit/SKILL.md +185 -0
- package/skills/conversion-audit/metadata.json +46 -0
- package/skills/custom-post-type-architect/README.md +34 -0
- package/skills/custom-post-type-architect/SKILL.md +158 -0
- package/skills/custom-post-type-architect/metadata.json +39 -0
- package/skills/design-system-synthesizer/README.md +46 -0
- package/skills/design-system-synthesizer/SKILL.md +395 -0
- package/skills/design-system-synthesizer/metadata.json +57 -0
- package/skills/figma-to-elementor/SKILL.md +204 -0
- package/skills/html-to-bricks/README.md +43 -0
- package/skills/html-to-bricks/SKILL.md +135 -0
- package/skills/html-to-bricks/metadata.json +41 -0
- package/skills/internal-link-builder/SKILL.md +258 -0
- package/skills/internal-link-builder/metadata.json +46 -0
- package/skills/migrate-beaver-builder-to-bricks/SKILL.md +251 -0
- package/skills/migrate-beaver-builder-to-gutenberg/SKILL.md +248 -0
- package/skills/migrate-brizy-to-gutenberg/SKILL.md +248 -0
- package/skills/migrate-divi-to-breakdance/SKILL.md +312 -0
- package/skills/migrate-divi-to-bricks/SKILL.md +321 -0
- package/skills/migrate-divi-to-gutenberg/SKILL.md +328 -0
- package/skills/migrate-elementor-to-breakdance/SKILL.md +287 -0
- package/skills/migrate-elementor-to-bricks/SKILL.md +289 -0
- package/skills/migrate-elementor-to-gutenberg/SKILL.md +327 -0
- package/skills/migrate-elementor-to-oxygen/SKILL.md +300 -0
- package/skills/migrate-oxygen-to-breakdance/SKILL.md +235 -0
- package/skills/migrate-oxygen-to-bricks/SKILL.md +237 -0
- package/skills/migrate-thrive-architect-to-gutenberg/SKILL.md +257 -0
- package/skills/migrate-visual-composer-to-gutenberg/SKILL.md +261 -0
- package/skills/migrate-wpbakery-to-bricks/SKILL.md +336 -0
- package/skills/migrate-wpbakery-to-gutenberg/SKILL.md +345 -0
- package/skills/mobile-experience-report/SKILL.md +719 -0
- package/skills/mobile-experience-report/telemetry.ts +137 -0
- package/skills/page-template-library/README.md +41 -0
- package/skills/page-template-library/SKILL.md +175 -0
- package/skills/page-template-library/metadata.json +44 -0
- package/skills/prime-the-agent/README.md +49 -0
- package/skills/prime-the-agent/SKILL.md +225 -0
- package/skills/prime-the-agent/metadata.json +46 -0
- package/skills/respira-setup-assistant/SKILL.md +386 -0
- package/skills/respira-setup-assistant/metadata.json +36 -0
- package/skills/seo-aeo-amplifier/README.md +61 -0
- package/skills/seo-aeo-amplifier/SKILL.md +277 -0
- package/skills/seo-aeo-amplifier/metadata.json +62 -0
- package/skills/stale-content-detector/README.md +41 -0
- package/skills/stale-content-detector/SKILL.md +156 -0
- package/skills/stale-content-detector/metadata.json +43 -0
- package/skills/technical-debt-audit/SKILL.md +691 -0
- package/skills/technical-debt-audit/telemetry.ts +142 -0
- package/skills/woocommerce-health-check/SKILL.md +719 -0
- package/skills/woocommerce-health-check/telemetry.ts +137 -0
- package/skills/wordpress-ai-image-optimizer/README.md +49 -0
- package/skills/wordpress-ai-image-optimizer/SKILL.md +232 -0
- package/skills/wordpress-ai-image-optimizer/metadata.json +63 -0
- package/skills/wordpress-site-dna/README.md +81 -0
- package/skills/wordpress-site-dna/SKILL.md +669 -0
- package/skills/wordpress-site-dna/telemetry.ts +137 -0
- package/dist/__tests__/acf-tool-routing.test.d.ts +0 -2
- package/dist/__tests__/acf-tool-routing.test.d.ts.map +0 -1
- package/dist/__tests__/acf-tool-routing.test.js +0 -37
- package/dist/__tests__/acf-tool-routing.test.js.map +0 -1
- package/dist/__tests__/cowork-bootstrap.test.d.ts +0 -2
- package/dist/__tests__/cowork-bootstrap.test.d.ts.map +0 -1
- package/dist/__tests__/cowork-bootstrap.test.js +0 -61
- package/dist/__tests__/cowork-bootstrap.test.js.map +0 -1
package/dist/wordpress-client.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import axios from 'axios';
|
|
7
7
|
import FormData from 'form-data';
|
|
8
8
|
import { readFileSync, existsSync, statSync } from 'node:fs';
|
|
9
|
-
import { dirname, resolve, extname
|
|
9
|
+
import { dirname, resolve, extname } from 'node:path';
|
|
10
10
|
import { fileURLToPath } from 'node:url';
|
|
11
11
|
import { Agent as HttpAgent } from 'node:http';
|
|
12
12
|
import { getRespiraAgentHeaders } from './agent-signature.js';
|
|
@@ -37,15 +37,6 @@ export class WordPressClient {
|
|
|
37
37
|
insecureTLS = false;
|
|
38
38
|
negotiatedApiVersion = null;
|
|
39
39
|
negotiationPromise = null;
|
|
40
|
-
/**
|
|
41
|
-
* The real error from the last failed `/wp-json/respira/v2/status` probe.
|
|
42
|
-
* Bug 8d2c3331: getApiVersion() used to swallow this entirely, so a 401
|
|
43
|
-
* (missing/invalid API key) or 403 (missing v2 scope) — both of which prove
|
|
44
|
-
* the route IS live and reachable — looked identical to a genuine 404 /
|
|
45
|
-
* network failure. ensureV2() reads this to surface the real cause instead
|
|
46
|
-
* of a misleading "not available" boilerplate.
|
|
47
|
-
*/
|
|
48
|
-
negotiationError = null;
|
|
49
40
|
// Version compatibility check — populated lazily on first API call.
|
|
50
41
|
compatibilityChecked = false;
|
|
51
42
|
compatibilityPromise = null;
|
|
@@ -555,20 +546,11 @@ export class WordPressClient {
|
|
|
555
546
|
const response = await this.rootClient.get('/wp-json/respira/v2/status');
|
|
556
547
|
if (response.status >= 200 && response.status < 300) {
|
|
557
548
|
this.negotiatedApiVersion = 'v2';
|
|
558
|
-
this.negotiationError = null;
|
|
559
549
|
return 'v2';
|
|
560
550
|
}
|
|
561
551
|
}
|
|
562
|
-
catch
|
|
563
|
-
//
|
|
564
|
-
// The response interceptor (errorInterceptor -> handleError) has
|
|
565
|
-
// already turned this into a descriptive Error by this point (e.g.
|
|
566
|
-
// "Authentication failed: No API key provided..." for a 401, or a
|
|
567
|
-
// scope-denied message for a 403) — both of which mean the v2 route
|
|
568
|
-
// IS live and reachable, which is the opposite of what
|
|
569
|
-
// ensureV2()'s old generic message implied. Fall back to v1 either
|
|
570
|
-
// way (so genuinely v1-only sites keep working) but remember why.
|
|
571
|
-
this.negotiationError = err instanceof Error ? err : new Error(String(err));
|
|
552
|
+
catch {
|
|
553
|
+
// Ignore and fall back to v1.
|
|
572
554
|
}
|
|
573
555
|
this.negotiatedApiVersion = 'v1';
|
|
574
556
|
return 'v1';
|
|
@@ -588,29 +570,7 @@ export class WordPressClient {
|
|
|
588
570
|
async ensureV2() {
|
|
589
571
|
const version = await this.getApiVersion();
|
|
590
572
|
if (version !== 'v2') {
|
|
591
|
-
const err = this.negotiationError;
|
|
592
|
-
const errName = err instanceof Error ? err.name : undefined;
|
|
593
|
-
// Bug 8d2c3331: a 401/403 from the v2 status probe means the route IS
|
|
594
|
-
// live and reachable — WordPress itself rejected the request's
|
|
595
|
-
// credentials/scope. That is a completely different failure than
|
|
596
|
-
// "route not found" (404, HTML-instead-of-JSON, DNS/network errors),
|
|
597
|
-
// so it needs a different message: none of the permalinks/WAF/plugin-
|
|
598
|
-
// version causes below apply, and repeating them just sends the next
|
|
599
|
-
// person chasing the wrong fix.
|
|
600
|
-
const looksLikeAuthOrScopeRejection = typeof errName === 'string' &&
|
|
601
|
-
(errName.startsWith('respira_') || errName === 'http_401' || errName === 'http_403');
|
|
602
|
-
if (err && looksLikeAuthOrScopeRejection) {
|
|
603
|
-
throw new Error(`respira/v2 rejected this request's credentials: ${err.message}\n\n` +
|
|
604
|
-
'The v2 route is live and reachable on this site — this is an authentication or ' +
|
|
605
|
-
'permission problem, not a permalinks/WAF/plugin-version problem. v1 tools may still ' +
|
|
606
|
-
'work because some v1 routes have looser permission checks.\n\n' +
|
|
607
|
-
`To confirm: open ${this.siteConfig.url}/wp-json/respira/v2/status in a browser with no ` +
|
|
608
|
-
'headers. A JSON 401/403 response (not a 404 or an HTML page) confirms the route works ' +
|
|
609
|
-
'and this is an auth/scope issue — check that the configured API key is correct, active, ' +
|
|
610
|
-
'and has write permission for this site.');
|
|
611
|
-
}
|
|
612
573
|
throw new Error('respira/v2 is not available on this site.\n\n' +
|
|
613
|
-
(err ? `Underlying error from the v2 status probe: ${err.message}\n\n` : '') +
|
|
614
574
|
'Common causes:\n' +
|
|
615
575
|
'• A security plugin (Wordfence, Sucuri, iThemes Security) is blocking the /wp-json/respira/v2/ path — whitelist that path in the plugin settings.\n' +
|
|
616
576
|
'• WordPress permalinks are set to "Plain" — go to Settings → Permalinks and choose any option except Plain.\n' +
|
|
@@ -805,13 +765,7 @@ export class WordPressClient {
|
|
|
805
765
|
return new Error(`Site not reachable: ${this.siteConfig.url} returned a ${status} response from the web server (not WordPress).\n\n${hint}`);
|
|
806
766
|
}
|
|
807
767
|
const reason = data?.message || data?.code || 'Invalid API key';
|
|
808
|
-
|
|
809
|
-
// Bug 8d2c3331: stamp the WP_Error code (e.g. respira_missing_api_key)
|
|
810
|
-
// onto .name so callers like ensureV2() can tell "the route rejected my
|
|
811
|
-
// auth" (the route IS live) apart from "the route doesn't exist"
|
|
812
|
-
// instead of collapsing both into the same generic message.
|
|
813
|
-
authError.name = typeof data?.code === 'string' && data.code ? data.code.slice(0, 80) : 'http_401';
|
|
814
|
-
return authError;
|
|
768
|
+
return new Error(`Authentication failed: ${reason}`);
|
|
815
769
|
}
|
|
816
770
|
else if (status === 429) {
|
|
817
771
|
return new Error(`Rate limit exceeded. Please wait before making more requests.`);
|
|
@@ -906,6 +860,13 @@ export class WordPressClient {
|
|
|
906
860
|
if (detail) {
|
|
907
861
|
apiError.message = `${apiError.message} [attempted: ${detail}]`;
|
|
908
862
|
}
|
|
863
|
+
// Woo add-on v3.0 added many routes (brands, variations, coupons,
|
|
864
|
+
// customers, refunds, ai-readiness). A missing /woocommerce/ route
|
|
865
|
+
// on a licensed site almost always means the installed add-on
|
|
866
|
+
// predates the tool.
|
|
867
|
+
if (reqUrl.includes('/woocommerce/')) {
|
|
868
|
+
apiError.message = `${apiError.message} This tool may require a newer Respira WooCommerce Add-on (v3.0+). Update it in wp-admin under Plugins.`;
|
|
869
|
+
}
|
|
909
870
|
}
|
|
910
871
|
return apiError;
|
|
911
872
|
}
|
|
@@ -1558,19 +1519,10 @@ export class WordPressClient {
|
|
|
1558
1519
|
clearTimeout(killer);
|
|
1559
1520
|
}
|
|
1560
1521
|
}
|
|
1561
|
-
else if (file.startsWith('/') ||
|
|
1562
|
-
file
|
|
1563
|
-
file.startsWith('../') ||
|
|
1564
|
-
file.startsWith('~') ||
|
|
1565
|
-
/^[A-Za-z]:[\\/]/.test(file) || // Windows drive path: C:\... or C:/...
|
|
1566
|
-
file.startsWith('\\\\') // Windows UNC path: \\server\share\...
|
|
1567
|
-
) {
|
|
1568
|
-
// Local file path — preflight size before reading the whole file into memory.
|
|
1569
|
-
// Without the Windows branches above, a path like C:\Users\me\img.jpeg fell
|
|
1570
|
-
// through to the base64 branch below and was decoded into garbage bytes,
|
|
1571
|
-
// surfacing to the agent as "Could not connect — no response received".
|
|
1522
|
+
else if (file.startsWith('/') || file.startsWith('./') || file.startsWith('../') || file.startsWith('~')) {
|
|
1523
|
+
// Local file path — preflight size before reading the whole file into memory
|
|
1572
1524
|
const resolvedPath = file.startsWith('~')
|
|
1573
|
-
? file.replace(/^~/, process.env.HOME ||
|
|
1525
|
+
? file.replace(/^~/, process.env.HOME || '')
|
|
1574
1526
|
: resolve(file);
|
|
1575
1527
|
if (!existsSync(resolvedPath)) {
|
|
1576
1528
|
throw new Error(`File not found: ${resolvedPath}`);
|
|
@@ -1592,11 +1544,6 @@ export class WordPressClient {
|
|
|
1592
1544
|
catch (err) {
|
|
1593
1545
|
throw new Error(`Failed to read ${resolvedPath}: ${err?.message || String(err)}`);
|
|
1594
1546
|
}
|
|
1595
|
-
if (!filename) {
|
|
1596
|
-
// Caller passed only a file path (e.g. upload_media({ file: "C:\\...\\img.jpg" }))
|
|
1597
|
-
// with no separate filename — derive it from the path basename.
|
|
1598
|
-
filename = basename(resolvedPath);
|
|
1599
|
-
}
|
|
1600
1547
|
if (!mimeType) {
|
|
1601
1548
|
const ext = extname(resolvedPath).toLowerCase();
|
|
1602
1549
|
const mimeMap = {
|
|
@@ -1960,7 +1907,7 @@ export class WordPressClient {
|
|
|
1960
1907
|
/**
|
|
1961
1908
|
* Inject page builder content
|
|
1962
1909
|
*/
|
|
1963
|
-
async injectBuilderContent(builder, pageId, content, diviVersion, editTarget, mode, confirmReplace
|
|
1910
|
+
async injectBuilderContent(builder, pageId, content, diviVersion, editTarget, mode, confirmReplace) {
|
|
1964
1911
|
if (builder.toLowerCase() === 'divi') {
|
|
1965
1912
|
if (!diviVersion) {
|
|
1966
1913
|
const existing = await this.extractBuilderContent('divi', pageId);
|
|
@@ -2002,46 +1949,13 @@ export class WordPressClient {
|
|
|
2002
1949
|
// here so every downstream caller sees the same shape: pass the inner
|
|
2003
1950
|
// array when the caller wrapped it, otherwise pass through verbatim.
|
|
2004
1951
|
const normalisedContent = this.unwrapBuilderContent(content);
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
try {
|
|
2013
|
-
const response = await this.client.post(`/builder/${builder}/inject/${pageId}`, {
|
|
2014
|
-
content: normalisedContent,
|
|
2015
|
-
editTarget,
|
|
2016
|
-
mode: mode || 'replace',
|
|
2017
|
-
confirm_replace: confirmReplace === true,
|
|
2018
|
-
// Chunked build: when target_path is given, the plugin inserts the
|
|
2019
|
-
// content as children of the container at that bracket path
|
|
2020
|
-
// (e.g. "sections[0].rows[1].columns[0]") instead of at page top
|
|
2021
|
-
// level. Lets an agent build a large section in small calls when the
|
|
2022
|
-
// whole tree exceeds the AI client's per-tool-call payload cap.
|
|
2023
|
-
// Only forwarded when set, so default behaviour is unchanged.
|
|
2024
|
-
...(targetPath && targetPath.trim() !== ''
|
|
2025
|
-
? { target_path: targetPath.trim(), position: typeof position === 'number' ? position : -1 }
|
|
2026
|
-
: {}),
|
|
2027
|
-
}, { timeout: 90_000 });
|
|
2028
|
-
return response.data;
|
|
2029
|
-
}
|
|
2030
|
-
catch (err) {
|
|
2031
|
-
const isTimeout = err?.code === 'ECONNABORTED' ||
|
|
2032
|
-
err?.code === 'ETIMEDOUT' ||
|
|
2033
|
-
/timeout/i.test(String(err?.message || ''));
|
|
2034
|
-
if (!isTimeout) {
|
|
2035
|
-
throw err;
|
|
2036
|
-
}
|
|
2037
|
-
throw new Error(`inject_builder_content exceeded 90s on the "${builder}" page ${pageId}. This is almost ` +
|
|
2038
|
-
`always a large page hitting a host or edge request-time limit (for example Cloudflare or ` +
|
|
2039
|
-
`WP Engine), not a Respira error, and the write may have completed on the server — verify with ` +
|
|
2040
|
-
`extract_builder_content before retrying. To stay under the limit, build the page in smaller ` +
|
|
2041
|
-
`pieces: send the first section with mode:"append", then append the rest one or two sections ` +
|
|
2042
|
-
`per call (or use add_section / add_html). If it must go in one call, ask the host to confirm ` +
|
|
2043
|
-
`/wp-json/respira/* is not CDN-cached or WAF-challenged and to raise PHP max_execution_time.`);
|
|
2044
|
-
}
|
|
1952
|
+
const response = await this.client.post(`/builder/${builder}/inject/${pageId}`, {
|
|
1953
|
+
content: normalisedContent,
|
|
1954
|
+
editTarget,
|
|
1955
|
+
mode: mode || 'replace',
|
|
1956
|
+
confirm_replace: confirmReplace === true,
|
|
1957
|
+
});
|
|
1958
|
+
return response.data;
|
|
2045
1959
|
}
|
|
2046
1960
|
/**
|
|
2047
1961
|
* Unwrap the common `{content: array}` shape that round-tripped extracts
|
|
@@ -2134,24 +2048,17 @@ export class WordPressClient {
|
|
|
2134
2048
|
/**
|
|
2135
2049
|
* Update a specific module in a page builder page
|
|
2136
2050
|
*/
|
|
2137
|
-
async updateModule(builder, pageId, moduleIdentifier, updates, editTarget
|
|
2051
|
+
async updateModule(builder, pageId, moduleIdentifier, updates, editTarget) {
|
|
2138
2052
|
try {
|
|
2139
2053
|
// Increase timeout for large content updates
|
|
2140
2054
|
const timeout = updates.content && updates.content.length > 50000
|
|
2141
2055
|
? 60000 // 60 seconds for large content
|
|
2142
2056
|
: 30000; // 30 seconds default
|
|
2143
|
-
const
|
|
2057
|
+
const response = await this.client.put(`/builder/${builder}/modules/${pageId}`, {
|
|
2144
2058
|
module_identifier: moduleIdentifier,
|
|
2145
2059
|
updates,
|
|
2146
2060
|
editTarget,
|
|
2147
|
-
};
|
|
2148
|
-
// e402506e (Christian): forward the live-edit confirmation so the
|
|
2149
|
-
// confirmation_required handshake completes through MCP. snake_case to
|
|
2150
|
-
// match the plugin's element/module write gate.
|
|
2151
|
-
if (confirmLiveEdit !== undefined) {
|
|
2152
|
-
payload.confirm_live_edit = confirmLiveEdit;
|
|
2153
|
-
}
|
|
2154
|
-
const response = await this.client.put(`/builder/${builder}/modules/${pageId}`, payload, { timeout });
|
|
2061
|
+
}, { timeout });
|
|
2155
2062
|
return response.data;
|
|
2156
2063
|
}
|
|
2157
2064
|
catch (error) {
|
|
@@ -2279,7 +2186,7 @@ export class WordPressClient {
|
|
|
2279
2186
|
/**
|
|
2280
2187
|
* Apply v2 builder patch operations.
|
|
2281
2188
|
*/
|
|
2282
|
-
async applyBuilderPatch(builder, postId, operations, include, editTarget
|
|
2189
|
+
async applyBuilderPatch(builder, postId, operations, include, editTarget) {
|
|
2283
2190
|
await this.ensureV2();
|
|
2284
2191
|
const payload = { operations };
|
|
2285
2192
|
if (include) {
|
|
@@ -2288,10 +2195,6 @@ export class WordPressClient {
|
|
|
2288
2195
|
if (editTarget) {
|
|
2289
2196
|
payload.editTarget = editTarget;
|
|
2290
2197
|
}
|
|
2291
|
-
// e402506e (Christian): forward live-edit confirmation for the handshake.
|
|
2292
|
-
if (confirmLiveEdit !== undefined) {
|
|
2293
|
-
payload.confirm_live_edit = confirmLiveEdit;
|
|
2294
|
-
}
|
|
2295
2198
|
const response = await this.rootClient.post(`/wp-json/respira/v2/builder/${builder}/patch/${postId}`, payload);
|
|
2296
2199
|
return response.data;
|
|
2297
2200
|
}
|
|
@@ -2336,24 +2239,6 @@ export class WordPressClient {
|
|
|
2336
2239
|
const response = await this.rootClient.request({ method: 'PATCH', url, data: { content } });
|
|
2337
2240
|
return response.data;
|
|
2338
2241
|
}
|
|
2339
|
-
/**
|
|
2340
|
-
* Tail wp-content/debug.log (or the site's configured WP_DEBUG_LOG path)
|
|
2341
|
-
* via GET /respira/v2/debug-log. Read-only, no path parameter accepted —
|
|
2342
|
-
* the plugin resolves the log location itself and rejects anything
|
|
2343
|
-
* outside wp-content / the configured custom path.
|
|
2344
|
-
*/
|
|
2345
|
-
async readDebugLog(opts = {}) {
|
|
2346
|
-
const params = {};
|
|
2347
|
-
if (typeof opts.lines === 'number')
|
|
2348
|
-
params.lines = opts.lines;
|
|
2349
|
-
if (opts.level)
|
|
2350
|
-
params.level = opts.level;
|
|
2351
|
-
if (opts.since)
|
|
2352
|
-
params.since = opts.since;
|
|
2353
|
-
if (opts.grep)
|
|
2354
|
-
params.grep = opts.grep;
|
|
2355
|
-
return await this.callRestV2('GET', '/debug-log', params);
|
|
2356
|
-
}
|
|
2357
2242
|
/**
|
|
2358
2243
|
* Get site name (for logging)
|
|
2359
2244
|
*/
|
|
@@ -2366,13 +2251,6 @@ export class WordPressClient {
|
|
|
2366
2251
|
getSiteUrl() {
|
|
2367
2252
|
return this.siteConfig.url;
|
|
2368
2253
|
}
|
|
2369
|
-
/**
|
|
2370
|
-
* Get the site's API key. Used by the account site-list refresh to pick a
|
|
2371
|
-
* live `respira_site_` token to authenticate the refresh call with.
|
|
2372
|
-
*/
|
|
2373
|
-
getApiKey() {
|
|
2374
|
-
return this.siteConfig.apiKey;
|
|
2375
|
-
}
|
|
2376
2254
|
/**
|
|
2377
2255
|
* Get approvals URL in WordPress admin.
|
|
2378
2256
|
*
|
|
@@ -3127,6 +3005,251 @@ export class WordPressClient {
|
|
|
3127
3005
|
const response = await this.client.get('/woocommerce/reports/sales', { params: params || {} });
|
|
3128
3006
|
return response.data;
|
|
3129
3007
|
}
|
|
3008
|
+
// WooCommerce Add-on v3.0 — brands
|
|
3009
|
+
async woocommerceListBrands(params) {
|
|
3010
|
+
const response = await this.client.get('/woocommerce/brands', { params: params || {} });
|
|
3011
|
+
return response.data;
|
|
3012
|
+
}
|
|
3013
|
+
async woocommerceGetBrand(id) {
|
|
3014
|
+
const response = await this.client.get(`/woocommerce/brands/${id}`);
|
|
3015
|
+
return response.data;
|
|
3016
|
+
}
|
|
3017
|
+
async woocommerceCreateBrand(data) {
|
|
3018
|
+
const response = await this.client.post('/woocommerce/brands', data);
|
|
3019
|
+
return response.data;
|
|
3020
|
+
}
|
|
3021
|
+
async woocommerceUpdateBrand(id, data) {
|
|
3022
|
+
const response = await this.client.put(`/woocommerce/brands/${id}`, data);
|
|
3023
|
+
return response.data;
|
|
3024
|
+
}
|
|
3025
|
+
async woocommerceDeleteBrand(id) {
|
|
3026
|
+
const response = await this.client.delete(`/woocommerce/brands/${id}`);
|
|
3027
|
+
return response.data;
|
|
3028
|
+
}
|
|
3029
|
+
// WooCommerce Add-on v3.0 — catalog operations
|
|
3030
|
+
async woocommerceListProductsAdvanced(params) {
|
|
3031
|
+
const response = await this.client.get('/woocommerce/products/advanced', { params: params || {} });
|
|
3032
|
+
return response.data;
|
|
3033
|
+
}
|
|
3034
|
+
async woocommerceFindProduct(params) {
|
|
3035
|
+
const response = await this.client.get('/woocommerce/products/search', { params });
|
|
3036
|
+
return response.data;
|
|
3037
|
+
}
|
|
3038
|
+
async woocommerceCatalogHealth() {
|
|
3039
|
+
const response = await this.client.get('/woocommerce/catalog/health');
|
|
3040
|
+
return response.data;
|
|
3041
|
+
}
|
|
3042
|
+
async woocommerceBulkUpdateProducts(data) {
|
|
3043
|
+
const response = await this.client.post('/woocommerce/products/bulk-update', data);
|
|
3044
|
+
return response.data;
|
|
3045
|
+
}
|
|
3046
|
+
// WooCommerce Add-on v3.0 — pricing
|
|
3047
|
+
async woocommerceBulkUpdatePrices(data) {
|
|
3048
|
+
const response = await this.client.post('/woocommerce/pricing/bulk-update', data);
|
|
3049
|
+
return response.data;
|
|
3050
|
+
}
|
|
3051
|
+
async woocommerceScheduleSale(data) {
|
|
3052
|
+
const response = await this.client.post('/woocommerce/pricing/schedule-sale', data);
|
|
3053
|
+
return response.data;
|
|
3054
|
+
}
|
|
3055
|
+
async woocommerceRevertPricing(data) {
|
|
3056
|
+
const response = await this.client.post('/woocommerce/pricing/revert', data);
|
|
3057
|
+
return response.data;
|
|
3058
|
+
}
|
|
3059
|
+
// WooCommerce Add-on v3.0 — inventory
|
|
3060
|
+
async woocommerceBulkUpdateStock(data) {
|
|
3061
|
+
const response = await this.client.post('/woocommerce/inventory/bulk-update', data);
|
|
3062
|
+
return response.data;
|
|
3063
|
+
}
|
|
3064
|
+
async woocommerceFindLowStock(params) {
|
|
3065
|
+
const response = await this.client.get('/woocommerce/inventory/low-stock', { params: params || {} });
|
|
3066
|
+
return response.data;
|
|
3067
|
+
}
|
|
3068
|
+
// WooCommerce Add-on v3.0 — storefront intelligence
|
|
3069
|
+
async woocommerceAnalyzeShopPage(params) {
|
|
3070
|
+
const response = await this.client.get('/woocommerce/storefront/analyze-shop', { params: params || {} });
|
|
3071
|
+
return response.data;
|
|
3072
|
+
}
|
|
3073
|
+
async woocommerceAnalyzeProductPage(params) {
|
|
3074
|
+
const response = await this.client.get('/woocommerce/storefront/analyze-product', { params });
|
|
3075
|
+
return response.data;
|
|
3076
|
+
}
|
|
3077
|
+
async woocommerceUpdateProductCardLayout(data) {
|
|
3078
|
+
const response = await this.client.post('/woocommerce/storefront/update-card-layout', data);
|
|
3079
|
+
return response.data;
|
|
3080
|
+
}
|
|
3081
|
+
async woocommerceAddLowStockBadge(data) {
|
|
3082
|
+
const response = await this.client.post('/woocommerce/storefront/add-low-stock-badge', data);
|
|
3083
|
+
return response.data;
|
|
3084
|
+
}
|
|
3085
|
+
async woocommerceAddSaleBadge(data) {
|
|
3086
|
+
const response = await this.client.post('/woocommerce/storefront/add-sale-badge', data);
|
|
3087
|
+
return response.data;
|
|
3088
|
+
}
|
|
3089
|
+
async woocommerceUpdateCheckoutLayout(data) {
|
|
3090
|
+
const response = await this.client.post('/woocommerce/storefront/update-checkout-layout', data);
|
|
3091
|
+
return response.data;
|
|
3092
|
+
}
|
|
3093
|
+
// WooCommerce Add-on v3.0 — variations and attributes
|
|
3094
|
+
async woocommerceSetProductAttributes(id, data) {
|
|
3095
|
+
const response = await this.client.post(`/woocommerce/products/${id}/attributes`, data);
|
|
3096
|
+
return response.data;
|
|
3097
|
+
}
|
|
3098
|
+
async woocommerceGenerateVariations(id, data) {
|
|
3099
|
+
const response = await this.client.post(`/woocommerce/products/${id}/variations/generate`, data);
|
|
3100
|
+
return response.data;
|
|
3101
|
+
}
|
|
3102
|
+
async woocommerceCreateVariation(id, data) {
|
|
3103
|
+
const response = await this.client.post(`/woocommerce/products/${id}/variations`, data);
|
|
3104
|
+
return response.data;
|
|
3105
|
+
}
|
|
3106
|
+
async woocommerceCreateGlobalAttribute(data) {
|
|
3107
|
+
const response = await this.client.post('/woocommerce/attributes', data);
|
|
3108
|
+
return response.data;
|
|
3109
|
+
}
|
|
3110
|
+
async woocommerceSetVariationGallery(id, data) {
|
|
3111
|
+
const response = await this.client.put(`/woocommerce/variations/${id}/gallery`, data);
|
|
3112
|
+
return response.data;
|
|
3113
|
+
}
|
|
3114
|
+
// WooCommerce Add-on v3.0 — coupons and customers
|
|
3115
|
+
async woocommerceListCoupons(params) {
|
|
3116
|
+
const response = await this.client.get('/woocommerce/coupons', { params: params || {} });
|
|
3117
|
+
return response.data;
|
|
3118
|
+
}
|
|
3119
|
+
async woocommerceCreateCoupon(data) {
|
|
3120
|
+
const response = await this.client.post('/woocommerce/coupons', data);
|
|
3121
|
+
return response.data;
|
|
3122
|
+
}
|
|
3123
|
+
async woocommerceUpdateCoupon(id, data) {
|
|
3124
|
+
const response = await this.client.put(`/woocommerce/coupons/${id}`, data);
|
|
3125
|
+
return response.data;
|
|
3126
|
+
}
|
|
3127
|
+
async woocommerceCreateCustomer(data) {
|
|
3128
|
+
const response = await this.client.post('/woocommerce/customers', data);
|
|
3129
|
+
return response.data;
|
|
3130
|
+
}
|
|
3131
|
+
async woocommerceUpdateCustomer(id, data) {
|
|
3132
|
+
const response = await this.client.put(`/woocommerce/customers/${id}`, data);
|
|
3133
|
+
return response.data;
|
|
3134
|
+
}
|
|
3135
|
+
// WooCommerce Add-on v3.0 — order notes and refunds
|
|
3136
|
+
async woocommerceAddOrderNote(id, data) {
|
|
3137
|
+
const response = await this.client.post(`/woocommerce/orders/${id}/notes`, data);
|
|
3138
|
+
return response.data;
|
|
3139
|
+
}
|
|
3140
|
+
async woocommerceGetOrderRefunds(id) {
|
|
3141
|
+
const response = await this.client.get(`/woocommerce/orders/${id}/refunds`);
|
|
3142
|
+
return response.data;
|
|
3143
|
+
}
|
|
3144
|
+
async woocommerceCreateOrderRefund(id, data) {
|
|
3145
|
+
const response = await this.client.post(`/woocommerce/orders/${id}/refunds`, data);
|
|
3146
|
+
return response.data;
|
|
3147
|
+
}
|
|
3148
|
+
// WooCommerce Add-on v3.1 — Subscriptions / Bookings / Memberships
|
|
3149
|
+
async woocommerceListSubscriptions(params) {
|
|
3150
|
+
const response = await this.client.get('/woocommerce/subscriptions', { params: params || {} });
|
|
3151
|
+
return response.data;
|
|
3152
|
+
}
|
|
3153
|
+
async woocommerceGetSubscription(id) {
|
|
3154
|
+
const response = await this.client.get(`/woocommerce/subscriptions/${id}`);
|
|
3155
|
+
return response.data;
|
|
3156
|
+
}
|
|
3157
|
+
async woocommerceUpdateSubscriptionStatus(id, data) {
|
|
3158
|
+
const response = await this.client.put(`/woocommerce/subscriptions/${id}/status`, data || {});
|
|
3159
|
+
return response.data;
|
|
3160
|
+
}
|
|
3161
|
+
async woocommerceUpdateSubscriptionDates(id, data) {
|
|
3162
|
+
const response = await this.client.put(`/woocommerce/subscriptions/${id}/dates`, data || {});
|
|
3163
|
+
return response.data;
|
|
3164
|
+
}
|
|
3165
|
+
async woocommerceAddSubscriptionNote(id, data) {
|
|
3166
|
+
const response = await this.client.post(`/woocommerce/subscriptions/${id}/notes`, data || {});
|
|
3167
|
+
return response.data;
|
|
3168
|
+
}
|
|
3169
|
+
async woocommerceListBookings(params) {
|
|
3170
|
+
const response = await this.client.get('/woocommerce/bookings', { params: params || {} });
|
|
3171
|
+
return response.data;
|
|
3172
|
+
}
|
|
3173
|
+
async woocommerceGetBooking(id) {
|
|
3174
|
+
const response = await this.client.get(`/woocommerce/bookings/${id}`);
|
|
3175
|
+
return response.data;
|
|
3176
|
+
}
|
|
3177
|
+
async woocommerceUpdateBookingStatus(id, data) {
|
|
3178
|
+
const response = await this.client.put(`/woocommerce/bookings/${id}/status`, data || {});
|
|
3179
|
+
return response.data;
|
|
3180
|
+
}
|
|
3181
|
+
async woocommerceRescheduleBooking(id, data) {
|
|
3182
|
+
const response = await this.client.put(`/woocommerce/bookings/${id}/reschedule`, data || {});
|
|
3183
|
+
return response.data;
|
|
3184
|
+
}
|
|
3185
|
+
async woocommerceListMembershipPlans(params) {
|
|
3186
|
+
const response = await this.client.get('/woocommerce/membership-plans', { params: params || {} });
|
|
3187
|
+
return response.data;
|
|
3188
|
+
}
|
|
3189
|
+
async woocommerceListMemberships(params) {
|
|
3190
|
+
const response = await this.client.get('/woocommerce/memberships', { params: params || {} });
|
|
3191
|
+
return response.data;
|
|
3192
|
+
}
|
|
3193
|
+
async woocommerceGetMembership(id) {
|
|
3194
|
+
const response = await this.client.get(`/woocommerce/memberships/${id}`);
|
|
3195
|
+
return response.data;
|
|
3196
|
+
}
|
|
3197
|
+
async woocommerceUpdateMembershipStatus(id, data) {
|
|
3198
|
+
const response = await this.client.put(`/woocommerce/memberships/${id}/status`, data || {});
|
|
3199
|
+
return response.data;
|
|
3200
|
+
}
|
|
3201
|
+
async woocommerceSetMembershipEndDate(id, data) {
|
|
3202
|
+
const response = await this.client.put(`/woocommerce/memberships/${id}/end-date`, data || {});
|
|
3203
|
+
return response.data;
|
|
3204
|
+
}
|
|
3205
|
+
// WooCommerce Add-on v3.1 — assisted checkout
|
|
3206
|
+
async woocommerceCreateCartLink(data) {
|
|
3207
|
+
const response = await this.client.post('/woocommerce/cart-links', data);
|
|
3208
|
+
return response.data;
|
|
3209
|
+
}
|
|
3210
|
+
async woocommerceAgentOrdersReport(params) {
|
|
3211
|
+
const response = await this.client.get('/woocommerce/reports/agent-orders', { params: params || {} });
|
|
3212
|
+
return response.data;
|
|
3213
|
+
}
|
|
3214
|
+
// WooCommerce Add-on v3.1 — readiness autofix
|
|
3215
|
+
async woocommerceReadinessFixlist(params) {
|
|
3216
|
+
const response = await this.client.get('/woocommerce/catalog/readiness-fixlist', { params: params || {} });
|
|
3217
|
+
return response.data;
|
|
3218
|
+
}
|
|
3219
|
+
async woocommerceSetImageAlt(id, data) {
|
|
3220
|
+
const response = await this.client.post(`/woocommerce/products/${id}/image-alt`, data);
|
|
3221
|
+
return response.data;
|
|
3222
|
+
}
|
|
3223
|
+
// WooCommerce Add-on v3.1 — product feeds
|
|
3224
|
+
async woocommerceConfigureFeed(data) {
|
|
3225
|
+
const response = await this.client.post('/woocommerce/feeds/config', data || {});
|
|
3226
|
+
return response.data;
|
|
3227
|
+
}
|
|
3228
|
+
async woocommerceGenerateFeed(data) {
|
|
3229
|
+
const response = await this.client.post('/woocommerce/feeds/generate', data || {});
|
|
3230
|
+
return response.data;
|
|
3231
|
+
}
|
|
3232
|
+
async woocommerceGetFeedStatus() {
|
|
3233
|
+
const response = await this.client.get('/woocommerce/feeds/status');
|
|
3234
|
+
return response.data;
|
|
3235
|
+
}
|
|
3236
|
+
async woocommerceValidateFeed(params) {
|
|
3237
|
+
const response = await this.client.get('/woocommerce/feeds/validate', { params: params || {} });
|
|
3238
|
+
return response.data;
|
|
3239
|
+
}
|
|
3240
|
+
async woocommerceSetFeedCategoryMapping(data) {
|
|
3241
|
+
const response = await this.client.post('/woocommerce/feeds/category-mapping', data || {});
|
|
3242
|
+
return response.data;
|
|
3243
|
+
}
|
|
3244
|
+
// WooCommerce Add-on v3.0 — AI readiness
|
|
3245
|
+
async woocommerceProductAiReadiness(id) {
|
|
3246
|
+
const response = await this.client.get(`/woocommerce/products/${id}/ai-readiness`);
|
|
3247
|
+
return response.data;
|
|
3248
|
+
}
|
|
3249
|
+
async woocommerceCatalogAiReadiness(params) {
|
|
3250
|
+
const response = await this.client.get('/woocommerce/catalog/ai-readiness', { params: params || {} });
|
|
3251
|
+
return response.data;
|
|
3252
|
+
}
|
|
3130
3253
|
// --- Accessibility ---
|
|
3131
3254
|
async listAccessibilityScans(opts) {
|
|
3132
3255
|
const response = await this.client.get('/accessibility/scans', {
|