@appaflytech/zeyrek-ai-mcp 0.0.13 → 0.0.14
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.
|
@@ -2041,32 +2041,76 @@ export function orphanedFlowPlan(schema, pageEvents, ops) {
|
|
|
2041
2041
|
if (op.op !== 'set_event' && op.op !== 'remove_event')
|
|
2042
2042
|
continue;
|
|
2043
2043
|
const eventName = String(op.event ?? '');
|
|
2044
|
+
const eventValue = typeof op.eventValue === 'string' ? op.eventValue : undefined;
|
|
2045
|
+
const boundTo = (events) => asObjects(events)
|
|
2046
|
+
.filter(event => String(event.name ?? '') === eventName && typeof event.value === 'string' && event.value !== '');
|
|
2047
|
+
// Bir olaya birden fazla akış bağlı olabilir. Değersiz `remove_event` o durumda platformda
|
|
2048
|
+
// `ambiguous-event` ile düşer ve hiçbir bağ kalkmaz; değerli olan yalnız o akışı çözer.
|
|
2049
|
+
const removedBy = (named) => eventValue === undefined
|
|
2050
|
+
? (named.length === 1 ? named : [])
|
|
2051
|
+
: named.filter(event => event.value === eventValue);
|
|
2044
2052
|
// `remove_event target:'page'` düğümü değil barındırıcının düzey olaylarını hedefler
|
|
2045
2053
|
// (`PageSchemaMicroOpApplier.PageTarget`); düğüm aramasına düşseydi plan boş kalır ve yalnız
|
|
2046
2054
|
// oraya bağlı akış kapıdan geçip kalıcı silinirdi. Düzey olayı olmayan widget'ta applier da
|
|
2047
2055
|
// düğüm aramasına düşer.
|
|
2048
2056
|
if (op.op === 'remove_event' && target === 'page' && Array.isArray(pageEvents)) {
|
|
2049
2057
|
const hostEvents = asObjects(pageEvents);
|
|
2050
|
-
const removed =
|
|
2051
|
-
|
|
2052
|
-
continue;
|
|
2053
|
-
const surviving = new Set(hostEvents.filter(event => event !== removed && typeof event.value === 'string').map(event => String(event.value)));
|
|
2058
|
+
const removed = removedBy(boundTo(hostEvents));
|
|
2059
|
+
const surviving = new Set(hostEvents.filter(event => !removed.includes(event) && typeof event.value === 'string').map(event => String(event.value)));
|
|
2054
2060
|
collectFlowRefsExcept(nodes, '', surviving);
|
|
2055
|
-
|
|
2056
|
-
|
|
2061
|
+
const flowIds = [...new Set(removed.map(event => String(event.value)))].filter(flowId => !surviving.has(flowId));
|
|
2062
|
+
if (flowIds.length > 0)
|
|
2063
|
+
plan.push({ target, op: 'remove_event', flowIds });
|
|
2057
2064
|
continue;
|
|
2058
2065
|
}
|
|
2059
2066
|
const node = findNodeByElementId(nodes, target);
|
|
2060
|
-
const
|
|
2061
|
-
|
|
2062
|
-
|
|
2067
|
+
const named = boundTo(node?.events);
|
|
2068
|
+
// `set_event` adın BÜTÜN bağlarını tek kayda indirir; yeni değerden farklı her akış bağını kaybeder.
|
|
2069
|
+
const losing = op.op === 'set_event' ? named.filter(event => event.value !== eventValue) : removedBy(named);
|
|
2070
|
+
if (losing.length === 0)
|
|
2063
2071
|
continue;
|
|
2064
2072
|
const surviving = survivingRefs(target, eventName);
|
|
2065
|
-
|
|
2066
|
-
|
|
2073
|
+
for (const event of named) {
|
|
2074
|
+
if (!losing.includes(event))
|
|
2075
|
+
surviving.add(String(event.value));
|
|
2076
|
+
}
|
|
2077
|
+
const flowIds = [...new Set(losing.map(event => String(event.value)))].filter(flowId => !surviving.has(flowId));
|
|
2078
|
+
if (flowIds.length > 0)
|
|
2079
|
+
plan.push({ target, op: String(op.op), flowIds });
|
|
2067
2080
|
}
|
|
2068
2081
|
return plan;
|
|
2069
2082
|
}
|
|
2083
|
+
/**
|
|
2084
|
+
* PAGE-034 — dolu bir olaya farklı akışla `set_event` gelmesi. `set_event` adın bütün bağlarını
|
|
2085
|
+
* TEK kayda indirir, yani önceki akış bağını sessizce kaybeder; akış başka yerden de
|
|
2086
|
+
* referanslıysa `orphanedFlowPlan` da susar ve kayıp hiç görünmez (maddelerim 4: makale önerisi
|
|
2087
|
+
* akışı, akıllı öneri bağlanınca çalışmaz oldu). Olaya ikinci akış eklemek `add_event`'tir; bilerek
|
|
2088
|
+
* değiştirmek için op'a `replaceBoundFlows: true` verilir. Okunan ağaçta olmayan hedef denetlenmez.
|
|
2089
|
+
*/
|
|
2090
|
+
export function boundEventOps(schema, ops) {
|
|
2091
|
+
const nodes = asObjects(schema);
|
|
2092
|
+
return asObjects(ops)
|
|
2093
|
+
.filter(op => op.op === 'set_event' && op.replaceBoundFlows !== true)
|
|
2094
|
+
.flatMap(op => {
|
|
2095
|
+
const target = String(op.target ?? '');
|
|
2096
|
+
const event = String(op.event ?? '');
|
|
2097
|
+
const eventValue = typeof op.eventValue === 'string' ? op.eventValue : '';
|
|
2098
|
+
const bound = asObjects(findNodeByElementId(nodes, target)?.events)
|
|
2099
|
+
.filter(entry => String(entry.name ?? '') === event && typeof entry.value === 'string' && entry.value !== '')
|
|
2100
|
+
.map(entry => String(entry.value));
|
|
2101
|
+
const replaced = [...new Set(bound)].filter(flowId => flowId !== eventValue);
|
|
2102
|
+
if (replaced.length === 0)
|
|
2103
|
+
return [];
|
|
2104
|
+
return [`PAGE-034: '${target}' komponentinin '${event}' olayına zaten bağlı akış var (${replaced.join(', ')}). set_event olayın BÜTÜN bağlarını tek akışa indirir ve bu akışlar olay tetiklenince artık çalışmaz. `
|
|
2105
|
+
+ `Olaya bir akış daha eklemek için { op: 'add_event', target: '${target}', event: '${event}', eventValue: '${eventValue}' } kullanın — bağlı akışların hepsi paralel koşar. `
|
|
2106
|
+
+ `Mevcut bağı bilerek değiştirmek istiyorsanız aynı op'a replaceBoundFlows: true ekleyin.`];
|
|
2107
|
+
});
|
|
2108
|
+
}
|
|
2109
|
+
/** Gateway'e ait op alanları platforma gitmez. */
|
|
2110
|
+
export function stripGatewayEventFields(ops) {
|
|
2111
|
+
for (const op of ops)
|
|
2112
|
+
delete op.replaceBoundFlows;
|
|
2113
|
+
}
|
|
2070
2114
|
export function orphanedFlowMessage(plan) {
|
|
2071
2115
|
const lines = plan.map(entry => `'${entry.target}' (${entry.op}) → ${entry.flowIds.join(', ')}`);
|
|
2072
2116
|
return `İstek gönderilmedi: bu yama ${plan.reduce((total, entry) => total + entry.flowIds.length, 0)} akışı sayfada referanssız bırakıyor ve platform referanssız akışı KALICI siler — ${lines.join(' · ')}. `
|
|
@@ -167,11 +167,23 @@ ve `datatable` yalnız `mount` yayar (`datatable`'ınki bilinçli — Kural 1e).
|
|
|
167
167
|
sessizce ölü kalır** — önce `component_get`. Gateway `set_event`'i katalogla karşılaştırır ve
|
|
168
168
|
uymayan adı **PAGE-008** ile istek gitmeden reddeder.
|
|
169
169
|
|
|
170
|
+
**Bir olaya birden fazla akış bağlanabilir — ikinciyi `add_event` ile ekle.** `set_event` olayın
|
|
171
|
+
BÜTÜN bağlarını tek akışa indirir: başlık alanının `change` olayına makale önerisi bağlıyken akıllı
|
|
172
|
+
öneriyi `set_event` ile bağlamak makale önerisini devre dışı bırakır. Gateway bunu **PAGE-034** ile
|
|
173
|
+
istek gitmeden reddeder. Doğru op `{ "op": "add_event", "target": "<elementId>", "event": "change",
|
|
174
|
+
"eventValue": "<ikinci flow id>" }`'dir. Olay tetiklenince bağlı akışların hepsi **paralel ve
|
|
175
|
+
birbirinden bağımsız** koşar: biri hata verirse diğeri etkilenmez, **sıra garantisi yoktur**. Biri
|
|
176
|
+
diğerinin sonucunu bekliyorsa ya da ikisi aynı değişkene/prop'a yazıyorsa ayrı bağ değil,
|
|
177
|
+
`flow-trigger` adımıyla zincir kur (Kural 1c). Mevcut bağı bilerek değiştirmek için `set_event`
|
|
178
|
+
op'una `replaceBoundFlows: true` ekle. **Mobil runtime yalnız ilk akışı koşar** — mobil
|
|
179
|
+
uygulamada olay başına tek akış bağla.
|
|
180
|
+
|
|
170
181
|
**Olay KALDIRMAK için `remove_event` kullan.** Platformun `set_event` micro-op'u olay silemez:
|
|
171
182
|
`eventValue: null` verildiğinde kayıt `{ name: 'click' }` olarak (değersiz) kalır, diziden
|
|
172
183
|
çıkmaz — şemada ölü bağ artığı bırakır. `{ "op": "remove_event", "target": "<elementId>",
|
|
173
184
|
"event": "click" }` platformun op'udur: olayı diziden çıkarır (yanıtta `removedEvents`); olmayan
|
|
174
|
-
bir olayı kaldırmaya çalışmak `missing-event` ile 422 döner.
|
|
185
|
+
bir olayı kaldırmaya çalışmak `missing-event` ile 422 döner. Olaya birden fazla akış bağlıysa
|
|
186
|
+
kaldırılacak akışı `eventValue` ile ver; vermezsen `ambiguous-event` ile 422 döner. Sayfa düzeyi olaylar için
|
|
175
187
|
`target: "page"`. Referanssız kalan akış silineceği için `allowFlowDeletion` kuralı (G-21) bu op'ta
|
|
176
188
|
da geçerlidir.
|
|
177
189
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { orphanedFlowWarnings, orphanedFlowPlan, orphanedFlowMessage, staleSetterWarnings, normalizeSchemaOps, validationNote, componentDefaultsNote, replacePropNote, flexSizeWarnings, nestedRepeaterNodes, nestedRepeaterMessage, stringStyleNodes, stringStyleWarning, inertFlexPropNodes, inertFlexPropWarning, verticalGapWarnings, withNormalization, FLEX_LAYOUT_PROP_NAMES } from '../knowledge/normalize.js';
|
|
1
|
+
import { orphanedFlowWarnings, orphanedFlowPlan, orphanedFlowMessage, boundEventOps, stripGatewayEventFields, staleSetterWarnings, normalizeSchemaOps, validationNote, componentDefaultsNote, replacePropNote, flexSizeWarnings, nestedRepeaterNodes, nestedRepeaterMessage, stringStyleNodes, stringStyleWarning, inertFlexPropNodes, inertFlexPropWarning, verticalGapWarnings, withNormalization, FLEX_LAYOUT_PROP_NAMES } from '../knowledge/normalize.js';
|
|
2
2
|
import { opsParam, writeViewParam, outlineWriteResponse, unknownEventOps, collectTypes, simulateLayoutOps, removeNodeFromTree, planEventRemovals, planResizes, planPropTypes, assertOpBodies } from './schemaOps.js';
|
|
3
3
|
import { guid, projectParam, environmentParam, updates, microOps } from './common.js';
|
|
4
4
|
import { fetchHost, hostPath } from './screens.js';
|
|
@@ -68,7 +68,10 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
|
|
|
68
68
|
}
|
|
69
69
|
const nodes = (record[spec.tree] ?? []);
|
|
70
70
|
const events = host === 'layout' ? record.events : undefined;
|
|
71
|
-
if (opRecords.some(entry => entry.op === 'set_event')) {
|
|
71
|
+
if (opRecords.some(entry => entry.op === 'set_event' || entry.op === 'add_event')) {
|
|
72
|
+
const bound = boundEventOps(nodes, opRecords);
|
|
73
|
+
if (bound.length > 0)
|
|
74
|
+
throw new PlatformApiError(`PAGE-034 — dolu olaya set_event (istek gönderilmedi): ${bound.join(' · ')}`, 400);
|
|
72
75
|
const typesByElementId = new Map();
|
|
73
76
|
collectTypes(nodes, typesByElementId);
|
|
74
77
|
collectTypes(opRecords.map(entry => entry.component).filter(Boolean), typesByElementId);
|
|
@@ -77,6 +80,7 @@ export function registerDesignSchemaPatchTool(server, platform, host) {
|
|
|
77
80
|
if (unknown.length > 0)
|
|
78
81
|
throw new PlatformApiError(`PAGE-008 — geçersiz olay adı (istek gönderilmedi): ${unknown.join(' · ')}`, 400);
|
|
79
82
|
}
|
|
83
|
+
stripGatewayEventFields(opRecords);
|
|
80
84
|
const deletedFlows = orphanedFlowPlan(nodes, events, [...opRecords, ...removeEventOps]);
|
|
81
85
|
if (deletedFlows.length > 0 && allowFlowDeletion !== true)
|
|
82
86
|
throw new PlatformApiError(orphanedFlowMessage(deletedFlows), 400);
|
package/dist/tools/flows.js
CHANGED
|
@@ -399,7 +399,7 @@ export function registerFlowTools(server, platform) {
|
|
|
399
399
|
outcome: existing === undefined ? 'created' : 'updated',
|
|
400
400
|
flow: { id: writtenFlowId, name, slug, steps: steps.length },
|
|
401
401
|
...(parameterWarnings.length > 0 ? { parameterWarnings } : {}),
|
|
402
|
-
hint: "Akışı bir olaya bağlamak için: page_schema_patch (layout'ta layout_schema_patch, widget'ta component_schema_patch) ops:[{op:'set_event', target:<elementId>, event:'<component_get events listesindeki ad>', eventValue:<flow id>}]. Olay adları komponente özeldir ve 'on' ÖNEKİ ALMAZ (button → 'click', form → 'submit', table → 'mount'/'select'/'sort'…); uydurma ad 200 döner ama bağ sessizce ölü kalır — gateway PAGE-008 ile yakalar."
|
|
402
|
+
hint: "Akışı bir olaya bağlamak için: page_schema_patch (layout'ta layout_schema_patch, widget'ta component_schema_patch) ops:[{op:'set_event', target:<elementId>, event:'<component_get events listesindeki ad>', eventValue:<flow id>}]; olayda zaten akış bağlıysa ikinciyi add_event ile ekleyin (set_event bağlı akışı değiştirir, PAGE-034). Olay adları komponente özeldir ve 'on' ÖNEKİ ALMAZ (button → 'click', form → 'submit', table → 'mount'/'select'/'sort'…); uydurma ad 200 döner ama bağ sessizce ölü kalır — gateway PAGE-008 ile yakalar."
|
|
403
403
|
}, normalized), drops), findings);
|
|
404
404
|
}));
|
|
405
405
|
server.registerTool('flow_update', {
|
package/dist/tools/pages.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { guid, projectParam, environmentParam, pagingParams, readOnly, writes, updates, destructive, microOps, isBranchName } from './common.js';
|
|
2
|
-
import { orphanedFlowWarnings, orphanedFlowPlan, orphanedFlowMessage, staleSetterWarnings, lostSetterTargets, normalizeComponentDefaults, normalizeSchemaOps, schemaOpValidationErrors, codePropTemplateErrors, validationNote, componentDefaultsNote, replacePropNote, ensurePageContainer, retargetRootAdds, rootAddsNote, flexSizeWarnings, spacingLayerWarnings, reorderSchemaBlocks, reorderNote, nestedRepeaterNodes, nestedRepeaterMessage, stringStyleNodes, stringStyleWarning, inertFlexPropNodes, inertFlexPropWarning, FLEX_LAYOUT_PROP_NAMES, resetPageContainerPosition, pageContainerPositionWarning, verticalGapWarnings, flexIndexOrder, flexIndexOrderNote, withNormalization, parseVariableEntries, PAGE_CONTAINER_ELEMENT_ID } from '../knowledge/normalize.js';
|
|
2
|
+
import { orphanedFlowWarnings, orphanedFlowPlan, orphanedFlowMessage, boundEventOps, stripGatewayEventFields, staleSetterWarnings, lostSetterTargets, normalizeComponentDefaults, normalizeSchemaOps, schemaOpValidationErrors, codePropTemplateErrors, validationNote, componentDefaultsNote, replacePropNote, ensurePageContainer, retargetRootAdds, rootAddsNote, flexSizeWarnings, spacingLayerWarnings, reorderSchemaBlocks, reorderNote, nestedRepeaterNodes, nestedRepeaterMessage, stringStyleNodes, stringStyleWarning, inertFlexPropNodes, inertFlexPropWarning, FLEX_LAYOUT_PROP_NAMES, resetPageContainerPosition, pageContainerPositionWarning, verticalGapWarnings, flexIndexOrder, flexIndexOrderNote, withNormalization, parseVariableEntries, PAGE_CONTAINER_ELEMENT_ID } from '../knowledge/normalize.js';
|
|
3
3
|
import { functionSignature } from '../knowledge/functionGuards.js';
|
|
4
4
|
import { fetchHost, pageUpdateBody, schemaParam, eventsParam, unwrap, modeParam, summarize, findNode, flowPath } from './screens.js';
|
|
5
5
|
import { fetchComponentEventNames } from './components.js';
|
|
@@ -67,7 +67,7 @@ async function fetchPage(platform, project, environment, applicationId, pageId)
|
|
|
67
67
|
*/
|
|
68
68
|
export const SERVER_PAGE_OPS = [
|
|
69
69
|
'replace_prop', 'set_binding', 'set_prop_type', 'add_component', 'remove_component', 'move_component', 'reorder', 'set_block',
|
|
70
|
-
'set_appearance', 'set_states', 'set_event', 'remove_event', 'set_validations', 'set_state_binding', 'remove_state_binding', 'batch'
|
|
70
|
+
'set_appearance', 'set_states', 'set_event', 'add_event', 'remove_event', 'set_validations', 'set_state_binding', 'remove_state_binding', 'batch'
|
|
71
71
|
];
|
|
72
72
|
export function registerPageTools(server, platform, injectedScreenshotter, injectedMemory) {
|
|
73
73
|
const config = platform.config;
|
|
@@ -638,10 +638,13 @@ export function registerPageTools(server, platform, injectedScreenshotter, injec
|
|
|
638
638
|
reject('PAGE-016', entry, schemaOpValidationErrors([entry]));
|
|
639
639
|
for (const entry of opRecords)
|
|
640
640
|
reject('PAGE-032', entry, codePropTemplateErrors([entry]));
|
|
641
|
-
if (opRecords.some(entry => entry.op === 'set_event')) {
|
|
641
|
+
if (opRecords.some(entry => entry.op === 'set_event' || entry.op === 'add_event')) {
|
|
642
642
|
const typesByElementId = new Map();
|
|
643
643
|
try {
|
|
644
|
-
|
|
644
|
+
const page = await readPage();
|
|
645
|
+
collectTypes(page.schema, typesByElementId);
|
|
646
|
+
for (const entry of opRecords)
|
|
647
|
+
reject('PAGE-034', entry, boundEventOps(page.schema, [entry]));
|
|
645
648
|
}
|
|
646
649
|
catch {
|
|
647
650
|
typesByElementId.clear();
|
|
@@ -653,6 +656,7 @@ export function registerPageTools(server, platform, injectedScreenshotter, injec
|
|
|
653
656
|
}
|
|
654
657
|
if (rejected.length > 0)
|
|
655
658
|
throw new PlatformApiError(rejectedOpsMessage(rejected), 400);
|
|
659
|
+
stripGatewayEventFields(opRecords);
|
|
656
660
|
const wantsRootAdd = opRecords.some(entry => entry.op === 'add_component' && (entry.parent === undefined || entry.parent === null || entry.parent === 'root'));
|
|
657
661
|
let retargeted = [];
|
|
658
662
|
if (wantsRootAdd) {
|
package/dist/tools/schemaOps.js
CHANGED
|
@@ -24,7 +24,7 @@ export function outlineWriteResponse(response) {
|
|
|
24
24
|
if (Array.isArray(container.appliedPatch))
|
|
25
25
|
container.appliedPatch = outlineAppliedPatch(container.appliedPatch);
|
|
26
26
|
}
|
|
27
|
-
export const opsParam = z.array(z.record(z.unknown())).describe("Micro-op listesi. Op sözlüğü: replace_prop {target, prop, value} (value ham değer, code sarmalı {type: 'code', ref: '{{ … }}'} ya da translation sarmalı {type: 'translation', ref: '<çeviri anahtarı>'} — prop tipini değiştirmek için komponenti silip yeniden EKLEMEYİN, ona yazan setter'ların hedefi silinir (FLOW-018); platform replace_prop'ta expression alanını OKUMAZ — gateway onu code sarmalına çevirir) | set_binding {target, prop, expression: '{{ Page.variables.x }}'} | add_component {parent (üst elementId ya da 'root'), index?, component} | remove_component {target} | move_component {target, parent, index?, position: {x, y}} (index ÇİZİM sırası değildir, runtime çocukları blocks.position'a göre (y, sonra x) çizer. page_schema_patch'te flex kapta gateway index'i görünen sıraya çevirir ve kardeş konumlarını yeniden yazar; ızgara kapta sırayı position.y verir, sona eklemeyen index PAGE-033 uyarısıdır. layout_schema_patch ve component_schema_patch bu çeviriyi YAPMAZ: orada sırayı position.y ile verin) | set_event {target, event, eventValue} | remove_event {target, event} (olayı diziden çıkarır; target: 'page' sayfa düzeyi olaylar. set_event ile eventValue: null olay SİLMEZ, değersiz ölü kayıt bırakır. Olmayan olay 422 missing-event) | set_validations {target, validations: [{type, message, value, isActive}]} (komponentin validation listesini TAMAMEN değiştirir; boş dizi hepsini siler) | set_appearance {target, appearance: {heightType?, widthType?, tooltip?, background?, …}} (kurulu düğümün appearance'ına YALNIZ verilen alanları yazar, gerisini korur; null alanı temizler; bilinmeyen alan unknown-appearance-field ile reddedilir. GÖRÜNÜRLÜK appearance'ta DEĞİLDİR: gizlemek için replace_prop {target, prop: 'isHidden', value: true}, koşul için set_binding {prop: 'isHidden'} — add_component gövdesindeki appearance.isHidden'ı gateway props.isHidden'a taşır) | resize_component {target, size?: {w,h}, appearance?: {widthType,widthString,heightType,heightString}, states?: {isWrapper,isScrollable,isSticky,isDroppable,isFloating,isQuickStack}, breakpoint?: 1024} (gateway adı: platforma set_block {target, breakpoint, size} + set_appearance {target, appearance} + set_states {target, states} olarak gider — o üç op'u doğrudan da gönderebilirsiniz. move_component'e konan size reddedilir. Izgarada blocks[].size, flex'te appearance geçerlidir; ebeveynin düzeni yazılanı etkisiz kılıyorsa PAGE-019 uyarısı çıkar. states bir PROP DEĞİL düğüm alanıdır ve replace_prop onu yazamaz — düğümü silmeden isWrapper bayrağını değiştirmenin yolu budur). set_prop_type {target, prop, propType: 'static'|'code'|'translation', ref?, data?} (replace_prop sarmalıyla aynı sonucu verir ve mevcut data'yı tasarım yedeği olarak taşır. Bu op prop'un TİPİNİ yerinde değiştirir. Taşıyıcı alan tipe göre: static → data, code ve translation → ref (runtime data'yı her turda ezer, anahtar yalnız ref'te yaşar). Eksik taşıyıcı istek gönderilmeden reddedilir; page_schema_validate aynı kararı verir) | reorder {parent ('root' ya da elementId), order: [çocuk elementId'lerinin TAMAMI, yeni sırada]} (yalnız DİZİ sırasını değiştirir; çizim sırası blocks.position'dır — görünen sırayı değiştirmek için konumları set_block/move_component ile de yazın) | set_state_binding {target, binding: {name, expression, targets}} (ada göre ekler/değiştirir) | remove_state_binding {target, name} | batch {gestureId?, label?, ops: [...]} (iç içe batch yok). target = elementId. İstek atomiktir: tek op reddedilirse hiçbiri yazılmaz.");
|
|
27
|
+
export const opsParam = z.array(z.record(z.unknown())).describe("Micro-op listesi. Op sözlüğü: replace_prop {target, prop, value} (value ham değer, code sarmalı {type: 'code', ref: '{{ … }}'} ya da translation sarmalı {type: 'translation', ref: '<çeviri anahtarı>'} — prop tipini değiştirmek için komponenti silip yeniden EKLEMEYİN, ona yazan setter'ların hedefi silinir (FLOW-018); platform replace_prop'ta expression alanını OKUMAZ — gateway onu code sarmalına çevirir) | set_binding {target, prop, expression: '{{ Page.variables.x }}'} | add_component {parent (üst elementId ya da 'root'), index?, component} | remove_component {target} | move_component {target, parent, index?, position: {x, y}} (index ÇİZİM sırası değildir, runtime çocukları blocks.position'a göre (y, sonra x) çizer. page_schema_patch'te flex kapta gateway index'i görünen sıraya çevirir ve kardeş konumlarını yeniden yazar; ızgara kapta sırayı position.y verir, sona eklemeyen index PAGE-033 uyarısıdır. layout_schema_patch ve component_schema_patch bu çeviriyi YAPMAZ: orada sırayı position.y ile verin) | set_event {target, event, eventValue, replaceBoundFlows?} (olayın BÜTÜN bağlarını bu tek akışa indirir; olayda başka akış bağlıysa gateway PAGE-034 ile reddeder — bilerek değiştirmek için replaceBoundFlows: true) | add_event {target, event, eventValue} (olaya bir akış DAHA bağlar; bağlı akışların hepsi paralel ve birbirinden bağımsız koşar, sıra garantisi yoktur — sıra gerekiyorsa flow-trigger. Aynı akış iki kez 422 duplicate-event. Mobil runtime yalnız İLK akışı koşar) | remove_event {target, event, eventValue?} (olayı diziden çıkarır; target: 'page' sayfa düzeyi olaylar. Olaya birden fazla akış bağlıysa eventValue ile hangisi olduğunu verin, yoksa 422 ambiguous-event. set_event ile eventValue: null olay SİLMEZ, değersiz ölü kayıt bırakır. Olmayan olay 422 missing-event) | set_validations {target, validations: [{type, message, value, isActive}]} (komponentin validation listesini TAMAMEN değiştirir; boş dizi hepsini siler) | set_appearance {target, appearance: {heightType?, widthType?, tooltip?, background?, …}} (kurulu düğümün appearance'ına YALNIZ verilen alanları yazar, gerisini korur; null alanı temizler; bilinmeyen alan unknown-appearance-field ile reddedilir. GÖRÜNÜRLÜK appearance'ta DEĞİLDİR: gizlemek için replace_prop {target, prop: 'isHidden', value: true}, koşul için set_binding {prop: 'isHidden'} — add_component gövdesindeki appearance.isHidden'ı gateway props.isHidden'a taşır) | resize_component {target, size?: {w,h}, appearance?: {widthType,widthString,heightType,heightString}, states?: {isWrapper,isScrollable,isSticky,isDroppable,isFloating,isQuickStack}, breakpoint?: 1024} (gateway adı: platforma set_block {target, breakpoint, size} + set_appearance {target, appearance} + set_states {target, states} olarak gider — o üç op'u doğrudan da gönderebilirsiniz. move_component'e konan size reddedilir. Izgarada blocks[].size, flex'te appearance geçerlidir; ebeveynin düzeni yazılanı etkisiz kılıyorsa PAGE-019 uyarısı çıkar. states bir PROP DEĞİL düğüm alanıdır ve replace_prop onu yazamaz — düğümü silmeden isWrapper bayrağını değiştirmenin yolu budur). set_prop_type {target, prop, propType: 'static'|'code'|'translation', ref?, data?} (replace_prop sarmalıyla aynı sonucu verir ve mevcut data'yı tasarım yedeği olarak taşır. Bu op prop'un TİPİNİ yerinde değiştirir. Taşıyıcı alan tipe göre: static → data, code ve translation → ref (runtime data'yı her turda ezer, anahtar yalnız ref'te yaşar). Eksik taşıyıcı istek gönderilmeden reddedilir; page_schema_validate aynı kararı verir) | reorder {parent ('root' ya da elementId), order: [çocuk elementId'lerinin TAMAMI, yeni sırada]} (yalnız DİZİ sırasını değiştirir; çizim sırası blocks.position'dır — görünen sırayı değiştirmek için konumları set_block/move_component ile de yazın) | set_state_binding {target, binding: {name, expression, targets}} (ada göre ekler/değiştirir) | remove_state_binding {target, name} | batch {gestureId?, label?, ops: [...]} (iç içe batch yok). target = elementId. İstek atomiktir: tek op reddedilirse hiçbiri yazılmaz.");
|
|
28
28
|
/**
|
|
29
29
|
* PAGE-008 — `set_event` uydurma bir olay adıyla 200 döner ve bağ SESSİZCE ölü kalır: motor olayı
|
|
30
30
|
* komponentin yaydığı adla eşleştirir, eşleşme yoksa akış hiç çalışmaz. Kontrol yalnız hedefin
|
|
@@ -35,7 +35,7 @@ export const opsParam = z.array(z.record(z.unknown())).describe("Micro-op listes
|
|
|
35
35
|
export function unknownEventOps(ops, typesByElementId, eventsBySlug) {
|
|
36
36
|
return ops
|
|
37
37
|
.map(op => op)
|
|
38
|
-
.filter(op => op.op === 'set_event')
|
|
38
|
+
.filter(op => op.op === 'set_event' || op.op === 'add_event')
|
|
39
39
|
.flatMap(op => {
|
|
40
40
|
const target = String(op.target ?? '');
|
|
41
41
|
const event = String(op.event ?? '');
|
package/package.json
CHANGED