@respira/wordpress-mcp-server 8.3.18 → 8.3.20
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 +89 -0
- package/TOOL_CATALOG.md +36 -36
- package/dist/__tests__/0e6bd33c-redeem-preserves-per-site-settings.test.d.ts +2 -0
- package/dist/__tests__/0e6bd33c-redeem-preserves-per-site-settings.test.d.ts.map +1 -0
- package/dist/__tests__/0e6bd33c-redeem-preserves-per-site-settings.test.js +91 -0
- package/dist/__tests__/0e6bd33c-redeem-preserves-per-site-settings.test.js.map +1 -0
- package/dist/__tests__/139f7353-put-fallback-dedicated-methods.test.d.ts +30 -0
- package/dist/__tests__/139f7353-put-fallback-dedicated-methods.test.d.ts.map +1 -0
- package/dist/__tests__/139f7353-put-fallback-dedicated-methods.test.js +162 -0
- package/dist/__tests__/139f7353-put-fallback-dedicated-methods.test.js.map +1 -0
- package/dist/__tests__/44fcf6b5-basic-auth-is-not-a-blocked-verb.test.d.ts +2 -0
- package/dist/__tests__/44fcf6b5-basic-auth-is-not-a-blocked-verb.test.d.ts.map +1 -0
- package/dist/__tests__/44fcf6b5-basic-auth-is-not-a-blocked-verb.test.js +207 -0
- package/dist/__tests__/44fcf6b5-basic-auth-is-not-a-blocked-verb.test.js.map +1 -0
- package/dist/__tests__/e105ed25-report-issue-builder-context.test.d.ts +2 -0
- package/dist/__tests__/e105ed25-report-issue-builder-context.test.d.ts.map +1 -0
- package/dist/__tests__/e105ed25-report-issue-builder-context.test.js +115 -0
- package/dist/__tests__/e105ed25-report-issue-builder-context.test.js.map +1 -0
- package/dist/__tests__/respira-outage-blamed-on-the-site.test.d.ts +2 -0
- package/dist/__tests__/respira-outage-blamed-on-the-site.test.d.ts.map +1 -0
- package/dist/__tests__/respira-outage-blamed-on-the-site.test.js +83 -0
- package/dist/__tests__/respira-outage-blamed-on-the-site.test.js.map +1 -0
- package/dist/__tests__/upload-media-path-detection.test.js +35 -1
- package/dist/__tests__/upload-media-path-detection.test.js.map +1 -1
- package/dist/__tests__/v2-negotiation-ttl-retry.test.d.ts +2 -0
- package/dist/__tests__/v2-negotiation-ttl-retry.test.d.ts.map +1 -0
- package/dist/__tests__/v2-negotiation-ttl-retry.test.js +108 -0
- package/dist/__tests__/v2-negotiation-ttl-retry.test.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +59 -4
- package/dist/config.js.map +1 -1
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +54 -4
- package/dist/server.js.map +1 -1
- package/dist/wordpress-client.d.ts +108 -1
- package/dist/wordpress-client.d.ts.map +1 -1
- package/dist/wordpress-client.js +467 -77
- package/dist/wordpress-client.js.map +1 -1
- package/package.json +2 -2
- package/skills/woo-marketing-campaigns/SKILL.md +128 -0
- package/skills/woo-pricing-promotions/SKILL.md +119 -0
- package/tool-capabilities.json +92 -344
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,95 @@ All notable changes to Respira WordPress MCP Server will be documented in this f
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [8.3.20] - 2026-09-09
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **One failed handshake made a site look broken for the rest of the session.** A
|
|
13
|
+
successful version negotiation is cached for the life of the client, which is right.
|
|
14
|
+
A failure was cached the same way, which is not: a single transient error from the
|
|
15
|
+
host meant every later call replayed the same verdict without sending a request, so
|
|
16
|
+
nothing appeared in the site's own logs either and the site looked dead for as long as
|
|
17
|
+
the session lasted. Two customers sat blocked for a quarter of an hour on sites that
|
|
18
|
+
were already healthy. Failures now expire after a minute, and a message that came from
|
|
19
|
+
cache says when the failure was first seen instead of implying a fresh check.
|
|
20
|
+
- **A Respira outage was described as a fault on the customer's site.** When the
|
|
21
|
+
account service could not answer, the resulting error was rendered as though the site
|
|
22
|
+
had produced it, ending with advice to go and read wp-content/debug.log. The failure
|
|
23
|
+
is now named for what it is, a problem reaching Respira rather than anything to fix on
|
|
24
|
+
the site, and the debug.log advice is gone from that path.
|
|
25
|
+
- **Editing a menu item failed on hosts that block PUT.** Those hosts already had a
|
|
26
|
+
fallback that reissues the request as a POST, but it was only wired into some paths,
|
|
27
|
+
and twenty five methods called PUT directly without it, menus among them. The fallback
|
|
28
|
+
could not have rescued them anyway: it decided whether to retry by reading a status
|
|
29
|
+
that the shared error handler discards, so it only ever fired for one specific case
|
|
30
|
+
and never for a real 405. Both halves are fixed, so every PUT write now falls back
|
|
31
|
+
where the host requires it. Deletes still need a change on the WordPress side and are
|
|
32
|
+
unchanged for now.
|
|
33
|
+
- **Redeeming an install token discarded local per-site settings.** The redeemed entry
|
|
34
|
+
replaced the stored one outright, and the dashboard only sends five fields, so
|
|
35
|
+
anything set by hand was dropped: the flag that forces the query-string REST route,
|
|
36
|
+
the forced write method, HTTP auth credentials, the TLS exception, and local tool
|
|
37
|
+
preferences. The site kept working until the next restart, which put the loss a long
|
|
38
|
+
way from its cause. A redeem now updates the fields it carries and leaves the rest
|
|
39
|
+
alone.
|
|
40
|
+
- **A password-protected site was reported as one with Respira uninstalled.** The check
|
|
41
|
+
for whether the Respira routes exist was the one request in the client that did not
|
|
42
|
+
send configured credentials, so on a site behind HTTP auth it was refused, and the
|
|
43
|
+
refusal was read as the routes being absent. The connector then said the plugin was
|
|
44
|
+
deactivated, deleted, or failing to load. It also called an authentication challenge a
|
|
45
|
+
firewall or maintenance mode, and told operators to add credentials they had already
|
|
46
|
+
added. The probe now authenticates, an unanswerable check says so instead of claiming
|
|
47
|
+
absence, and the connection diagnostic reports an authentication challenge as what it
|
|
48
|
+
is rather than as a blocked method.
|
|
49
|
+
- **Filed issue reports lost the builder they came from.** The report tool read the
|
|
50
|
+
builder name from a field the site does not return, so every report was filed with no
|
|
51
|
+
builder recorded even when the site could name it unambiguously.
|
|
52
|
+
- **Two commerce skills were never shipped.** The bundling step rebuilds the skills
|
|
53
|
+
directory from source on every build, and these two existed only in the built copy, so
|
|
54
|
+
each build deleted them. They were listed in the public catalogue throughout. Both now
|
|
55
|
+
ship, and the build fails loudly rather than quietly deleting a skill that is missing
|
|
56
|
+
from source.
|
|
57
|
+
|
|
58
|
+
## [8.3.19] - 2026-09-04
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
- **Uploading a JPEG never worked.** `upload_media` decided whether the `file`
|
|
63
|
+
argument was a filesystem path by testing whether it started with `/`. Base64 of a
|
|
64
|
+
JPEG's opening bytes is `/9j/`, so every bare base64 JPEG matched that test, was
|
|
65
|
+
treated as an absolute path, and failed with "File not found: /9j/...". Nothing
|
|
66
|
+
ever reached WordPress. The existing test missed it because its sample payload
|
|
67
|
+
happened to start with a letter.
|
|
68
|
+
- **A failed upload hung for minutes instead of retrying.** The multipart body was a
|
|
69
|
+
single-use stream, and both retry paths (the 5xx idempotency retry and the
|
|
70
|
+
`?rest_route=` fallback) re-sent the already-consumed stream with the original
|
|
71
|
+
`Content-Length`. The request promised bytes it then never wrote, so it never
|
|
72
|
+
reached the server and sat until the socket timed out. Measured at 88 seconds for
|
|
73
|
+
one call, with only the first attempt ever delivered. The body is now replayable
|
|
74
|
+
and no streaming body is re-sent.
|
|
75
|
+
- **The `?rest_route=` upload fallback had never worked.** It inherited the same
|
|
76
|
+
exhausted stream, so the fallback reported that the host "also returned HTML"
|
|
77
|
+
without having sent anything.
|
|
78
|
+
- **One bad upload could take the whole server down.** Error responses skipped the
|
|
79
|
+
size cap that success responses go through, so a failed upload echoed the entire
|
|
80
|
+
base64 payload back inside the error message. A 900 KB image produced a 1.2 MB
|
|
81
|
+
JSON-RPC frame against a 100 KiB cap, and an oversized frame makes MCP hosts kill
|
|
82
|
+
the subprocess, which is why every later tool call timed out until a restart. Error
|
|
83
|
+
messages are now truncated.
|
|
84
|
+
- The tool description advertised a 120 second upload timeout; the actual default has
|
|
85
|
+
been 90 seconds since 6.18.4. Corrected.
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
|
|
89
|
+
- `mcp-bundle/build.sh` now packs the local `mcp-server` when its version matches the
|
|
90
|
+
bundle's pin, instead of always resolving from the npm registry. The registry path
|
|
91
|
+
remains as the fallback. The bundle could previously only be built after publishing,
|
|
92
|
+
while the release workflow's parity gate runs before publishing and requires the
|
|
93
|
+
built bundle to already carry the version being released, so a release was
|
|
94
|
+
unsatisfiable on the first attempt at any version. It also means the bundle is now
|
|
95
|
+
reproducible from the tag rather than dependent on registry state.
|
|
96
|
+
|
|
8
97
|
## [8.3.18] - 2026-09-03
|
|
9
98
|
|
|
10
99
|
### Fixed
|
package/TOOL_CATALOG.md
CHANGED
|
@@ -9,24 +9,24 @@ The runtime applies site context and per-site governance, so an individual conne
|
|
|
9
9
|
## WordPress and Respira
|
|
10
10
|
|
|
11
11
|
- `respira_duplicate_with_translations` — write; hosted/stdio
|
|
12
|
-
- `wordpress_abilities_gap_report` — read; hosted
|
|
12
|
+
- `wordpress_abilities_gap_report` — read; native + hosted
|
|
13
13
|
- `wordpress_activate_design_direction` — write; native + hosted
|
|
14
14
|
- `wordpress_activate_plugin` — write; native + hosted
|
|
15
15
|
- `wordpress_analyze_aeo` — read; native + hosted
|
|
16
16
|
- `wordpress_analyze_images` — read; native + hosted
|
|
17
|
-
- `wordpress_analyze_pagespeed` — read; hosted
|
|
17
|
+
- `wordpress_analyze_pagespeed` — read; native + hosted
|
|
18
18
|
- `wordpress_analyze_performance` — read; native + hosted
|
|
19
19
|
- `wordpress_analyze_rankmath` — read; native + hosted
|
|
20
20
|
- `wordpress_analyze_readability` — read; native + hosted
|
|
21
21
|
- `wordpress_analyze_seo` — read; native + hosted
|
|
22
|
-
- `wordpress_append_theme_file` — read; hosted
|
|
23
|
-
- `wordpress_apply_accessibility_fixes` — write; hosted
|
|
22
|
+
- `wordpress_append_theme_file` — read; native + hosted
|
|
23
|
+
- `wordpress_apply_accessibility_fixes` — write; native + hosted
|
|
24
24
|
- `wordpress_apply_builder_patch` — write; native + hosted
|
|
25
25
|
- `wordpress_apply_design_direction` — write; native + hosted
|
|
26
|
-
- `wordpress_apply_divi_library_item` — write; hosted
|
|
26
|
+
- `wordpress_apply_divi_library_item` — write; native + hosted
|
|
27
27
|
- `wordpress_assign_menu_location` — write; native + hosted
|
|
28
28
|
- `wordpress_batch_update` — write; native + hosted
|
|
29
|
-
- `wordpress_begin_session` — read; hosted
|
|
29
|
+
- `wordpress_begin_session` — read; native + hosted
|
|
30
30
|
- `wordpress_build_mega_menu` — write; native + hosted
|
|
31
31
|
- `wordpress_build_page` — write; native + hosted
|
|
32
32
|
- `wordpress_bulk_pages_operation` — write; native + hosted
|
|
@@ -34,7 +34,7 @@ The runtime applies site context and per-site governance, so an individual conne
|
|
|
34
34
|
- `wordpress_check_seo_issues` — read; native + hosted
|
|
35
35
|
- `wordpress_check_structured_data` — read; native + hosted
|
|
36
36
|
- `wordpress_convert_html_to_builder` — write; native + hosted
|
|
37
|
-
- `wordpress_create_acf_field_group` — write; hosted
|
|
37
|
+
- `wordpress_create_acf_field_group` — write; native + hosted
|
|
38
38
|
- `wordpress_create_comment` — write; native + hosted
|
|
39
39
|
- `wordpress_create_custom_post` — write; native + hosted
|
|
40
40
|
- `wordpress_create_design_token` — write; native + hosted
|
|
@@ -43,23 +43,23 @@ The runtime applies site context and per-site governance, so an individual conne
|
|
|
43
43
|
- `wordpress_create_page_duplicate` — write; native + hosted
|
|
44
44
|
- `wordpress_create_playbook` — write; hosted/stdio
|
|
45
45
|
- `wordpress_create_post_duplicate` — write; native + hosted
|
|
46
|
-
- `wordpress_create_post_type` — write; hosted
|
|
46
|
+
- `wordpress_create_post_type` — write; native + hosted
|
|
47
47
|
- `wordpress_create_site_navigation` — write; native + hosted
|
|
48
48
|
- `wordpress_create_site_pattern` — write; native + hosted
|
|
49
49
|
- `wordpress_create_site_template` — write; native + hosted
|
|
50
|
-
- `wordpress_create_taxonomy` — write; hosted
|
|
50
|
+
- `wordpress_create_taxonomy` — write; native + hosted
|
|
51
51
|
- `wordpress_create_term` — write; native + hosted
|
|
52
52
|
- `wordpress_create_theme_builder_template` — write; native + hosted
|
|
53
53
|
- `wordpress_create_translation` — write; native + hosted
|
|
54
54
|
- `wordpress_create_user` — write; native + hosted
|
|
55
55
|
- `wordpress_deactivate_design_direction` — write; native + hosted
|
|
56
56
|
- `wordpress_deactivate_plugin` — write; native + hosted
|
|
57
|
-
- `wordpress_delete_acf_field_group` — write; hosted
|
|
57
|
+
- `wordpress_delete_acf_field_group` — write; native + hosted
|
|
58
58
|
- `wordpress_delete_comment` — write; native + hosted
|
|
59
59
|
- `wordpress_delete_custom_post` — write; native + hosted
|
|
60
60
|
- `wordpress_delete_design_direction` — write; native + hosted
|
|
61
61
|
- `wordpress_delete_design_token` — write; native + hosted
|
|
62
|
-
- `wordpress_delete_divi_preset` — write; hosted
|
|
62
|
+
- `wordpress_delete_divi_preset` — write; native + hosted
|
|
63
63
|
- `wordpress_delete_media` — write; native + hosted
|
|
64
64
|
- `wordpress_delete_menu` — write; native + hosted
|
|
65
65
|
- `wordpress_delete_menu_item` — write; native + hosted
|
|
@@ -68,37 +68,37 @@ The runtime applies site context and per-site governance, so an individual conne
|
|
|
68
68
|
- `wordpress_delete_playbook` — write; hosted/stdio
|
|
69
69
|
- `wordpress_delete_plugin` — write; native + hosted
|
|
70
70
|
- `wordpress_delete_post` — write; native + hosted
|
|
71
|
-
- `wordpress_delete_post_type` — write; hosted
|
|
71
|
+
- `wordpress_delete_post_type` — write; native + hosted
|
|
72
72
|
- `wordpress_delete_site_navigation` — write; native + hosted
|
|
73
73
|
- `wordpress_delete_site_pattern` — write; native + hosted
|
|
74
|
-
- `wordpress_delete_taxonomy` — write; hosted
|
|
74
|
+
- `wordpress_delete_taxonomy` — write; native + hosted
|
|
75
75
|
- `wordpress_delete_term` — write; native + hosted
|
|
76
76
|
- `wordpress_delete_user` — write; native + hosted
|
|
77
77
|
- `wordpress_diagnose_connection` — read; hosted/stdio
|
|
78
78
|
- `wordpress_diff_snapshots` — read; native + hosted
|
|
79
79
|
- `wordpress_duplicate_element` — write; native + hosted
|
|
80
|
-
- `wordpress_end_session` — read; hosted
|
|
80
|
+
- `wordpress_end_session` — read; native + hosted
|
|
81
81
|
- `wordpress_export_design_direction` — read; native + hosted
|
|
82
82
|
- `wordpress_extract_builder_content` — read; native + hosted
|
|
83
83
|
- `wordpress_find_builder_targets` — read; native + hosted
|
|
84
84
|
- `wordpress_find_element` — read; native + hosted
|
|
85
85
|
- `wordpress_forget` — read; native + hosted
|
|
86
|
-
- `wordpress_get_accessibility_scan` — read; hosted
|
|
86
|
+
- `wordpress_get_accessibility_scan` — read; native + hosted
|
|
87
87
|
- `wordpress_get_active_site` — read; hosted/stdio
|
|
88
88
|
- `wordpress_get_activity` — read; native + hosted
|
|
89
89
|
- `wordpress_get_builder_info` — read; native + hosted
|
|
90
|
-
- `wordpress_get_builder_inline_schemas` — read; hosted
|
|
90
|
+
- `wordpress_get_builder_inline_schemas` — read; native + hosted
|
|
91
91
|
- `wordpress_get_comment` — read; native + hosted
|
|
92
92
|
- `wordpress_get_core_web_vitals` — read; native + hosted
|
|
93
93
|
- `wordpress_get_custom_post` — read; native + hosted
|
|
94
94
|
- `wordpress_get_design_apply_reports` — read; native + hosted
|
|
95
95
|
- `wordpress_get_design_direction` — read; native + hosted
|
|
96
|
-
- `wordpress_get_divi_migration_readiness` — read; hosted
|
|
96
|
+
- `wordpress_get_divi_migration_readiness` — read; native + hosted
|
|
97
97
|
- `wordpress_get_media` — read; native + hosted
|
|
98
98
|
- `wordpress_get_menu` — read; native + hosted
|
|
99
99
|
- `wordpress_get_menu_item` — read; native + hosted
|
|
100
100
|
- `wordpress_get_option` — read; native + hosted
|
|
101
|
-
- `wordpress_get_page_outline` — read; hosted
|
|
101
|
+
- `wordpress_get_page_outline` — read; native + hosted
|
|
102
102
|
- `wordpress_get_playbook` — read; hosted/stdio
|
|
103
103
|
- `wordpress_get_post_type` — read; native + hosted
|
|
104
104
|
- `wordpress_get_server_compatibility` — read; native + hosted
|
|
@@ -116,16 +116,16 @@ The runtime applies site context and per-site governance, so an individual conne
|
|
|
116
116
|
- `wordpress_inject_builder_content` — write; native + hosted
|
|
117
117
|
- `wordpress_install_plugin` — write; native + hosted
|
|
118
118
|
- `wordpress_invoke_ability` — write; hosted/stdio
|
|
119
|
-
- `wordpress_list_accessibility_scans` — read; hosted
|
|
120
|
-
- `wordpress_list_acf_field_groups` — read; hosted
|
|
119
|
+
- `wordpress_list_accessibility_scans` — read; native + hosted
|
|
120
|
+
- `wordpress_list_acf_field_groups` — read; native + hosted
|
|
121
121
|
- `wordpress_list_activity` — read; native + hosted
|
|
122
122
|
- `wordpress_list_comments` — read; native + hosted
|
|
123
|
-
- `wordpress_list_custom_post_types` — read; hosted
|
|
123
|
+
- `wordpress_list_custom_post_types` — read; native + hosted
|
|
124
124
|
- `wordpress_list_custom_posts` — read; native + hosted
|
|
125
|
-
- `wordpress_list_custom_taxonomies` — read; hosted
|
|
125
|
+
- `wordpress_list_custom_taxonomies` — read; native + hosted
|
|
126
126
|
- `wordpress_list_design_directions` — read; native + hosted
|
|
127
127
|
- `wordpress_list_design_tokens` — read; native + hosted
|
|
128
|
-
- `wordpress_list_divi_presets` — read; hosted
|
|
128
|
+
- `wordpress_list_divi_presets` — read; native + hosted
|
|
129
129
|
- `wordpress_list_media` — read; native + hosted
|
|
130
130
|
- `wordpress_list_memory` — read; native + hosted
|
|
131
131
|
- `wordpress_list_menu_items` — read; native + hosted
|
|
@@ -146,40 +146,40 @@ The runtime applies site context and per-site governance, so an individual conne
|
|
|
146
146
|
- `wordpress_list_terms` — read; native + hosted
|
|
147
147
|
- `wordpress_list_theme_builder_templates` — read; native + hosted
|
|
148
148
|
- `wordpress_list_users` — read; native + hosted
|
|
149
|
-
- `wordpress_make_responsive` — read; hosted
|
|
149
|
+
- `wordpress_make_responsive` — read; native + hosted
|
|
150
150
|
- `wordpress_mint_design_preview` — read; native + hosted
|
|
151
151
|
- `wordpress_move_element` — write; native + hosted
|
|
152
152
|
- `wordpress_purge_cache` — write; native + hosted
|
|
153
153
|
- `wordpress_read_page` — read; native + hosted
|
|
154
154
|
- `wordpress_read_post` — read; native + hosted
|
|
155
|
-
- `wordpress_read_theme_file` — read; hosted
|
|
155
|
+
- `wordpress_read_theme_file` — read; native + hosted
|
|
156
156
|
- `wordpress_redeem_token` — write; hosted/stdio
|
|
157
157
|
- `wordpress_remember` — read; native + hosted
|
|
158
158
|
- `wordpress_remove_element` — write; native + hosted
|
|
159
159
|
- `wordpress_reorder_elements` — write; native + hosted
|
|
160
160
|
- `wordpress_report_issue` — read; hosted/stdio
|
|
161
161
|
- `wordpress_reset_site_template` — write; native + hosted
|
|
162
|
-
- `wordpress_resolve_divi_preset` — read; hosted
|
|
163
|
-
- `wordpress_restore_session` — write; hosted
|
|
162
|
+
- `wordpress_resolve_divi_preset` — read; native + hosted
|
|
163
|
+
- `wordpress_restore_session` — write; native + hosted
|
|
164
164
|
- `wordpress_restore_snapshot` — write; native + hosted
|
|
165
|
-
- `wordpress_run_pagespeed_audit` — read; hosted
|
|
165
|
+
- `wordpress_run_pagespeed_audit` — read; native + hosted
|
|
166
166
|
- `wordpress_run_security_audit` — read; native + hosted
|
|
167
167
|
- `wordpress_save_design_direction` — write; native + hosted
|
|
168
|
-
- `wordpress_save_divi_library_item` — write; hosted
|
|
169
|
-
- `wordpress_scan_page_accessibility` — read; hosted
|
|
168
|
+
- `wordpress_save_divi_library_item` — write; native + hosted
|
|
169
|
+
- `wordpress_scan_page_accessibility` — read; native + hosted
|
|
170
170
|
- `wordpress_search_abilities` — read; native + hosted
|
|
171
171
|
- `wordpress_search_docs` — read; hosted/stdio
|
|
172
172
|
- `wordpress_search_stock_images` — read; native + hosted
|
|
173
173
|
- `wordpress_sideload_image` — write; native + hosted
|
|
174
174
|
- `wordpress_switch_site` — write; native + hosted
|
|
175
|
-
- `wordpress_update_acf_field_group` — write; hosted
|
|
175
|
+
- `wordpress_update_acf_field_group` — write; native + hosted
|
|
176
176
|
- `wordpress_update_comment` — write; native + hosted
|
|
177
177
|
- `wordpress_update_core_security` — write; native + hosted
|
|
178
178
|
- `wordpress_update_custom_post` — write; native + hosted
|
|
179
179
|
- `wordpress_update_design_token` — write; native + hosted
|
|
180
180
|
- `wordpress_update_element` — write; native + hosted
|
|
181
181
|
- `wordpress_update_media` — write; native + hosted
|
|
182
|
-
- `wordpress_update_media_batch` — write; hosted
|
|
182
|
+
- `wordpress_update_media_batch` — write; native + hosted
|
|
183
183
|
- `wordpress_update_menu` — write; native + hosted
|
|
184
184
|
- `wordpress_update_menu_item` — write; native + hosted
|
|
185
185
|
- `wordpress_update_module` — write; native + hosted
|
|
@@ -188,19 +188,19 @@ The runtime applies site context and per-site governance, so an individual conne
|
|
|
188
188
|
- `wordpress_update_playbook` — write; hosted/stdio
|
|
189
189
|
- `wordpress_update_plugin` — write; native + hosted
|
|
190
190
|
- `wordpress_update_post` — write; native + hosted
|
|
191
|
-
- `wordpress_update_post_type` — write; hosted
|
|
191
|
+
- `wordpress_update_post_type` — write; native + hosted
|
|
192
192
|
- `wordpress_update_site_navigation` — write; native + hosted
|
|
193
193
|
- `wordpress_update_site_pattern` — write; native + hosted
|
|
194
194
|
- `wordpress_update_site_template` — write; native + hosted
|
|
195
|
-
- `wordpress_update_taxonomy` — write; hosted
|
|
195
|
+
- `wordpress_update_taxonomy` — write; native + hosted
|
|
196
196
|
- `wordpress_update_term` — write; native + hosted
|
|
197
197
|
- `wordpress_update_theme_builder_template` — write; native + hosted
|
|
198
198
|
- `wordpress_update_translation` — write; native + hosted
|
|
199
199
|
- `wordpress_update_user` — write; native + hosted
|
|
200
200
|
- `wordpress_upload_media` — write; native + hosted
|
|
201
|
-
- `wordpress_upsert_divi_presets` — read; hosted
|
|
201
|
+
- `wordpress_upsert_divi_presets` — read; native + hosted
|
|
202
202
|
- `wordpress_validate_security` — read; native + hosted
|
|
203
|
-
- `wordpress_write_theme_file` — read; hosted
|
|
203
|
+
- `wordpress_write_theme_file` — read; native + hosted
|
|
204
204
|
|
|
205
205
|
## WooCommerce add-on
|
|
206
206
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0e6bd33c-redeem-preserves-per-site-settings.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/0e6bd33c-redeem-preserves-per-site-settings.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket 0e6bd33c — redeeming a token must not silently discard the per-site
|
|
3
|
+
* settings the token does not own.
|
|
4
|
+
*
|
|
5
|
+
* A redeem token carries exactly five fields per site: id, name, url, apiKey
|
|
6
|
+
* and default (buildRespiraConfig, product-website/src/lib/mcp-config.ts).
|
|
7
|
+
* Everything else on a site object in ~/.respira/config.json was put there by
|
|
8
|
+
* the operator, usually on this connector's own advice:
|
|
9
|
+
*
|
|
10
|
+
* forceRestRoute — the only thing that makes hosts work where pretty
|
|
11
|
+
* /wp-json/ 404s and ?rest_route= returns JSON
|
|
12
|
+
* forceWriteMethod — the only thing that makes hosts work where PUT is
|
|
13
|
+
* blocked or dropped
|
|
14
|
+
* httpAuth — server-level Basic Auth for staging sites
|
|
15
|
+
* insecureTLS — the documented TLS escape hatch
|
|
16
|
+
*
|
|
17
|
+
* mergeRedeemedSites used to do `byKey.set(key, site)` on a URL collision:
|
|
18
|
+
* the freshly minted entry replaced the whole object. Redeem reported
|
|
19
|
+
* success, the file was rewritten, and every one of those flags was gone.
|
|
20
|
+
* The session kept working (the live clients were already built) so nothing
|
|
21
|
+
* failed until the next restart, at which point the site failed exactly the
|
|
22
|
+
* way it had failed before the flag was added.
|
|
23
|
+
*
|
|
24
|
+
* These assertions fail on unmodified main.
|
|
25
|
+
*/
|
|
26
|
+
import { test } from 'node:test';
|
|
27
|
+
import assert from 'node:assert/strict';
|
|
28
|
+
import { mergeRedeemedSites } from '../config.js';
|
|
29
|
+
/** What the dashboard mints: five fields, nothing else. */
|
|
30
|
+
function tokenSite(id, url, extra = {}) {
|
|
31
|
+
return { id, name: id, url, apiKey: `respira_site_${id}`, ...extra };
|
|
32
|
+
}
|
|
33
|
+
test('a re-redeem keeps forceRestRoute on the site that needed it', () => {
|
|
34
|
+
const existing = [
|
|
35
|
+
tokenSite('a', 'https://a.example.com', { default: true, forceRestRoute: true }),
|
|
36
|
+
];
|
|
37
|
+
const merged = mergeRedeemedSites(existing, [tokenSite('a', 'https://a.example.com', { default: true })]);
|
|
38
|
+
assert.equal(merged.length, 1);
|
|
39
|
+
assert.equal(merged[0].forceRestRoute, true, 'forceRestRoute was dropped by the redeem rewrite; the site 404s on every call after the next restart');
|
|
40
|
+
});
|
|
41
|
+
test('a re-redeem keeps every per-site key the token does not carry', () => {
|
|
42
|
+
const existing = [
|
|
43
|
+
tokenSite('a', 'https://a.example.com', {
|
|
44
|
+
default: true,
|
|
45
|
+
forceRestRoute: true,
|
|
46
|
+
forceWriteMethod: 'post',
|
|
47
|
+
insecureTLS: true,
|
|
48
|
+
httpAuth: { username: 'staging', password: 'hunter2' },
|
|
49
|
+
}),
|
|
50
|
+
];
|
|
51
|
+
const merged = mergeRedeemedSites(existing, [tokenSite('a', 'https://a.example.com', { default: true })]);
|
|
52
|
+
assert.equal(merged[0].forceRestRoute, true, 'forceRestRoute dropped');
|
|
53
|
+
assert.equal(merged[0].forceWriteMethod, 'post', 'forceWriteMethod dropped');
|
|
54
|
+
assert.equal(merged[0].insecureTLS, true, 'insecureTLS dropped');
|
|
55
|
+
assert.deepEqual(merged[0].httpAuth, { username: 'staging', password: 'hunter2' }, 'httpAuth dropped');
|
|
56
|
+
});
|
|
57
|
+
test('an unrecognised per-site key added by hand also survives', () => {
|
|
58
|
+
// Deliberately not in WordPressSiteConfig: an allowlist-based fix would
|
|
59
|
+
// drop this, and would drop every future key added to the schema too.
|
|
60
|
+
const existing = [
|
|
61
|
+
{ ...tokenSite('a', 'https://a.example.com', { default: true }), someFutureFlag: 'keep-me' },
|
|
62
|
+
];
|
|
63
|
+
const merged = mergeRedeemedSites(existing, [tokenSite('a', 'https://a.example.com', { default: true })]);
|
|
64
|
+
assert.equal(merged[0].someFutureFlag, 'keep-me');
|
|
65
|
+
});
|
|
66
|
+
test('the token still wins for the fields it does carry', () => {
|
|
67
|
+
const existing = [
|
|
68
|
+
tokenSite('a', 'https://a.example.com', { default: true, forceRestRoute: true }),
|
|
69
|
+
];
|
|
70
|
+
const merged = mergeRedeemedSites(existing, [
|
|
71
|
+
{ id: 'a', name: 'Renamed', url: 'https://a.example.com', apiKey: 'respira_site_rotated', default: true },
|
|
72
|
+
]);
|
|
73
|
+
assert.equal(merged[0].apiKey, 'respira_site_rotated', 'a rotated key must still land');
|
|
74
|
+
assert.equal(merged[0].name, 'Renamed', 'a renamed site must still land');
|
|
75
|
+
assert.equal(merged[0].forceRestRoute, true, 'and the local flag must still survive it');
|
|
76
|
+
});
|
|
77
|
+
test('preserving local keys does not leave two sites claiming default', () => {
|
|
78
|
+
const existing = [
|
|
79
|
+
tokenSite('a', 'https://a.example.com', { default: true, forceRestRoute: true }),
|
|
80
|
+
tokenSite('b', 'https://b.example.com'),
|
|
81
|
+
];
|
|
82
|
+
// A full-account token re-mints both and marks b default.
|
|
83
|
+
const merged = mergeRedeemedSites(existing, [
|
|
84
|
+
tokenSite('b', 'https://b.example.com', { default: true }),
|
|
85
|
+
tokenSite('a', 'https://a.example.com'),
|
|
86
|
+
]);
|
|
87
|
+
assert.equal(merged.filter((s) => s.default === true).length, 1, 'exactly one default must survive the merge');
|
|
88
|
+
assert.equal(merged.find((s) => s.default === true)?.url, 'https://b.example.com', "the just-redeemed token's default wins");
|
|
89
|
+
assert.equal(merged.find((s) => s.url === 'https://a.example.com')?.forceRestRoute, true);
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=0e6bd33c-redeem-preserves-per-site-settings.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0e6bd33c-redeem-preserves-per-site-settings.test.js","sourceRoot":"","sources":["../../src/__tests__/0e6bd33c-redeem-preserves-per-site-settings.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket 139f7353 — the PUT-blocked-host fallback never reached the ~25
|
|
3
|
+
* dedicated client methods that call `client.put()` directly.
|
|
4
|
+
*
|
|
5
|
+
* Two earlier tickets fixed this in two places: e2d884cb wired
|
|
6
|
+
* `putWithPostFallback` into updatePost/updatePage/updateCustomPost, and
|
|
7
|
+
* 2b3a706b wired it into the shared `callRestV1`/`callRestV2` callers. Both
|
|
8
|
+
* left the dedicated methods alone. On a host whose edge blocks PUT (reported
|
|
9
|
+
* on Kinsta + Cloudflare, where `respira_diagnose_connection` shows
|
|
10
|
+
* `write_method_probe.put_status` 404/405) that produced a very specific
|
|
11
|
+
* shape of broken: `respira_create_menu_item` worked, because creating is a
|
|
12
|
+
* POST, and `respira_update_menu_item` returned 405, so a menu could be built
|
|
13
|
+
* and then never reordered.
|
|
14
|
+
*
|
|
15
|
+
* `respira_update_menu_item` is the one that got reported. It is not special:
|
|
16
|
+
* every menu, media, user, comment, term, WooCommerce and ACF update method
|
|
17
|
+
* had the identical gap.
|
|
18
|
+
*
|
|
19
|
+
* The fallback is safe here for the same reason it is safe for posts and
|
|
20
|
+
* pages: the plugin registers all of these routes with
|
|
21
|
+
* `WP_REST_Server::EDITABLE`, which is `'POST, PUT, PATCH'`, so the fallback
|
|
22
|
+
* POST lands on the identical handler. Verified against the route table in
|
|
23
|
+
* wordpress-plugin/respira-for-wordpress/includes/class-respira-api.php.
|
|
24
|
+
*
|
|
25
|
+
* A real HTTP server, not a mocked adapter, so the whole interceptor chain
|
|
26
|
+
* runs — including the codedError() step that strips `.response` and made an
|
|
27
|
+
* earlier status-only version of this predicate a no-op.
|
|
28
|
+
*/
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=139f7353-put-fallback-dedicated-methods.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"139f7353-put-fallback-dedicated-methods.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/139f7353-put-fallback-dedicated-methods.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket 139f7353 — the PUT-blocked-host fallback never reached the ~25
|
|
3
|
+
* dedicated client methods that call `client.put()` directly.
|
|
4
|
+
*
|
|
5
|
+
* Two earlier tickets fixed this in two places: e2d884cb wired
|
|
6
|
+
* `putWithPostFallback` into updatePost/updatePage/updateCustomPost, and
|
|
7
|
+
* 2b3a706b wired it into the shared `callRestV1`/`callRestV2` callers. Both
|
|
8
|
+
* left the dedicated methods alone. On a host whose edge blocks PUT (reported
|
|
9
|
+
* on Kinsta + Cloudflare, where `respira_diagnose_connection` shows
|
|
10
|
+
* `write_method_probe.put_status` 404/405) that produced a very specific
|
|
11
|
+
* shape of broken: `respira_create_menu_item` worked, because creating is a
|
|
12
|
+
* POST, and `respira_update_menu_item` returned 405, so a menu could be built
|
|
13
|
+
* and then never reordered.
|
|
14
|
+
*
|
|
15
|
+
* `respira_update_menu_item` is the one that got reported. It is not special:
|
|
16
|
+
* every menu, media, user, comment, term, WooCommerce and ACF update method
|
|
17
|
+
* had the identical gap.
|
|
18
|
+
*
|
|
19
|
+
* The fallback is safe here for the same reason it is safe for posts and
|
|
20
|
+
* pages: the plugin registers all of these routes with
|
|
21
|
+
* `WP_REST_Server::EDITABLE`, which is `'POST, PUT, PATCH'`, so the fallback
|
|
22
|
+
* POST lands on the identical handler. Verified against the route table in
|
|
23
|
+
* wordpress-plugin/respira-for-wordpress/includes/class-respira-api.php.
|
|
24
|
+
*
|
|
25
|
+
* A real HTTP server, not a mocked adapter, so the whole interceptor chain
|
|
26
|
+
* runs — including the codedError() step that strips `.response` and made an
|
|
27
|
+
* earlier status-only version of this predicate a no-op.
|
|
28
|
+
*/
|
|
29
|
+
import { test, after } from 'node:test';
|
|
30
|
+
import assert from 'node:assert/strict';
|
|
31
|
+
import http from 'node:http';
|
|
32
|
+
import { WordPressClient, ORIGINAL_METHOD_HEADER, isRetryableAsPost } from '../wordpress-client.js';
|
|
33
|
+
/**
|
|
34
|
+
* The second half of the same ticket. PUT_FALLBACK_STATUSES has said
|
|
35
|
+
* {403, 404, 405} since 2b3a706b, but `handleError` rebuilds every non-2xx
|
|
36
|
+
* through `codedError`, which drops `.response`. So the status check in
|
|
37
|
+
* `isRetryableAsPost` could never fire on a real client error, and the
|
|
38
|
+
* name-based check that patched around that was hardcoded to 403 alone.
|
|
39
|
+
* A host that answers PUT with 405 and an HTML page — which is what the
|
|
40
|
+
* reporter's edge does — was therefore never retried, even at the call sites
|
|
41
|
+
* where the fallback WAS already wired in.
|
|
42
|
+
*/
|
|
43
|
+
test('an HTML 405 from the edge is retryable as POST, not just an HTML 403', () => {
|
|
44
|
+
assert.equal(isRetryableAsPost({ name: 'http_403_non_wordpress' }), true);
|
|
45
|
+
assert.equal(isRetryableAsPost({ name: 'http_405_non_wordpress' }), true, '405 is the reported case');
|
|
46
|
+
assert.equal(isRetryableAsPost({ name: 'http_404_non_wordpress' }), true, '404 is the other reported case');
|
|
47
|
+
// A status raised BY WordPress keeps its WP_Error code and stays a decision.
|
|
48
|
+
assert.equal(isRetryableAsPost({ name: 'rest_forbidden' }), false);
|
|
49
|
+
assert.equal(isRetryableAsPost({ name: 'http_500_non_wordpress' }), false);
|
|
50
|
+
assert.equal(isRetryableAsPost({ name: 'http_401_non_wordpress' }), false);
|
|
51
|
+
});
|
|
52
|
+
const servers = [];
|
|
53
|
+
after(() => { for (const s of servers)
|
|
54
|
+
s.close(); });
|
|
55
|
+
/**
|
|
56
|
+
* A host that answers 405 Method Not Allowed to PUT before WordPress runs
|
|
57
|
+
* (Cloudflare / Kinsta edge rule on the verb) and 200 to POST on the same
|
|
58
|
+
* path. The 405 body is HTML, like a real edge rejection, so the client
|
|
59
|
+
* cannot mistake it for a WordPress decision.
|
|
60
|
+
*/
|
|
61
|
+
async function startPutBlockedSite() {
|
|
62
|
+
const hits = [];
|
|
63
|
+
const server = http.createServer((req, res) => {
|
|
64
|
+
hits.push({
|
|
65
|
+
method: req.method || '',
|
|
66
|
+
url: req.url || '',
|
|
67
|
+
idempotencyKey: req.headers['idempotency-key'] || null,
|
|
68
|
+
originalMethod: req.headers[ORIGINAL_METHOD_HEADER.toLowerCase()] || null,
|
|
69
|
+
});
|
|
70
|
+
if (req.method === 'PUT') {
|
|
71
|
+
res.writeHead(405, { 'Content-Type': 'text/html', Allow: 'GET, POST, HEAD' });
|
|
72
|
+
res.end('<!DOCTYPE html><html><head><title>405 Not Allowed</title></head><body>405</body></html>');
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (req.method === 'POST') {
|
|
76
|
+
let body = '';
|
|
77
|
+
req.on('data', (c) => { body += c; });
|
|
78
|
+
req.on('end', () => {
|
|
79
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
80
|
+
res.end(JSON.stringify({ success: true, via: 'POST', echo: body ? JSON.parse(body) : null }));
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
85
|
+
res.end(JSON.stringify({ ok: true }));
|
|
86
|
+
});
|
|
87
|
+
servers.push(server);
|
|
88
|
+
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
|
|
89
|
+
const { port } = server.address();
|
|
90
|
+
const client = new WordPressClient({
|
|
91
|
+
id: 'blocked',
|
|
92
|
+
name: 'blocked',
|
|
93
|
+
url: `http://127.0.0.1:${port}`,
|
|
94
|
+
apiKey: `respira_site_${'x'.repeat(24)}`,
|
|
95
|
+
});
|
|
96
|
+
return { client, hits };
|
|
97
|
+
}
|
|
98
|
+
test('update_menu_item survives a host that answers 405 to PUT', async () => {
|
|
99
|
+
const { client, hits } = await startPutBlockedSite();
|
|
100
|
+
const result = await client.updateMenuItem(42, { position: 2 });
|
|
101
|
+
assert.equal(result.success, true, 'the reorder must actually land, not surface a 405');
|
|
102
|
+
assert.deepEqual(hits.map((h) => h.method), ['PUT', 'POST'], 'exactly one PUT then exactly one POST');
|
|
103
|
+
assert.equal(hits[1].url, '/wp-json/respira/v1/menus/items/42');
|
|
104
|
+
assert.equal(hits[1].originalMethod, 'PUT', 'the fallback POST must declare the verb it replaces');
|
|
105
|
+
assert.equal(hits[0].idempotencyKey, hits[1].idempotencyKey, 'both attempts must share one Idempotency-Key or the plugin cannot dedupe them');
|
|
106
|
+
assert.ok(hits[0].idempotencyKey, 'an idempotency key must be present at all');
|
|
107
|
+
});
|
|
108
|
+
/**
|
|
109
|
+
* update_menu_item is the reported one. These are the sibling methods that had
|
|
110
|
+
* the identical gap — all of them EDITABLE routes, so all of them fixable the
|
|
111
|
+
* same way. Named individually so a future regression names the tool it broke.
|
|
112
|
+
*/
|
|
113
|
+
const SIBLINGS = [
|
|
114
|
+
['update_menu', (c) => c.updateMenu(7, { name: 'Main' }), '/wp-json/respira/v1/menus/7'],
|
|
115
|
+
['assign_menu_location', (c) => c.assignMenuToLocation('primary', 7), '/wp-json/respira/v1/menus/locations/primary'],
|
|
116
|
+
['update_media', (c) => c.updateMedia(3, { alt: 'a' }), '/wp-json/respira/v1/media/3'],
|
|
117
|
+
['update_media_batch', (c) => c.updateMediaBatch([{ id: 3, alt: 'a' }]), '/wp-json/respira/v1/media/batch'],
|
|
118
|
+
['update_user', (c) => c.updateUser(5, { display_name: 'A' }), '/wp-json/respira/v1/users/5'],
|
|
119
|
+
['update_comment', (c) => c.updateComment(9, { content: 'x' }), '/wp-json/respira/v1/comments/9'],
|
|
120
|
+
['update_term', (c) => c.updateTerm('category', 4, { name: 'n' }), '/wp-json/respira/v1/taxonomies/category/terms/4'],
|
|
121
|
+
];
|
|
122
|
+
for (const [label, call, expectedPath] of SIBLINGS) {
|
|
123
|
+
test(`${label} survives a host that answers 405 to PUT`, async () => {
|
|
124
|
+
const { client, hits } = await startPutBlockedSite();
|
|
125
|
+
const result = await call(client);
|
|
126
|
+
assert.equal(result.success, true, `${label} must fall back to POST`);
|
|
127
|
+
assert.deepEqual(hits.map((h) => h.method), ['PUT', 'POST']);
|
|
128
|
+
assert.equal(hits[1].url, expectedPath);
|
|
129
|
+
assert.equal(hits[1].originalMethod, 'PUT');
|
|
130
|
+
assert.equal(hits[0].idempotencyKey, hits[1].idempotencyKey);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
test('the ACF dispatcher falls back too', async () => {
|
|
134
|
+
const { client, hits } = await startPutBlockedSite();
|
|
135
|
+
const result = await client.dispatchAcfTool('respira_acf_update_field', {
|
|
136
|
+
post_id: 12,
|
|
137
|
+
field_key: 'field_1',
|
|
138
|
+
value: 'x',
|
|
139
|
+
});
|
|
140
|
+
assert.equal(result.success, true);
|
|
141
|
+
assert.deepEqual(hits.map((h) => h.method), ['PUT', 'POST']);
|
|
142
|
+
assert.equal(hits[1].originalMethod, 'PUT');
|
|
143
|
+
});
|
|
144
|
+
test('a WordPress-issued 405 on a POST is not retried into a loop', async () => {
|
|
145
|
+
// Guard against the fix turning one failed call into an unbounded ladder:
|
|
146
|
+
// the fallback is exactly one POST, and a POST that fails is final.
|
|
147
|
+
const hits = [];
|
|
148
|
+
const server = http.createServer((req, res) => {
|
|
149
|
+
hits.push(req.method || '');
|
|
150
|
+
res.writeHead(405, { 'Content-Type': 'text/html' });
|
|
151
|
+
res.end('<!DOCTYPE html><html><head><title>405</title></head><body>405</body></html>');
|
|
152
|
+
});
|
|
153
|
+
servers.push(server);
|
|
154
|
+
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
|
|
155
|
+
const { port } = server.address();
|
|
156
|
+
const client = new WordPressClient({
|
|
157
|
+
id: 'x', name: 'x', url: `http://127.0.0.1:${port}`, apiKey: `respira_site_${'x'.repeat(24)}`,
|
|
158
|
+
});
|
|
159
|
+
await assert.rejects(() => client.updateMenuItem(1, { position: 1 }));
|
|
160
|
+
assert.deepEqual(hits, ['PUT', 'POST'], 'one PUT, one POST, then stop');
|
|
161
|
+
});
|
|
162
|
+
//# sourceMappingURL=139f7353-put-fallback-dedicated-methods.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"139f7353-put-fallback-dedicated-methods.test.js","sourceRoot":"","sources":["../../src/__tests__/139f7353-put-fallback-dedicated-methods.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"44fcf6b5-basic-auth-is-not-a-blocked-verb.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/44fcf6b5-basic-auth-is-not-a-blocked-verb.test.ts"],"names":[],"mappings":""}
|