webcake-storefront-mcp 1.15.0 → 1.15.1
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/builder/bindings.js
CHANGED
|
@@ -202,6 +202,8 @@ export function normalizeBindings(bindings) {
|
|
|
202
202
|
if (!Array.isArray(bindings))
|
|
203
203
|
return bindings;
|
|
204
204
|
return bindings.map((b) => {
|
|
205
|
+
if (typeof b === "string")
|
|
206
|
+
return makeBinding(b); // bare "name::field" target
|
|
205
207
|
if (!b || typeof b !== "object")
|
|
206
208
|
return b;
|
|
207
209
|
if (b.id && b.name)
|
package/dist/builder/catalog.js
CHANGED
|
@@ -166,7 +166,7 @@ export function buildElement(type, opts = {}) {
|
|
|
166
166
|
if (Array.isArray(node.bindings) && node.bindings.length)
|
|
167
167
|
node.bindings = normalizeBindings(node.bindings);
|
|
168
168
|
if (Array.isArray(node.events) && node.events.length)
|
|
169
|
-
node.events = normalizeEvents(node.events);
|
|
169
|
+
node.events = normalizeEvents(node.events, node.type);
|
|
170
170
|
return node;
|
|
171
171
|
}
|
|
172
172
|
export function isKnownType(type) {
|
package/dist/builder/events.js
CHANGED
|
@@ -80,25 +80,45 @@ export function isKnownTrigger(name) {
|
|
|
80
80
|
export function getEventAction(action) {
|
|
81
81
|
return ACTION_BY_NAME[action];
|
|
82
82
|
}
|
|
83
|
+
// Element types whose events only fire on a specific trigger — mirrors builderx_spa
|
|
84
|
+
// components/editor/traits/Events.vue `addEvent()`. For these the element-type trigger
|
|
85
|
+
// is the right default (a click handler on a form never fires); for everything else the
|
|
86
|
+
// action's usual trigger (or "click") wins.
|
|
87
|
+
const SPECIAL_EVENT_TRIGGER = {
|
|
88
|
+
form: "success",
|
|
89
|
+
swiper: "tab",
|
|
90
|
+
popup: "hide",
|
|
91
|
+
"input-search": "onenter",
|
|
92
|
+
"submit-button": "hover",
|
|
93
|
+
};
|
|
94
|
+
/** The trigger the builder defaults to for a given element type, if it is a special one. */
|
|
95
|
+
export function defaultTriggerForType(type) {
|
|
96
|
+
return type ? SPECIAL_EVENT_TRIGGER[type] : undefined;
|
|
97
|
+
}
|
|
83
98
|
/**
|
|
84
99
|
* Mint a structurally-valid event object. Pass at least `action`; extra action-specific
|
|
85
100
|
* fields are merged verbatim. The id and a sensible eventName are filled in.
|
|
101
|
+
* eventName precedence (mirrors the editor): explicit > element-type default
|
|
102
|
+
* (form→success, swiper→tab, popup→hide, input-search→onenter, submit-button→hover) >
|
|
103
|
+
* the action's usual trigger > "click".
|
|
86
104
|
* makeEvent({ action: "scroll_to", scroll_to_id: "SECTION-x" })
|
|
87
|
-
* makeEvent({ action: "
|
|
105
|
+
* makeEvent({ action: "open_page", open_page_id: "…" }, "form") // eventName → "success"
|
|
88
106
|
*/
|
|
89
|
-
export function makeEvent(spec) {
|
|
107
|
+
export function makeEvent(spec, elementType) {
|
|
90
108
|
if (!spec || typeof spec !== "object")
|
|
91
109
|
throw new Error("Event spec must be an object with at least an `action`.");
|
|
92
110
|
const def = spec.action ? ACTION_BY_NAME[spec.action] : undefined;
|
|
93
|
-
const eventName = spec.eventName || (def ? def.trigger : "click");
|
|
111
|
+
const eventName = spec.eventName || defaultTriggerForType(elementType) || (def ? def.trigger : "click");
|
|
94
112
|
const { eventName: _e, action: _a, id: _id, ...rest } = spec;
|
|
95
113
|
return { id: spec.id || `EVENT-${randomString(6)}`, eventName, ...(spec.action ? { action: spec.action } : {}), ...rest };
|
|
96
114
|
}
|
|
97
|
-
/** Ensure every event in an array has an id + an eventName (mint where missing).
|
|
98
|
-
|
|
115
|
+
/** Ensure every event in an array has an id + an eventName (mint where missing).
|
|
116
|
+
* Pass the owning element's type so special types get the right default trigger.
|
|
117
|
+
* Round-trip safe: events that already carry id/eventName are preserved verbatim. */
|
|
118
|
+
export function normalizeEvents(events, elementType) {
|
|
99
119
|
if (!Array.isArray(events))
|
|
100
120
|
return events;
|
|
101
|
-
return events.map((e) => (e && typeof e === "object" ? makeEvent(e) : e));
|
|
121
|
+
return events.map((e) => (e && typeof e === "object" ? makeEvent(e, elementType) : e));
|
|
102
122
|
}
|
|
103
123
|
/** Validate one element's events against the catalog + the set of ids present in the page. */
|
|
104
124
|
export function validateEvents(node, allIds) {
|
package/dist/changelog.json
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"v": "1.15.1",
|
|
4
|
+
"d": "24/06/2026",
|
|
5
|
+
"type": "Fixed",
|
|
6
|
+
"en": "update_page_element, update_page_elements, update_global_source_element, and update_global_source_elements now normalize events and bindings arrays…",
|
|
7
|
+
"vi": "update_page_element, update_page_elements, update_global_source_element và update_global_source_elements nay chuẩn hóa mảng events và bindings khi…"
|
|
8
|
+
},
|
|
2
9
|
{
|
|
3
10
|
"v": "1.15.0",
|
|
4
11
|
"d": "24/06/2026",
|
|
@@ -33,12 +40,5 @@
|
|
|
33
40
|
"type": "Added",
|
|
34
41
|
"en": "New update_product tool updates an existing product's name, description, images, category_ids, is_published flag, or variations (price/stock/SKU per…",
|
|
35
42
|
"vi": "Tool mới update_product cập nhật name, description, images, category_ids, cờ is_published hoặc variations (giá/tồn kho/SKU theo từng biến thể) của…"
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"v": "1.11.1",
|
|
39
|
-
"d": "24/06/2026",
|
|
40
|
-
"type": "Fixed",
|
|
41
|
-
"en": "create_site_from_template now calls the dedicated import_store_to_theme API instead of the generic site-duplicate endpoint, correctly cloning the…",
|
|
42
|
-
"vi": "create_site_from_template nay gọi đúng API import_store_to_theme thay vì endpoint nhân bản site thông thường, giúp clone đầy đủ các trang, global…"
|
|
43
43
|
}
|
|
44
44
|
]
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { getConfirmMode } from "./context.js";
|
|
3
|
+
import { normalizeEvents } from "../builder/events.js";
|
|
4
|
+
import { normalizeBindings } from "../builder/bindings.js";
|
|
3
5
|
/**
|
|
4
6
|
* Global Sources tools — manage site-wide components: cart, popup, overview, etc.
|
|
5
7
|
*
|
|
@@ -151,10 +153,11 @@ function applyNodeUpdates(node, updates) {
|
|
|
151
153
|
node.config = { ...(node.config || {}), ...updates.config };
|
|
152
154
|
if (updates.specials)
|
|
153
155
|
node.specials = { ...(node.specials || {}), ...updates.specials };
|
|
156
|
+
// Normalize so updated events/bindings get a valid id + eventName (renderer needs it).
|
|
154
157
|
if (updates.events !== undefined)
|
|
155
|
-
node.events = updates.events;
|
|
158
|
+
node.events = normalizeEvents(updates.events, node.type);
|
|
156
159
|
if (updates.bindings !== undefined)
|
|
157
|
-
node.bindings = updates.bindings;
|
|
160
|
+
node.bindings = normalizeBindings(updates.bindings);
|
|
158
161
|
if (updates.responsive) {
|
|
159
162
|
for (const [bp, val] of Object.entries(updates.responsive)) {
|
|
160
163
|
if (/^bp\d+$/.test(bp)) {
|
|
@@ -432,7 +435,8 @@ STEP 1: Call with dry_run=true (default) → returns diff of what will change.
|
|
|
432
435
|
STEP 2: Show the diff to the user and ask for confirmation. NEVER proceed without explicit user approval.
|
|
433
436
|
STEP 3: Only after user confirms, call again with dry_run=false to apply.
|
|
434
437
|
IMPORTANT: You MUST show the diff to the user and get explicit "yes/ok/confirm" before calling with dry_run=false. Skipping confirmation risks data loss.
|
|
435
|
-
Merge rules: style/config/specials = shallow merge,
|
|
438
|
+
Merge rules: style/config/specials = shallow merge, responsive = merge by bp key.
|
|
439
|
+
events/bindings = REPLACE the whole array — pass the COMPLETE list (read it first); entries are auto-normalized (id + eventName filled in).`, {
|
|
436
440
|
global_source_id: z.string().describe("Global source ID"),
|
|
437
441
|
element_id: z.string().describe("Element ID to update (e.g. 'TEXT-3', 'BUTTON-1')"),
|
|
438
442
|
component: z.string().optional().describe('Component hint for faster lookup'),
|
package/dist/tools/pages.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { CUSTOM_CODE_GUIDE } from "../guides.js";
|
|
3
3
|
import { getConfirmMode } from "./context.js";
|
|
4
|
+
import { normalizeEvents } from "../builder/events.js";
|
|
5
|
+
import { normalizeBindings } from "../builder/bindings.js";
|
|
4
6
|
/**
|
|
5
7
|
* Page source utilities.
|
|
6
8
|
*
|
|
@@ -145,10 +147,13 @@ function applyNodeUpdates(node, updates) {
|
|
|
145
147
|
node.config = { ...(node.config || {}), ...updates.config };
|
|
146
148
|
if (updates.specials)
|
|
147
149
|
node.specials = { ...(node.specials || {}), ...updates.specials };
|
|
150
|
+
// Normalize so updated events/bindings carry a valid id + eventName (and the right
|
|
151
|
+
// element-type default trigger) — the storefront renderer won't dispatch an event with
|
|
152
|
+
// no eventName. Round-trip safe: already-formed entries pass through unchanged.
|
|
148
153
|
if (updates.events !== undefined)
|
|
149
|
-
node.events = updates.events;
|
|
154
|
+
node.events = normalizeEvents(updates.events, node.type);
|
|
150
155
|
if (updates.bindings !== undefined)
|
|
151
|
-
node.bindings = updates.bindings;
|
|
156
|
+
node.bindings = normalizeBindings(updates.bindings);
|
|
152
157
|
// Responsive breakpoints (bp1, bp2, ...)
|
|
153
158
|
if (updates.responsive) {
|
|
154
159
|
for (const [bp, val] of Object.entries(updates.responsive)) {
|
|
@@ -460,7 +465,8 @@ STEP 1: Call with dry_run=true (default) → returns diff of what will change.
|
|
|
460
465
|
STEP 2: Show the diff to the user and ask for confirmation. NEVER proceed without explicit user approval.
|
|
461
466
|
STEP 3: Only after user confirms, call again with dry_run=false to apply.
|
|
462
467
|
IMPORTANT: You MUST show the diff to the user and get explicit "yes/ok/confirm" before calling with dry_run=false. Skipping confirmation risks data loss.
|
|
463
|
-
Merge rules: style/config/specials = shallow merge,
|
|
468
|
+
Merge rules: style/config/specials = shallow merge, responsive = merge by bp key.
|
|
469
|
+
events/bindings = REPLACE the whole array — pass the COMPLETE list (read it first with get_page_element so you don't drop the others); entries are auto-normalized (id + eventName filled in, so you can pass just { action, ...fields } / { target }).`, {
|
|
464
470
|
page_id: z.string().describe("Page ID"),
|
|
465
471
|
element_id: z.string().describe("Element ID to update (e.g. 'TEXT-3', 'BUTTON-1')"),
|
|
466
472
|
dry_run: z.boolean().optional().describe("Preview only (true) or apply changes (false). Defaults to confirm_mode setting. Use toggle_confirm_mode to change default."),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webcake-storefront-mcp",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.1",
|
|
4
4
|
"description": "MCP server for the WebCake/StoreCake storefront builder — page CRUD, page authoring, products, orders, and more",
|
|
5
5
|
"mcpName": "io.github.vuluu2k/webcake-storefront-mcp",
|
|
6
6
|
"license": "MIT",
|