@appaflytech/zeyrek-ai-mcp 0.0.8 → 0.0.9
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/README.md +27 -21
- package/dist/config.js +2 -0
- package/dist/knowledge/componentCatalog.js +122 -27
- package/dist/knowledge/componentEvents.js +35 -4
- package/dist/knowledge/errorPath.js +1 -1
- package/dist/knowledge/normalize.js +15 -0
- package/dist/knowledge/rules.js +3 -1
- package/dist/knowledge/styleResolve.js +46 -4
- package/dist/knowledge/themeResolve.js +936 -0
- package/dist/knowledge/themeRules.js +221 -0
- package/dist/knowledge/themeSchema.js +335 -0
- package/dist/platform/domSummary.js +144 -0
- package/dist/platform/screenshot.js +414 -23
- package/dist/platform/screenshotMemory.js +55 -0
- package/dist/resources/examples/layout-app-shell.json +1 -1
- package/dist/resources/examples/theme-brand.json +162 -0
- package/dist/resources/guides/component.md +7 -1
- package/dist/resources/guides/getting-started.md +4 -0
- package/dist/resources/guides/layout.md +30 -26
- package/dist/resources/guides/microservice.md +55 -1
- package/dist/resources/guides/page.md +87 -44
- package/dist/resources/guides/theme.md +210 -0
- package/dist/resources/guides/translation.md +6 -4
- package/dist/resources/guides/workflow.md +91 -6
- package/dist/resources/schema-fingerprint.json +2 -2
- package/dist/server.js +52 -43
- package/dist/tools/components.js +8 -0
- package/dist/tools/designSchemaPatch.js +152 -0
- package/dist/tools/flows.js +15 -18
- package/dist/tools/layouts.js +4 -4
- package/dist/tools/microservices.js +5 -5
- package/dist/tools/pages.js +196 -323
- package/dist/tools/projects.js +66 -9
- package/dist/tools/schemaOps.js +280 -0
- package/dist/tools/screenWrite.js +2 -1
- package/dist/tools/screens.js +0 -7
- package/dist/tools/themes.js +163 -0
- package/dist/tools/workflows.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Tema Rehberi (proje düzeyi tasarım)
|
|
2
|
+
|
|
3
|
+
Bir projenin rengi, yazı tipi, köşe/boşluk ölçekleri, gölgesi ve yeniden kullanılan stilleri
|
|
4
|
+
**tek bir kayıtta** yaşar: `projects.theme`. Runtime onu her sayfada `--ng-*` CSS
|
|
5
|
+
değişkenlerine çevirir, yani temayı değiştirmek bütün ekranları birden değiştirir.
|
|
6
|
+
|
|
7
|
+
Okuma `theme_get`, yazma `theme_update`. Studio'nun tema paneli de aynı kaydı yazar — MCP'den
|
|
8
|
+
yazdığınızı panel açar, panelin yazdığını MCP okur.
|
|
9
|
+
|
|
10
|
+
**Tema PROJE kaydıdır, ortam kaydı değil.** `environment` parametresi yoktur: yazma o an
|
|
11
|
+
projenin bütün ortamlarının runtime'ına iner (development de production da). Sayfa/entity
|
|
12
|
+
yazmalarının aksine burada "önce development'ta dene" diye bir ayrım YOKTUR.
|
|
13
|
+
|
|
14
|
+
## Veri modeli
|
|
15
|
+
|
|
16
|
+
`theme_get(view:'raw')` kaydın kendisini, `view:'resolved'` ekrana inen hâlini verir.
|
|
17
|
+
|
|
18
|
+
| Alan | Ne yapar | Ürettiği değişken(ler) |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `mode` | `'light'` (varsayılan) \| `'dark'` — yayınlanan uygulamanın modu | palet tabanını seçer |
|
|
21
|
+
| `palette` | AYDINLIK moddaki renk override'ları | `--ng-accent-*` · `--ng-background-*` · `--ng-text-*` · `--ng-border-*` · `--ng-status-*` |
|
|
22
|
+
| `paletteDark` | KARANLIK moddaki renk override'ları | aynı küme |
|
|
23
|
+
| `fontFamily` · `headingFontFamily` | Gövde ve başlık yazı tipi (Google Fonts adı) | `--ng-font` · `--ng-font-heading` |
|
|
24
|
+
| `fontSize` · `fontWeight` | Taban punto ve ağırlık | `--ng-font-size` · `--ng-font-weight` |
|
|
25
|
+
| `typeScale` | Metin seviyelerinin tabana ORANI (h1…small) | `--ng-font-size-h1` … `-small` (+ `-mobile`) |
|
|
26
|
+
| `spacing` · `spacingScale` | Taban boşluk ve kademe oranları | `--ng-spacing` · `--ng-spacing-xs..xl` |
|
|
27
|
+
| `borderRadius` · `radiusScale` | Taban köşe ve kademeler (`pill` sabit uzunluk) | `--ng-rounded` · `--ng-radius-sm/md/lg/pill` |
|
|
28
|
+
| `shadow` | Tek gölge tarifi (offset/blur/spread/color/opacity) | `--ng-shadow-sm/md/lg` |
|
|
29
|
+
| `defaultInputSize` | Form girdilerinin varsayılan boyu (`sm`/`md`/`lg`) | `--ng-form-default-size` |
|
|
30
|
+
| `colors` | Renk RAMPALARI (aile → ton) | `--ng-blue-500`, `--ng-grey-200` … |
|
|
31
|
+
| `actions` | Grafik/veri görselleştirme serisi renkleri | `--ng-action-blue` … |
|
|
32
|
+
| `presets` | **Adlı stiller** — düğümden `style.$preset` ile çağrılır | CSS değişkeni üretmez |
|
|
33
|
+
| `componentPresets` | Bir TİPİN yeni düğümlerde başlayacağı prop varsayılanları | CSS değişkeni üretmez |
|
|
34
|
+
| `componentStyles` | **EMEKLİ** — tipin her örneğine canlı uygulanan stil | CSS değişkeni üretmez |
|
|
35
|
+
|
|
36
|
+
**Yalnız SAPAN değer yazılır.** `typeScale`, `radiusScale`, `spacingScale` ve `actions`
|
|
37
|
+
kayıtta yalnız varsayılandan farklı olan kademeleri/renkleri taşır; dokunulmayan kademe
|
|
38
|
+
platformun varsayılanını İZLEMEYE devam eder. Hepsini birden yazmak onları o günkü değerlere
|
|
39
|
+
dondurur — yazmayın.
|
|
40
|
+
|
|
41
|
+
Değişkenlerin tam listesi ve o projedeki değerleri: `theme_get(view:'resolved')` → `cssVars`
|
|
42
|
+
(~190 giriş). Bir sayfada tek seferlik sapma için `platform_guide('page')` Kural 1h.
|
|
43
|
+
|
|
44
|
+
## Karar kuralları
|
|
45
|
+
|
|
46
|
+
**1. Önce tema, sonra preset, en son düğüm stili.** Aynı görünüm üç yerden verilebilir ve
|
|
47
|
+
sırası bellidir: projenin tamamı için tema token'ı (`theme_update`), tekrar eden bir kalıp için
|
|
48
|
+
adlı preset (`presets` + `style.$preset`), yalnız o düğüme özgü karar için düğümün kendi
|
|
49
|
+
`style`'ı. Sabit hex yazmak yerine `var(--ng-accent-primary)` yazmak, düğümü temaya BAĞLI
|
|
50
|
+
tutar.
|
|
51
|
+
|
|
52
|
+
**2. Marka rengi tek çağrıdır.** `theme_update({ palette: { accent: { primary, hover } } })`
|
|
53
|
+
sayfadaki her butonu, odak halkasını, seçili satırı ve grafik serisini birden çevirir. Komponent
|
|
54
|
+
komponent stil yazmak hem uzun sürer hem yeni komponent eklendiğinde tutarsızlık üretir.
|
|
55
|
+
|
|
56
|
+
**3. "Her X böyle görünsün" ile "yeni X şöyle başlasın" AYRI şeylerdir.**
|
|
57
|
+
|
|
58
|
+
| İstek | Yol | Mevcut düğümlere etkisi |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| Her kart aynı yüzeyi paylaşsın | `presets.kart` + düğümde `style.$preset: 'kart'` | Bağlı olanların hepsi anında değişir |
|
|
61
|
+
| Yeni bırakılan her button `lg` olsun | `componentPresets.button` | **YOK** — yalnız bundan sonra kurulanlar |
|
|
62
|
+
| (emekli) Her button kalın olsun | `componentStyles.button` | Studio paneli ilk kayıtta bunu `componentPresets`'e taşır ve canlı bağ kopar |
|
|
63
|
+
|
|
64
|
+
`componentPresets` bir KASKAD DEĞİL, başlangıç değeridir: değerler düğüm kurulurken prop'lara
|
|
65
|
+
yazılır ve `style.$componentPreset` yalnız "hangi versiyondan geldi"yi anar. Temada versiyonu
|
|
66
|
+
sonradan değiştirmek o düğümleri güncellemez.
|
|
67
|
+
|
|
68
|
+
**4. Koyu mod ayrı bir palettir ve proje `light` olsa da devreye girebilir.** Karanlıkta
|
|
69
|
+
runtime `paletteDark`'a bakar, `palette`'e değil. İki ayrı durum aynı sonucu verir:
|
|
70
|
+
|
|
71
|
+
- Kaydın kendisi `mode: 'dark'` ve yalnız `palette` yazılmış → renkler hiç görünmez.
|
|
72
|
+
- Kayıt `mode: 'light'` ama **ZİYARETÇİ** koyu moda geçmiş (`theme-toggle` komponenti,
|
|
73
|
+
tarayıcıda kalıcı; `page_screenshot(colorScheme: 'dark')` aynı yolu kullanır) → yine
|
|
74
|
+
`paletteDark` okunur ve markanız yerine platformun kendi koyu paleti çizilir.
|
|
75
|
+
|
|
76
|
+
Ölçüldü (2026-09-15): yalnız `palette` yazılmış bir projede aydınlık kare markanın indigo'sunu,
|
|
77
|
+
koyu kare platformun `#4C8DFF` mavisini gösterdi. **Uygulama koyu modda açılabiliyorsa
|
|
78
|
+
`paletteDark` da yazılır** — THEME-009 bunu her iki durumda da uyarır.
|
|
79
|
+
|
|
80
|
+
**5. Yazmadan önce `dryRun`.** `theme_update(dryRun: true, …)` hiçbir şey yazmadan hangi
|
|
81
|
+
yolların değişeceğini (`changed`) ve hangi CSS değişkeninin hangi değerden hangi değere
|
|
82
|
+
gideceğini (`cssVarsChanged`) söyler. Bir rengin türetilmiş etkisini (odak halkası, grafik
|
|
83
|
+
serisi, kontrast metin) görmenin en ucuz yolu budur.
|
|
84
|
+
|
|
85
|
+
**6. Kısmi yaz, `unset` ile sil.** `theme_update` verdiğiniz alanları mevcut kayda DERİN
|
|
86
|
+
birleştirir: bir rengi değiştirmek preset'leri düşürmez. Silmek `null` yazmakla değil
|
|
87
|
+
`unset: ['presets.kart']` ile olur; kaydın tamamını değiştirmek `replace: true` ister.
|
|
88
|
+
|
|
89
|
+
## Tarifler
|
|
90
|
+
|
|
91
|
+
**Marka paleti (aydınlık + karanlık):**
|
|
92
|
+
|
|
93
|
+
```jsonc
|
|
94
|
+
theme_update({ theme: {
|
|
95
|
+
palette: { accent: { primary: "#4F46E5", hover: "#4338CA" } },
|
|
96
|
+
paletteDark: { accent: { primary: "#818CF8", hover: "#A5B4FC" } }
|
|
97
|
+
} })
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Yazı tipi ve ölçek:** `fontFamily` panelin Google Fonts listesinden bir ad olmalı — runtime
|
|
101
|
+
fontu ADIYLA Google'dan çeker, tanınmayan ad sessizce sans-serif'e düşer (THEME-008).
|
|
102
|
+
|
|
103
|
+
```jsonc
|
|
104
|
+
theme_update({ theme: {
|
|
105
|
+
fontFamily: "Inter Tight", headingFontFamily: "Sora",
|
|
106
|
+
fontSize: "15px", typeScale: { h1: 2.5 }
|
|
107
|
+
} })
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Ölçekler:** oran `0 < r ≤ 20` aralığında olmalı; aralık dışı değer runtime'da SESSİZCE yok
|
|
111
|
+
sayılır (THEME-007 bunu yazmadan önce durdurur).
|
|
112
|
+
|
|
113
|
+
```jsonc
|
|
114
|
+
theme_update({ theme: { borderRadius: "8px", radiusScale: { lg: 2 }, spacing: "12px" } })
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Gölge:** `color` altı haneli hex OLMALI; başka bir yazım üç gölgeyi birden görünmez yapar
|
|
118
|
+
(THEME-004).
|
|
119
|
+
|
|
120
|
+
```jsonc
|
|
121
|
+
theme_update({ theme: { shadow: { offsetY: 6, blur: 12, spread: -2, color: "#1E1B4B", opacity: 18 } } })
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Adlı preset kurup bir düğüme bağlamak** — iki adım, ikincisi sayfa tarafında:
|
|
125
|
+
|
|
126
|
+
```jsonc
|
|
127
|
+
// 1) temaya yaz
|
|
128
|
+
theme_update({ theme: { presets: { kart: {
|
|
129
|
+
padding: "16px", borderRadius: "12px",
|
|
130
|
+
background: "var(--ng-background-surface)", boxShadow: "var(--ng-shadow-md)"
|
|
131
|
+
} } } })
|
|
132
|
+
|
|
133
|
+
// 2) düğüme bağla (page_schema_patch)
|
|
134
|
+
{ "op": "replace_prop", "target": "kart_1", "prop": "style", "value": { "$preset": "kart" } }
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Preset gövdesinde sabit hex yerine `var(--ng-*)` kullanın: preset de temayı izlesin.
|
|
138
|
+
|
|
139
|
+
**Bileşen preseti (yeni düğümlerin başlangıç değeri):** `props` ham prop varsayılanlarıdır
|
|
140
|
+
(`component_get` → `defaults` ile aynı şekil); `appearance` yalnız BOŞLUK alanlarını taşır
|
|
141
|
+
(margin/padding) — ölçü ve hizalama o örneğin ızgaradaki geometrisidir, tipin kararı değil.
|
|
142
|
+
|
|
143
|
+
```jsonc
|
|
144
|
+
theme_update({ applicationId: "<app>", theme: { componentPresets: { button: {
|
|
145
|
+
defaultVersion: "V1",
|
|
146
|
+
versions: { V1: { props: { size: "lg" }, appearance: { marginType: "custom", marginValues: { bottom: 12 } } } }
|
|
147
|
+
} } } })
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Bir tip en fazla 5 versiyon taşır ve `defaultVersion` versiyonlar arasında olmalıdır
|
|
151
|
+
(THEME-002). `applicationId` verirseniz gateway tipin o uygulamanın kataloğunda gerçekten
|
|
152
|
+
var olduğunu da denetler (THEME-011).
|
|
153
|
+
|
|
154
|
+
**Grafik paleti ve rampalar:** `actions` grafik serisi renkleri (`--ng-action-*`), `colors`
|
|
155
|
+
ise ton rampaları (`--ng-blue-500` gibi). İkisi de yalnız veri yoluyla ayarlanır; panelde
|
|
156
|
+
rampa arayüzü yoktur.
|
|
157
|
+
|
|
158
|
+
**Temayı sıfırlamak:** `theme_update({ replace: true, theme: {} })`.
|
|
159
|
+
|
|
160
|
+
## Doğrulama
|
|
161
|
+
|
|
162
|
+
Sıra sabittir; her adım bir öncekinin kanıtını üretir:
|
|
163
|
+
|
|
164
|
+
1. `theme_update(dryRun: true, …)` → `cssVarsChanged` beklediğiniz değişkenleri taşıyor mu?
|
|
165
|
+
2. `theme_update(…)` → `changed.set` / `changed.unset` yazılanı doğruluyor mu?
|
|
166
|
+
3. `theme_get(view:'resolved')` → `cssVars['--ng-accent-primary']` yeni değeri mi?
|
|
167
|
+
4. `page_screenshot(…)` → **ekranda** gerçekten öyle mi? Koyu mod için aynı çağrıya
|
|
168
|
+
`colorScheme: 'dark'`; sayfada `theme-toggle` komponenti bulunması GEREKMEZ.
|
|
169
|
+
5. Preset bağladıysanız `page_runtime_get(resolveStyles: true)` → düğümün
|
|
170
|
+
`styleLayers.preset` alanı preset adını söylüyor mu, `resolvedStyle` preset'in
|
|
171
|
+
değerlerini taşıyor mu?
|
|
172
|
+
|
|
173
|
+
## Tuzaklar
|
|
174
|
+
|
|
175
|
+
**`project_update` tema alanı verilmezse temayı SİLERDİ.** Platformun `PUT /projects/{id}`
|
|
176
|
+
ucu REPLACE'tir: gövdede `Theme` yoksa tema `null` yazılır ve bütün ortamlara yayılır. Gateway
|
|
177
|
+
artık mevcut temayı okuyup gövdeye geri koyuyor ve bunu `gatewayNormalized` ile bildiriyor —
|
|
178
|
+
ama temayı DEĞİŞTİRMEK için `project_update` değil `theme_update` kullanın.
|
|
179
|
+
|
|
180
|
+
**Studio tema paneli açık ve kaydedilmemişse yazmanız ezilir.** Panel durumunu açılışta
|
|
181
|
+
okur; siz MCP'den yazarken panel açıksa panelin sonraki "Save"i kendi kopyasını üstüne yazar.
|
|
182
|
+
Panel kapalıyken yazın. Gateway bunu tespit edemez — proje kaydında sürüm alanı yoktur.
|
|
183
|
+
|
|
184
|
+
**Silinen preset sessizce kaybolur.** Çözümleyici eşleşmeyen bir `$preset` adını hata vermeden
|
|
185
|
+
atlar (bir preset silindi diye sayfalar boşalmasın diye). Düğüm kendi stiline düşer ve kimse
|
|
186
|
+
bir şey söylemez — silmeden önce `page_schema_get` ile o adı arayın (THEME-010 uyarır ama
|
|
187
|
+
tarama yapmaz).
|
|
188
|
+
|
|
189
|
+
**`componentStyles` yazmak canlı kaskadı kalıcı kılmaz.** Runtime onu hâlâ uyguluyor ama
|
|
190
|
+
Studio tema paneli açıldığı ilk kayıtta içeriği `componentPresets`'e taşıyıp anahtarı siliyor:
|
|
191
|
+
o an "her örneğe uygulanan stil", "yalnız yeni düğümlere varsayılan"a döner ve sayfadaki
|
|
192
|
+
mevcut düğümler görünüşlerini kaybeder (THEME-003).
|
|
193
|
+
|
|
194
|
+
**Çıplak sayı CSS uzunluğu değildir.** `fontSize: 16` → `--ng-font-size: 16` geçersizdir ve
|
|
195
|
+
tarayıcı bildirimi sessizce atar. Gateway sayıyı `'16px'`e çevirip `gatewayNormalized` ile
|
|
196
|
+
bildirir; birimli yazmak daha açıktır.
|
|
197
|
+
|
|
198
|
+
**Tanınmayan anahtar kayıtta yaşar.** `projects.theme` doğrulanmayan bir jsonb blob'udur:
|
|
199
|
+
`pallete` yazan istek 200 döner ve panel o anahtarı körce geri yazar. `theme_update` şeması
|
|
200
|
+
bunu istek gitmeden reddeder; eski kayıtlardaki kalıntıları `theme_get` `unknownKeys` ile
|
|
201
|
+
gösterir ve `unset` temizler.
|
|
202
|
+
|
|
203
|
+
**Markanın koyu karşılığı ayrı yazılır.** Aydınlık paleti yazıp bitirdiğinizi sanmak en kolay
|
|
204
|
+
hata: ziyaretçi koyu moda geçtiği anda uygulamanız platformun varsayılan mavisine döner. İki
|
|
205
|
+
kareyi de alın: `page_screenshot(…)` ve `page_screenshot(…, colorScheme: 'dark')`; ikisinin de
|
|
206
|
+
`theme_get(view:'resolved', mode: …)` ile aynı şeyi söylediğini doğrulayın.
|
|
207
|
+
|
|
208
|
+
**Renkler hex olmalı.** CSS `rebeccapurple`'ı çizer ama studio'nun renk alanları hex bekler
|
|
209
|
+
ve vurgu üstündeki metin rengi (`--ng-text-on-accent`) accent'i karakter karakter okuyup
|
|
210
|
+
kontrast hesapladığı için tanımadığı değerde beyaza düşer (THEME-005).
|
|
@@ -87,7 +87,7 @@ backend'de zaten tanımlı, Studio'nun "Translate" aksiyonunun ürettiği şekil
|
|
|
87
87
|
> yeniden eklemeyi öneriyordu; o öneri uygulanınca düğüme yazan setter iteratee'lerinin `element`'i
|
|
88
88
|
> silindi (bir panoda alt başlık ve tarih aralığı boş kaldı). Ref'siz translation sarmalı istek
|
|
89
89
|
> gönderilmeden reddedilir; nesne `data` silinir. Eş yol `set_prop_type`'tır — mevcut `data`'yı
|
|
90
|
-
> tasarım yedeği olarak taşır
|
|
90
|
+
> tasarım yedeği olarak taşır:
|
|
91
91
|
>
|
|
92
92
|
> ```jsonc
|
|
93
93
|
> { "op": "set_prop_type", "target": "welcome_text", "prop": "text",
|
|
@@ -95,9 +95,11 @@ backend'de zaten tanımlı, Studio'nun "Translate" aksiyonunun ürettiği şekil
|
|
|
95
95
|
> ```
|
|
96
96
|
>
|
|
97
97
|
> İkisi de düğümün olay/setter bağlarını korur. **Prop tipini değiştirmek için
|
|
98
|
-
> `remove_component` + `add_component` yapmayın.**
|
|
99
|
-
>
|
|
100
|
-
> `
|
|
98
|
+
> `remove_component` + `add_component` yapmayın.** İki op da platformun kendi sözlüğündedir ve
|
|
99
|
+
> yamanın geri kalanıyla aynı PATCH'te gider — sayfada `page_schema_patch`, layout'ta
|
|
100
|
+
> `layout_schema_patch`, widget'ta `component_schema_patch`. Taşıyıcı alan tipe göre değişir:
|
|
101
|
+
> `static` → `data`, `code` ve `translation` → `ref`. Eksik taşıyıcı istek platforma gitmeden
|
|
102
|
+
> reddedilir ve `page_schema_validate` aynı kararı verir.
|
|
101
103
|
>
|
|
102
104
|
> Ölçüldü 2026-09-08 (yerel `dil-dogrulama/dil-app`): kurulu bir `statcard`'ın `title` prop'u tek
|
|
103
105
|
> `set_prop_type` op'uyla `f11.tam` anahtarına bağlandı; gerçek ekranda `tr` → "iki dilde dolu",
|
|
@@ -139,6 +139,85 @@ yoktur** (ölçüm: 2026-09-07). Yazmayı doğrulamak istiyorsan sorguyu kaydet,
|
|
|
139
139
|
|
|
140
140
|
Tool açıklamaları bu bölüme işaret eder; iki kaynak çelişirse **bu rehber** doğrudur.
|
|
141
141
|
|
|
142
|
+
## Önizleme çıktısını okumak: adım izi, hata alanları ve canlı koşudan farkı
|
|
143
|
+
|
|
144
|
+
`workflow_preview` / `automation_preview` yanıtı `WorkflowPreviewDto`'dur — Studio'daki "Önizleme"
|
|
145
|
+
düğmesinin okuduğu gövdenin aynısı (`WorkflowDetail.svelte` `handlePreview` →
|
|
146
|
+
`POST workflows/{appId}/preview`). Studio'nun yaptığı tek şey listeyi düzleştirip **`hasError: true`
|
|
147
|
+
olan ilk adıma** odaklanmaktır; hata yoksa son adıma. Aynı okumayı sen de yap:
|
|
148
|
+
|
|
149
|
+
```jsonc
|
|
150
|
+
{ "input": { "id": 12 }, // previewPayload'ın değerlendirilmiş hâli — BOŞSA girdi hiç bağlanmamıştır (WF-016)
|
|
151
|
+
"output": { … }, // akışın döndürdüğü gövde (response adımı)
|
|
152
|
+
"executionSuccess": true, // YALNIZ son adıma bakar — hata dalından dönen akışta da true olabilir
|
|
153
|
+
"steps": [
|
|
154
|
+
{ "step": { "id": "…", "name": "readRow", "type": "table" },
|
|
155
|
+
"input": [ { "expression": "input.id", "value": 12, "source": "filter", "member": "id" } ],
|
|
156
|
+
"output": { … }, // adımın ürettiği veri; patlayan adımda boş
|
|
157
|
+
"hasError": true,
|
|
158
|
+
"errorType": "RowNotFoundException", "errorCode": "RowNotFound",
|
|
159
|
+
"errorMessage": "…lokalize mesaj…", "errorDetail": "…iç ayrıntı (SQL/JS hatası)…",
|
|
160
|
+
"elapsedMilliseconds": 7.3,
|
|
161
|
+
"nextStep": { "id": "…", "name": "gatewayOnError", "type": "response" }, // akış buradan nereye gitti
|
|
162
|
+
"children": [ … ], // loop iterasyonları / alt workflow: her biri { kind, name, steps, input, output, executionSuccess }
|
|
163
|
+
"automations": [ … ] // table adımının tetiklediği automation'lar: { id, name, entityId, operation, row, previousRow, status, errorMessage, executionSuccess, steps }
|
|
164
|
+
} ],
|
|
165
|
+
"runtimeErrors": [ "readRow (table): RowNotFound — …" ] // GATEWAY ekler; platform gövdesinde yoktur
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Okuma sırası:**
|
|
170
|
+
|
|
171
|
+
1. **`runtimeErrors`** — gateway tüm ağacı tarar (`steps[].children[].steps[]` ve
|
|
172
|
+
`steps[].automations[].steps[]` dâhil). Boşsa akış hiçbir adımda patlamamıştır.
|
|
173
|
+
`executionSuccess`'e güvenme: platform onu son adımın `hasError`'ından hesaplar
|
|
174
|
+
(`WorkflowPreviewDto.cs:25`); ortada patlayıp `gatewayOnError`'dan 500 dönen akış `true` gösterir.
|
|
175
|
+
2. **Patlayan adımın satırı** — `errorType` exception tipi, `errorMessage` lokalize mesaj,
|
|
176
|
+
`errorDetail` iç ayrıntı. `input[]` adımın hangi ifadeyi hangi değere bağladığını gösterir:
|
|
177
|
+
satırda `value` yoksa ifade `undefined`/null üretmiştir — hatanın gerçek sebebi çoğu zaman bir
|
|
178
|
+
üst adımın çıktısı ya da bağlanmamış girdidir (`"input": {}`).
|
|
179
|
+
3. **`nextStep`** — adımdan sonra akışın nereye gittiği. Hata dalına düşen adımın `nextStep`'i
|
|
180
|
+
global-error dalının ilk adımıdır; `fail` dalı bağlıysa o adımdır.
|
|
181
|
+
4. **`elapsedMilliseconds`** — koşunun toplamı beklenenden çok kısaysa (yazma akışı 90 ms gibi)
|
|
182
|
+
akış ilk adımlarda patlayıp hata dalından dönmüştür; adım sürelerinden nerede durduğunu oku.
|
|
183
|
+
5. **HTTP 200 ≠ geçti, HTTP 400/500 ≠ adım hatası.** Yanıt 200 iken akış patlamış olabilir
|
|
184
|
+
(yukarıdaki alanlar). Yanıt 400/500 ise koşum **hiç başlamamıştır**: validator reddi (WF-026),
|
|
185
|
+
`previewPayload`'ın nesne gönderilmesi (`Unexpected end of input`), `previewVariables`
|
|
186
|
+
ifadesinin patlaması. İkisini ayır: ilkinde adımı, ikincisinde gövdeyi düzelt.
|
|
187
|
+
|
|
188
|
+
**Kayıtlı bir akışı çalıştırmadan koşturmak** (Studio'nun "Önizleme" düğmesinin MCP karşılığı):
|
|
189
|
+
|
|
190
|
+
1. `workflow_get(applicationId, id)` — varsayılan `view:'full'` gövde `steps`, `parameterDtoId`,
|
|
191
|
+
**`previewPayload`** ve **`previewVariables`** alanlarını taşır: Studio'da yazılan test girdisi
|
|
192
|
+
tanımla birlikte saklanır (`Workflow.PreviewPayload` / `PreviewVariables`) ve Studio'nun
|
|
193
|
+
önizlemesi de onu kullanır.
|
|
194
|
+
2. Yanıttaki `data` gövdesini `workflow_preview(definition)` ile olduğu gibi gönder: `id`,
|
|
195
|
+
`createdAt` gibi fazladan alanlar platformda yok sayılır; `parameterDtoId` yoksa gateway
|
|
196
|
+
`previewPayload`'ı düşürür. Girdiyi değiştirmek için yalnız `previewPayload`'ı yeniden yaz
|
|
197
|
+
(`"({ … })"` biçimi, Kural 4).
|
|
198
|
+
3. `runtimeErrors` boş + `input` dolu ⇒ akış bu girdiyle geçiyor. Ancak ondan sonra kaydet, uca
|
|
199
|
+
bağla ya da zamanla. Zamanlanmış iş için sıra ve tuzaklar: `platform_guide('microservice')`
|
|
200
|
+
§"Zamanlanmış işin gerçek sonucunu görmek".
|
|
201
|
+
|
|
202
|
+
**Önizleme neyi kanıtlar, neyi kanıtlamaz** (kaynak: `PreviewWorkflowCommand`, `WorkflowContext`,
|
|
203
|
+
`ExecuteMicroserviceBehavior`, `MicroserviceJob`):
|
|
204
|
+
|
|
205
|
+
| Konu | `workflow_preview` | Canlı uç (`/m/`, sayfa akışı) | Zamanlanmış iş (`schedule-job`) |
|
|
206
|
+
|---|---|---|---|
|
|
207
|
+
| Yazmalar | tek transaction, sonunda **rollback** | 2xx'te commit, 4xx/5xx'te rollback | 2xx'te commit; bağlanmamış fail ya da 2xx dışı sonuçta **rollback** (2026-09-16'dan beri; öncesinde her durumda commit ediyordu) |
|
|
208
|
+
| Girdi | `previewPayload` (JS kaynak metni) | isteğin gövdesi/query/route, DTO'ya bağlanır | **boş** (`MicroserviceExecuteParameter.Create()`); `input.x` hep `undefined` |
|
|
209
|
+
| `request.*` | **yok** (Preview'da yüklenmez) | var | **yok** (HttpContext yok) |
|
|
210
|
+
| `context` / `triggerSource` | kurulmaz (GEN-005) | var | kurulmaz |
|
|
211
|
+
| Middleware ve `user` | koşmaz | koşar | **koşmaz** — `user` yok |
|
|
212
|
+
| `email`, `http`, `code` içi HTTP | **gerçekten koşar** (SMTP gönderilir, dış uç çağrılır) | gerçek | gerçek |
|
|
213
|
+
| `microfunction` | `preview: true` bayrağıyla çağrılır | gerçek | gerçek |
|
|
214
|
+
| `table` / `file` yazmaları | geri alınır | yukarıdaki commit/rollback | yukarıdaki commit/rollback |
|
|
215
|
+
| Adım izi | **tam** (bu bölüm) | yok — yalnız yanıt gövdesi; ağaç için `microservice_debug` | yok — geçmiş satırı `status + süre + errorMessage` (`Step 'x' failed: <sebep>` ya da `The job's workflow returned 500 (<code>): <mesaj>`) |
|
|
216
|
+
|
|
217
|
+
Yani önizleme akışın **şeklini** kanıtlar: ifadeler, dallar, DTO uyumu, tablo/sorgu hataları.
|
|
218
|
+
Kanıtlamadıkları: dile bağlı dal (`context.language`), `user`'a bağlı kapsam, `request`'ten okunan
|
|
219
|
+
parametre — bunları `microservice_execute` ile ölç (§İstek dili, `platform_guide('middleware')`).
|
|
220
|
+
|
|
142
221
|
## Hata yolu
|
|
143
222
|
|
|
144
223
|
**Gateway workflow ve middleware tanımlarına hata yolunu otomatik ekler** (yanıtta
|
|
@@ -176,8 +255,11 @@ yapıyı dışarı sızdırır.
|
|
|
176
255
|
- **`automation` tipinde `response` adımı yasaktır**, bu yüzden gateway bu tipe enjeksiyon
|
|
177
256
|
yapmaz. Hata yolunu kendin yaz: global-error dalını `revert` (kapsamı `isQueue`'ya
|
|
178
257
|
bağlı — §izin matrisi) ya da `email`/`table` adımına bağla. Bağlı hata yolu yoksa `WF-021` uyarır.
|
|
179
|
-
- **Hata yolu hiç yoksa**
|
|
180
|
-
|
|
258
|
+
- **Hata yolu hiç yoksa** (fail dalı ve global-error dalı bağlı değil) adım patladığında motor
|
|
259
|
+
canlıda `WorkflowStepFailedException` fırlatır (2026-09-16): HTTP yanıt 500 +
|
|
260
|
+
`{ code, message, detail, type }` (patlayan adımın hatası), zamanlanmış iş ve automation geçmişi
|
|
261
|
+
`failed` + `Step 'x' failed: <sebep>`, senkron automation tetikleyen satır yazımını düşürür.
|
|
262
|
+
Önizlemede fırlatmaz, ağaç döner. Çalışır, ama çıktı lokalize değildir.
|
|
181
263
|
|
|
182
264
|
> **Preview HTTP 200 dönerken bile akış patlamış olabilir.** `executionSuccess` yalnız SON adıma
|
|
183
265
|
> bakar; ortada patlayıp hata dalından dönen akış `true` gösterir. Gateway tüm adımları (iç içe
|
|
@@ -186,10 +268,13 @@ yapıyı dışarı sızdırır.
|
|
|
186
268
|
>
|
|
187
269
|
> **`runtimeErrors` her tool'da aynı şeyi ölçmez.** Alan yalnız `steps[]` taşıyan yanıtlarda adım
|
|
188
270
|
> adım tarama yapar. `microservice_execute` / `microservice_debug` / `microservice_preview`
|
|
189
|
-
> yanıtlarında gateway sadece `httpStatus >= 400` durumunu bulgu sayar
|
|
190
|
-
> `
|
|
191
|
-
>
|
|
192
|
-
> `microservice_debug`
|
|
271
|
+
> yanıtlarında gateway sadece `httpStatus >= 400` durumunu bulgu sayar — bu üç uçta HTTP durumu
|
|
272
|
+
> akışın kendi `httpStatusCode`'udur (`MicroservicesController.HandleResult`), yani hata dalından
|
|
273
|
+
> 500 dönen akış yakalanır, ama 200 ile `{ success: false }` dönen akış yakalanmaz. Adım ağacını
|
|
274
|
+
> (`executionItems`) yalnız `microservice_debug` döner ve o düğümlerde hata işareti yoktur:
|
|
275
|
+
> patlayan adımın `output`'u boştur, hata gövdesi hata dalındaki response adımının çıktısındadır.
|
|
276
|
+
> Orada `body`'yi kendin oku. Adım başına hata alanı isteyen teşhis için akışı `workflow_preview`
|
|
277
|
+
> ile koştur (§Önizleme çıktısını okumak). `query_preview` yanıtları hiç kapsanmaz.
|
|
193
278
|
|
|
194
279
|
## Condition step kuralları
|
|
195
280
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"hash": "
|
|
3
|
-
"generatedAt": "2026-09-
|
|
2
|
+
"hash": "54430a8d4050fd201aaee88608a5d06b947edf6d561ad31354914422df4e94ce",
|
|
3
|
+
"generatedAt": "2026-09-16T11:17:11.569Z",
|
|
4
4
|
"types": 185,
|
|
5
5
|
"files": 107,
|
|
6
6
|
"note": "Şemaları üreten backend kaynaklarının parmak izi. Elle düzenlemeyin: 'npm run generate-schemas' yazar, 'npm run schema:check' denetler.",
|
package/dist/server.js
CHANGED
|
@@ -1,42 +1,44 @@
|
|
|
1
|
-
import { McpServer } from
|
|
2
|
-
import { registerMicroserviceTools } from
|
|
3
|
-
import { registerMicrofunctionTools } from
|
|
4
|
-
import { registerApplicationTools } from
|
|
5
|
-
import { registerDeploymentTools } from
|
|
6
|
-
import { registerDatasourceTools } from
|
|
7
|
-
import { registerAutomationTools } from
|
|
8
|
-
import { registerOrganizationTools } from
|
|
9
|
-
import { registerExternalComponentTools } from
|
|
10
|
-
import { registerComponentTools } from
|
|
11
|
-
import { registerPlatformTools } from
|
|
12
|
-
import { registerTemplateTools } from
|
|
13
|
-
import { registerWorkflowTools } from
|
|
14
|
-
import { registerLayoutTools } from
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { registerMicroserviceTools } from "./tools/microservices.js";
|
|
3
|
+
import { registerMicrofunctionTools } from "./tools/microfunctions.js";
|
|
4
|
+
import { registerApplicationTools } from "./tools/applications.js";
|
|
5
|
+
import { registerDeploymentTools } from "./tools/deployments.js";
|
|
6
|
+
import { registerDatasourceTools } from "./tools/datasources.js";
|
|
7
|
+
import { registerAutomationTools } from "./tools/automations.js";
|
|
8
|
+
import { registerOrganizationTools } from "./tools/organizations.js";
|
|
9
|
+
import { registerExternalComponentTools } from "./tools/externalComponents.js";
|
|
10
|
+
import { registerComponentTools } from "./tools/components.js";
|
|
11
|
+
import { registerPlatformTools } from "./tools/platformInfo.js";
|
|
12
|
+
import { registerTemplateTools } from "./tools/templates.js";
|
|
13
|
+
import { registerWorkflowTools } from "./tools/workflows.js";
|
|
14
|
+
import { registerLayoutTools } from "./tools/layouts.js";
|
|
15
|
+
import { registerDesignSchemaPatchTool } from "./tools/designSchemaPatch.js";
|
|
16
|
+
import { registerAccessTools } from "./tools/access.js";
|
|
17
|
+
import { registerTranslationTools } from "./tools/translations.js";
|
|
18
|
+
import { registerFlowTools } from "./tools/flows.js";
|
|
19
|
+
import { registerKnowledgeResources } from "./resources/knowledge.js";
|
|
20
|
+
import { registerSchemaResources } from "./resources/schemas.js";
|
|
21
|
+
import { registerRuleResources } from "./resources/rules.js";
|
|
22
|
+
import { instrumentServer } from "./observability/trace.js";
|
|
23
|
+
import { rejectUnknownArguments } from "./platform/strictArguments.js";
|
|
24
|
+
import { registerProjectTools } from "./tools/projects.js";
|
|
25
|
+
import { registerEntityTools } from "./tools/entities.js";
|
|
26
|
+
import { registerDependencyTools } from "./tools/dependencies.js";
|
|
27
|
+
import { registerVariableTools } from "./tools/variables.js";
|
|
28
|
+
import { registerFunctionTools } from "./tools/functions.js";
|
|
29
|
+
import { registerFolderTools } from "./tools/folders.js";
|
|
30
|
+
import { registerQueryTools } from "./tools/queries.js";
|
|
31
|
+
import { registerViewTools } from "./tools/views.js";
|
|
32
|
+
import { registerPageTools } from "./tools/pages.js";
|
|
33
|
+
import { registerThemeTools } from "./tools/themes.js";
|
|
34
|
+
import { registerFileTools } from "./tools/files.js";
|
|
35
|
+
import { registerRowTools } from "./tools/rows.js";
|
|
36
|
+
import { registerImportTools } from "./tools/imports.js";
|
|
37
|
+
import { registerEnvironmentTools } from "./tools/environments.js";
|
|
38
|
+
import { registerMergeTools } from "./tools/merges.js";
|
|
39
|
+
import { registerRevisionTools } from "./tools/revisions.js";
|
|
40
|
+
import { registerActivityTools } from "./tools/activities.js";
|
|
41
|
+
import { registerDtoTools } from "./tools/dtos.js";
|
|
40
42
|
const moduleRegistrations = {
|
|
41
43
|
platform: registerPlatformTools,
|
|
42
44
|
project: registerProjectTools,
|
|
@@ -53,10 +55,17 @@ const moduleRegistrations = {
|
|
|
53
55
|
dto: registerDtoTools,
|
|
54
56
|
view: registerViewTools,
|
|
55
57
|
page: registerPageTools,
|
|
56
|
-
|
|
58
|
+
theme: registerThemeTools,
|
|
59
|
+
component: (server, platform) => {
|
|
60
|
+
registerComponentTools(server, platform);
|
|
61
|
+
registerDesignSchemaPatchTool(server, platform, "component");
|
|
62
|
+
},
|
|
57
63
|
externalComponent: registerExternalComponentTools,
|
|
58
64
|
flow: registerFlowTools,
|
|
59
|
-
layout:
|
|
65
|
+
layout: (server, platform) => {
|
|
66
|
+
registerLayoutTools(server, platform);
|
|
67
|
+
registerDesignSchemaPatchTool(server, platform, "layout");
|
|
68
|
+
},
|
|
60
69
|
variable: registerVariableTools,
|
|
61
70
|
function: registerFunctionTools,
|
|
62
71
|
folder: registerFolderTools,
|
|
@@ -70,10 +79,10 @@ const moduleRegistrations = {
|
|
|
70
79
|
environment: registerEnvironmentTools,
|
|
71
80
|
merge: registerMergeTools,
|
|
72
81
|
activity: registerActivityTools,
|
|
73
|
-
revision: registerRevisionTools
|
|
82
|
+
revision: registerRevisionTools,
|
|
74
83
|
};
|
|
75
84
|
export function createGatewayServer(platform) {
|
|
76
|
-
const server = rejectUnknownArguments(instrumentServer(new McpServer({ name:
|
|
85
|
+
const server = rejectUnknownArguments(instrumentServer(new McpServer({ name: "ngapps", version: "0.1.0" }), platform.config));
|
|
77
86
|
for (const moduleName of platform.config.modules) {
|
|
78
87
|
moduleRegistrations[moduleName](server, platform);
|
|
79
88
|
}
|
package/dist/tools/components.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { guid, projectParam, environmentParam, readOnly, writes, updates, destructive } from './common.js';
|
|
2
2
|
import { normalizeComponentDefaults, componentDefaultsNote, clampBlockSizes, blockSizeNote, normalizeHeightTypes, heightTypeNote, normalizeSizeStrings, sizeStringNote, withNormalization } from '../knowledge/normalize.js';
|
|
3
3
|
import { eventContractsFor, eventPayloadNote } from '../knowledge/componentEvents.js';
|
|
4
|
+
import { componentPresetDefaults, readProjectTheme } from '../knowledge/themeSchema.js';
|
|
4
5
|
import { knowledgeFor, knowledgeNote, APPEARANCE_TOKEN_SETS, STATE_FLAG_NOTES, INTERNAL_ROLES_BY_TYPE } from '../knowledge/componentCatalog.js';
|
|
5
6
|
import { componentUpdateBody, fetchHost, schemaParam, unwrap } from './screens.js';
|
|
6
7
|
import { PlatformApiError } from '../platform/errors.js';
|
|
@@ -160,6 +161,12 @@ export function registerComponentTools(server, platform) {
|
|
|
160
161
|
: [];
|
|
161
162
|
const componentSlug = typeof component.slug === 'string' ? component.slug : undefined;
|
|
162
163
|
const knowledge = knowledgeFor(componentSlug);
|
|
164
|
+
// S-3 — `defaults` HAM katalogdur; Studio'da bırakılan düğüm ise temanın bileşen preseti
|
|
165
|
+
// kaplanmış katalogdan kurulur (`withThemeComponentDefaults`). Tema okunamazsa (uç düşer,
|
|
166
|
+
// yetki yoksa) alan yanıta HİÇ girmez: uydurulmuş bir varsayılan yanlış bilgidir.
|
|
167
|
+
const themeDefaults = componentSlug === undefined
|
|
168
|
+
? undefined
|
|
169
|
+
: componentPresetDefaults(readProjectTheme(await platform.org('GET', `/p/${platform.resolveProject(project)}`).catch(() => undefined)), componentSlug);
|
|
163
170
|
return {
|
|
164
171
|
id: component.id,
|
|
165
172
|
slug: component.slug,
|
|
@@ -188,6 +195,7 @@ export function registerComponentTools(server, platform) {
|
|
|
188
195
|
internalRolesNote: "Bu komponentin İÇ kontrolleri dışarıdan adreslenebilir: page_screenshot actions hedefine '<elementId>__<rol>' yazın (ör. 'tbl_vacancy__pager-next'). Kimlikler runtime'ın data-element-id özniteliğidir; ikinci bir mekanizma yoktur."
|
|
189
196
|
}
|
|
190
197
|
: {}),
|
|
198
|
+
...(themeDefaults ? { themeDefaults } : {}),
|
|
191
199
|
appearanceValues: APPEARANCE_TOKEN_SETS,
|
|
192
200
|
stateFlags: STATE_FLAG_NOTES,
|
|
193
201
|
validations: definition.validations,
|