@appaflytech/zeyrek-ai-mcp 0.0.7 → 0.0.8
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/knowledge/backendConstraints.js +3 -0
- package/dist/knowledge/componentCatalog.js +59 -15
- package/dist/knowledge/normalize.js +459 -23
- package/dist/knowledge/propTypes.js +5 -4
- package/dist/knowledge/rules.js +110 -5
- package/dist/knowledge/styleResolve.js +6 -1
- package/dist/platform/http.js +10 -2
- package/dist/platform/screenshot.js +80 -8
- package/dist/platform/strictArguments.js +32 -0
- package/dist/platform/writeDiff.js +6 -3
- package/dist/resources/examples/page-sign-in.json +1 -1
- package/dist/resources/guides/component.md +1 -1
- package/dist/resources/guides/expressions.md +6 -0
- package/dist/resources/guides/getting-started.md +2 -0
- package/dist/resources/guides/layout.md +6 -0
- package/dist/resources/guides/microservice.md +105 -5
- package/dist/resources/guides/page.md +81 -18
- package/dist/resources/guides/translation.md +11 -10
- package/dist/resources/guides/workflow.md +50 -1
- package/dist/resources/schema-fingerprint.json +2 -2
- package/dist/resources/schemas/CreateMicroserviceCommand.json +4 -1
- package/dist/resources/schemas/CreateWorkflowCommand.json +4 -1
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +4 -1
- package/dist/resources/schemas/PreviewWorkflowCommand.json +4 -1
- package/dist/resources/schemas/StepDto.json +4 -1
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +4 -1
- package/dist/resources/schemas/UpdateWorkflowCommand.json +4 -1
- package/dist/server.js +2 -1
- package/dist/tools/flows.js +9 -3
- package/dist/tools/layouts.js +4 -4
- package/dist/tools/microservices.js +70 -6
- package/dist/tools/pages.js +127 -57
- package/dist/tools/queries.js +72 -6
- package/dist/tools/workflows.js +9 -5
- package/package.json +1 -1
|
@@ -77,6 +77,12 @@ servis formunda görünür ve `microservice_get` outline görünümünde geri ok
|
|
|
77
77
|
> (`'all'`) ve SQL'de ona bakan bir dal. Aynı davranış workflow query adımında da geçerli;
|
|
78
78
|
> oradaki anlatım `platform_guide('workflow')` "Query adımı" bölümünde.
|
|
79
79
|
>
|
|
80
|
+
> **`(@p = '' OR kolon = @p)` YAZMA** — "filtre boşsa hepsini getir" dalı hiçbir zaman
|
|
81
|
+
> çalışmaz, çünkü boş değer `NULL` bağlanır. Değeri form bileşeninden gelen parametrede
|
|
82
|
+
> dokunulmamış alanın `null` ya da `''` göndermesi fark etmez; ikisi de `NULL` olur
|
|
83
|
+
> (2026-09-15 bulgusu: pano 0 kart, `COALESCE`/`IS NULL` ile 141). Gateway bu kalıbı
|
|
84
|
+
> `query_create`/`query_update`/`query_preview`'da **QRY-007** (warn) ile işaretler.
|
|
85
|
+
>
|
|
80
86
|
> **KAPSAM UYARISI: query kaynaklı ucun parametreleri ÇAĞRIDAN gelir.** Middleware'in
|
|
81
87
|
> kurduğu `user` bu yola girmez — kimlik/tenant kapsamını gövdeye yazan bir uç
|
|
82
88
|
> sahtelenebilir (ölçüldü 2026-09-07). Kapsam sunucuda zorlanacaksa sorguyu bir workflow
|
|
@@ -116,6 +122,11 @@ servis formunda görünür ve `microservice_get` outline görünümünde geri ok
|
|
|
116
122
|
5. **Doğrulama akışı:** `microservice_preview` (kaydetmeden) → kaydet → `microservice_execute`
|
|
117
123
|
(gerçek runtime yolu) → sonuç beklenmedikse **aynı parametrelerle `microservice_debug`** —
|
|
118
124
|
adım adım executionItems ağacı döner.
|
|
125
|
+
Çağrı parametrelerini (sorgu parametresi, filtre değeri) üst düzey `parameters: { ad: değer }`
|
|
126
|
+
ile ver; gateway GET'te query-string'e, POST/PUT'ta gövdeye koyar. Değeri NULL bağlanan query
|
|
127
|
+
parametresini debug yanıtı `unboundParameters` ile söyler — ağaçta o satırın `value` anahtarı
|
|
128
|
+
görünmez. Tool'un tanımadığı bir üst düzey argüman artık reddedilir (GW-005); 2026-09-15'e
|
|
129
|
+
kadar `parameters` hata vermeden atılıyordu ve dört farklı filtre aynı gövdeyi döndürdü (G-13).
|
|
119
130
|
|
|
120
131
|
## Yanıt sözleşmesi (DTO) uca DEĞİL workflow'a bağlanır (MS-018, block)
|
|
121
132
|
|
|
@@ -159,8 +170,9 @@ DTO'dan süzülmez (WF-026 — `platform_guide('workflow')` §Hata yolu). Sözle
|
|
|
159
170
|
## Asgari doğru table-source microservice (platformda doğrulanmış kurallar)
|
|
160
171
|
|
|
161
172
|
- `operation` enum'u **tam olarak** şudur ([MicroserviceTableOperation](../../../../zeyrek-backend/src/NgApps.Domain/Contexts/Studio/Microservices/MicroserviceTableOperation.cs)):
|
|
162
|
-
`get · create · update · delete · upsert · count
|
|
163
|
-
`operation: 'get'` + `isSingle: false`, tek kayıt için
|
|
173
|
+
`get · create · update · delete · upsert · count · bulk-create · bulk-update · bulk-delete`.
|
|
174
|
+
**`list` yoktur** — liste için `operation: 'get'` + `isSingle: false`, tek kayıt için
|
|
175
|
+
`isSingle: true`.
|
|
164
176
|
- **`upsert` vardır ve tercih edilmelidir.** Aynı formun hem yeni kayıt hem düzenleme
|
|
165
177
|
yapmasını iki ayrı uç + akışta condition dallanmasıyla kurmayın: tek `operation: 'upsert'`
|
|
166
178
|
ucu yeterlidir. Aynı işlem workflow **table step**'inde de desteklenir
|
|
@@ -174,9 +186,42 @@ DTO'dan süzülmez (WF-026 — `platform_guide('workflow')` §Hata yolu). Sözle
|
|
|
174
186
|
|
|
175
187
|
> **Upsert'te üretilen alan tuzağı.** `operation: 'upsert'` UPDATE yolunda da alan ifadelerini
|
|
176
188
|
> yeniden değerlendirir; sicil/kod gibi üretilen bir değeri `source: 'expression'` ile yazarsan
|
|
177
|
-
> güncellemede **sessizce değişir** (İK koşusu M-3: EMP-0005 → EMP-0006).
|
|
178
|
-
>
|
|
179
|
-
>
|
|
189
|
+
> güncellemede **sessizce değişir** (İK koşusu M-3: EMP-0005 → EMP-0006). Çözüm alan bazlı
|
|
190
|
+
> **`writeOn: create | update | always`**'dir (varsayılan `always`) ve 2026-09-04'ten beri
|
|
191
|
+
> platformdadır: üretilen alana `writeOn: 'create'` verirsen upsert'in UPDATE dalı o alanı satıra
|
|
192
|
+
> hiç koymaz (`ToRow(entityDto, writeOn)` iki satırı ayrı kurar). `writeOn` YALNIZ
|
|
193
|
+
> `operation: 'upsert'` ucunda anlamlıdır — başka operasyonda `always` dışında bir değer
|
|
194
|
+
> **MS-017** ile reddedilir. Gateway **MS-016** ile uyarır; alan `writeOn: 'create'` taşıyorsa
|
|
195
|
+
> susar. **`writeOn` bir "kısmi güncelleme" bayrağı DEĞİLDİR** — hangi DALIN yazacağını söyler,
|
|
196
|
+
> "gövdede gelmeyen alanı atla" demez (aşağıdaki §Güncelleme sözleşmesi).
|
|
197
|
+
- **Toplu yazma için `bulk-create` / `bulk-update` / `bulk-delete` vardır.** Aynı tabloya N satır
|
|
198
|
+
yazmak için akışta döngü kurmayın: bu üç uç gövdedeki **JSON diziyi** tek çağrıda işler
|
|
199
|
+
([TableMicroserviceExecutor](../../../../zeyrek-backend/src/NgApps.Domain/Contexts/Studio/Microservices/Executors/TableMicroserviceExecutor.cs)).
|
|
200
|
+
Kurallar:
|
|
201
|
+
- Gövde bir **dizi** olur; her eleman bir satırdır. `bulk-delete` gövdesinde yalnız birincil
|
|
202
|
+
anahtar alanı aranır ve tek bir `IN` filtresine çevrilir.
|
|
203
|
+
- `filters` **kullanılmaz** — satırlar ve anahtarlar gövdeden okunur.
|
|
204
|
+
- Tek istekte en fazla **1000 satır** (`EntityConstants.BulkRowLimit`); aşılırsa
|
|
205
|
+
`BulkRowLimitException` (422).
|
|
206
|
+
- Parti **hep-ya-hiç**tir: bir satır doğrulamadan geçmezse `BulkRowFailedException` hangi
|
|
207
|
+
satırın (index) patladığını söyler ve hiçbir satır yazılmaz.
|
|
208
|
+
- **Dosya alanı olan tablolarda `bulk-create`/`bulk-update` da desteklenir** — her satırın
|
|
209
|
+
dosya (ve çoka-çok dosya) alanı, tekil `create`/`update` ile **aynı format** üzerinden
|
|
210
|
+
(`{ type, fileName, value, clone, override, id }`) satır satır `fileService`'e gönderilir;
|
|
211
|
+
artık dosya alanı yüzünden 422 dönmez. Aynı entegrasyon workflow **table step**'inde de
|
|
212
|
+
vardır (satır dizisindeki dosya değeri de aynı formatı izler).
|
|
213
|
+
- **Bulk upsert yoktur.**
|
|
214
|
+
- `bulk-update` gövdesinde birincil anahtar **bulunur ve zorunludur** — tekil `update`'in
|
|
215
|
+
aksine satırı belirleyen filtre değil, gövdedeki anahtardır. `UpdateRowsAsync` bu anahtarı
|
|
216
|
+
`SET` listesinden dışlayıp `WHERE`'e taşır, bu yüzden alan listesinde görünmesi doğrudur ve
|
|
217
|
+
GENERATED ALWAYS koruması onu es geçer.
|
|
218
|
+
- Workflow **table step**'inde de aynı üç işlem vardır; orada satır dizisi adımın `expression`
|
|
219
|
+
alanından (JS) gelir, gövdeden değil. **Ancak studio'nun workflow table formunda bu
|
|
220
|
+
`expression` alanı için editör henüz yoktur** — akış adımında bulk seçilirse satır dizisi
|
|
221
|
+
girilemez ve adım `MissingParameterException` ile düşer. v1'de bulk yalnız microservice
|
|
222
|
+
ucundan kullanılır.
|
|
223
|
+
- Adımda tanımlı ama değeri boş bırakılan alanlar gövdeden/expression'dan gelen veriyi
|
|
224
|
+
**ezmez**; yalnız değeri dolu olan sabitler her satıra uygulanır.
|
|
180
225
|
- **`count` vardır** — kayıt sayısı için tüm satırları çekip uzunluğuna bakmayın; panel/KPI
|
|
181
226
|
sayaçlarının doğru şekli budur.
|
|
182
227
|
- Gövde kökünde **`entityId` zorunlu**. (Eski "kökte datasourceId zorunlu" bilgisi yanlıştı —
|
|
@@ -233,6 +278,61 @@ DTO'dan süzülmez (WF-026 — `platform_guide('workflow')` §Hata yolu). Sözle
|
|
|
233
278
|
}
|
|
234
279
|
```
|
|
235
280
|
|
|
281
|
+
## Güncelleme sözleşmesi: yazılan alan kümesi TANIMDAN gelir, gövdeden DEĞİL
|
|
282
|
+
|
|
283
|
+
`create` / `update` / `upsert` ucunda **SET listesi `fields[]`'tir**; gövde yalnız o alanların
|
|
284
|
+
DEĞERİNİ taşır. Studio'daki karşılığı "Oluşturulacak veya güncellenecek alanlar" ekranındaki
|
|
285
|
+
**İstek alanları** listesidir: önce hangi alanların yazılacağı seçilir, gövde sonra gelir.
|
|
286
|
+
İki yön de sessizdir, ikisi de 200 döner (ölçüm: 2026-09-15, `emrah/test`, `development`):
|
|
287
|
+
|
|
288
|
+
| Tanımda (`fields[]`) | Gövdede | Sonuç |
|
|
289
|
+
|---|---|---|
|
|
290
|
+
| alan **var** | anahtar **yok** | kolona **NULL yazılır** — eski değer silinir |
|
|
291
|
+
| alan **var** | anahtar var | değer yazılır |
|
|
292
|
+
| alan **yok** | anahtar var | **yok sayılır** — o alan bu uçtan hiç değiştirilemez |
|
|
293
|
+
|
|
294
|
+
Kod yolu: gövdede anahtar yoksa alan `null` değerini alır
|
|
295
|
+
(`MicroserviceRuntimeCacheDto.SetSourceEntityFieldAndFilterValue`, `:145-148`), `ToRow` Default
|
|
296
|
+
modlu **bütün** alanları sözlüğe basar (`:169-175`) ve `UpdateRowAsync` SET listesini doğrudan o
|
|
297
|
+
sözlüğün anahtarlarından kurar (`PostgreSqlEntityConnector.cs:262-273`; null → `DBNull.Value`).
|
|
298
|
+
"Yalnız gövdede gelen alanı yaz" diye bir bayrak **yoktur**.
|
|
299
|
+
|
|
300
|
+
Ölçülen üç vaka (`pu_test`: `title` · `owner` · `status`):
|
|
301
|
+
|
|
302
|
+
| # | Uç tanımı | Gövde | Sonuç |
|
|
303
|
+
|---|---|---|---|
|
|
304
|
+
| 1 | `fields: [title, owner, status]` | `{ id, status: 'done' }` | 200 — `status` değişti, **`title` ve `owner` NULL** oldu (`entity_audit_trails` ikisini de yalnız `previousValue` ile gösteriyor) |
|
|
305
|
+
| 2 | `fields: [status]` | `{ id, status, title: '…', owner: '…' }` | 200 — yalnız `status` değişti; listelenmeyen iki alan **yazılmadı** |
|
|
306
|
+
| 3 | `fields: [title, owner, status]`, `status` kolonu NOT NULL | `{ id, title }` | **400 `RowValidationFailed`** ("Please complete all required fields") — satır hiç değişmedi |
|
|
307
|
+
|
|
308
|
+
Yani kolon `nullable` ise kayıp **sessizdir**, NOT NULL ise istek **gürültülü** düşer. Kanban'da
|
|
309
|
+
kart sürüklemek, satır içi tek alan düzenlemek, "arşivle" düğmesi — hepsi 1. satırın tuzağıdır:
|
|
310
|
+
kart doğru sütuna geçer, başlığı ve sorumlusu silinir.
|
|
311
|
+
|
|
312
|
+
### Kısmi güncellemenin üç doğru yolu
|
|
313
|
+
|
|
314
|
+
1. **Eylem başına uç (varsayılan tercih).** Kartı taşıyan uç yalnız `status` yazar, başlığı
|
|
315
|
+
düzenleyen uç yalnız `title`: `fields[]` = o eylemin gerçekten yazdığı alanlar. Fazladan okuma
|
|
316
|
+
yok, eşzamanlı düzenlemede birbirini ezme yok, yetki yüzeyi de dar kalır (2. ölçüm bunun
|
|
317
|
+
kanıtıdır — uç, gövdeye konan `title`/`owner`'ı yok sayar).
|
|
318
|
+
2. **Tam form ucunda gövde de tam olur.** Düzenleme formu kaydediyorsa gövde `fields[]`'teki HER
|
|
319
|
+
alanı taşır; kullanıcının dokunmadığı alan da forma yüklendiği hâliyle geri gönderilir. Uçta
|
|
320
|
+
yapılacak bir şey yoktur — eksik gönderen istemci alanı siler.
|
|
321
|
+
3. **Oku-birleştir (alan kümesi ancak çağrı anında belliyse).** Akışta önce `table get`, sonra
|
|
322
|
+
`table update`; gelmeyen alan okunan değere düşer:
|
|
323
|
+
|
|
324
|
+
```js
|
|
325
|
+
typeof input.title !== 'undefined' && input.title !== null ? input.title : read_row.data.title
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Ölçüldü: `{ id, status }` gövdesiyle `title` ve `owner` korundu, `status` yazıldı. Bedeli iki
|
|
329
|
+
veritabanı turu ve **son yazan kazanır** — okuma ile yazma arasında başkasının yazdığı alan
|
|
330
|
+
geri alınır. Bu yüzden 1. yol varken bu yola girilmez.
|
|
331
|
+
|
|
332
|
+
> Aynı kural workflow **table step**'inde birebir geçerlidir; orada değer gövdeden değil
|
|
333
|
+
> ifadeden gelir ve `undefined` dönen ifade de `null` yazar —
|
|
334
|
+
> `platform_guide('workflow')` §"Table update adımı".
|
|
335
|
+
|
|
236
336
|
## İlişki alanı: `row_list` NESNE döner, uç/step JOIN'siz DÜZ FK döner
|
|
237
337
|
|
|
238
338
|
Aynı alan iki yoldan farklı şekilde gelir ve bu fark sessizce yanlış sonuç üretir:
|
|
@@ -78,16 +78,18 @@ mümkündür ama doğrulama duvarı ve canlı canvas yalnız `page_schema_patch`
|
|
|
78
78
|
her turda çözümlenmiş metinle EZER — anahtar yalnız `ref`'te yaşar, `data`'ya yazıp
|
|
79
79
|
güvenme (`code` prop'uyla aynı davranış). Tam şekil, fallback zinciri ve `translation_*`
|
|
80
80
|
tool'ları için `platform_guide('translation')`.
|
|
81
|
-
- **Kurulmuş bir düğümün prop TİPİNİ
|
|
81
|
+
- **Kurulmuş bir düğümün prop TİPİNİ yerinde değiştir — düğümü yeniden KURMA.** İki eş yol var:
|
|
82
|
+
`{ op: 'replace_prop', target: '<elementId>', prop: 'content', value: { type: 'translation', ref: 'dashboard.kpi.total' } }`
|
|
83
|
+
(applier `code` ve `translation` sarmalını tipiyle korur; gateway 2026-09-15'e kadar translation
|
|
84
|
+
sarmalını reddediyordu) ya da
|
|
82
85
|
`{ op: 'set_prop_type', target: '<elementId>', prop: 'content', propType: 'translation', ref: 'dashboard.kpi.total' }`
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
gönderilmeden reddedilir ve `page_schema_validate` aynı kararı verir.
|
|
86
|
+
(gateway emülasyonu; mevcut `data`'yı tasarım yedeği olarak taşır). Taşıyıcı alan tipe göre
|
|
87
|
+
değişir — `static` değeri `data`'da, `code` ve `translation` `ref`'te taşır; eksik taşıyıcı istek
|
|
88
|
+
gönderilmeden reddedilir ve `page_schema_validate` aynı kararı verir. Eski yol
|
|
89
|
+
`remove_component` + `add_component` idi: 2026-09-06 koşusunda on bir etiket bu yolla kuruldu ve
|
|
90
|
+
onlara yazan **dokuz setter iteratee'si** sessizce silindi; 2026-09-15'te (G-04) aynı zincir bir
|
|
91
|
+
`daterangepicker` yer tutucusunu çeviriye bağlarken tekrarlandı — setter hedefi elementId değil
|
|
92
|
+
komponentin iç kimliğidir (aşağıda Kural 2, `FLOW-018`).
|
|
91
93
|
|
|
92
94
|
- **`blocks[].size`, komponentin `component_get`'teki `maxSize`'ını aşamaz.** Dikkat: katalog
|
|
93
95
|
varsayılanı aşabiliyor (`page-header` default `h:8`, `maxSize` `h:4`) — varsayılanı körü körüne
|
|
@@ -394,6 +396,14 @@ göstermek error flow'un işidir.
|
|
|
394
396
|
> "branches": [{ "id": "<GUID>", "name": "always", "nextStepId": null }] }
|
|
395
397
|
> ```
|
|
396
398
|
|
|
399
|
+
> **`confirm` adımının diyalog çerçevesi de yazılabilir.** `args` dört düz metin alanı taşır:
|
|
400
|
+
> `message` (gövde), `title` (başlık), `confirmText` (onay düğmesi, `yes` dalı), `cancelText`
|
|
401
|
+
> (vazgeç düğmesi, `no` dalı). Son üçü isteğe bağlıdır; boş bırakılan alan dile göre sabit metne
|
|
402
|
+
> düşer ("Emin misiniz?" / "Evet" / "Hayır" — `dialog.functions.ts` `resolveDialogFrame`).
|
|
403
|
+
> Dördü de `alert`'in `message`'ı gibi DÜZ METİNDİR (FLOW-022 hepsini denetler):
|
|
404
|
+
> `{ "type": "confirm", "args": { "message": "Bu risk ve 4 aksiyonu silinecek.", "title": "Riski sil",
|
|
405
|
+
> "confirmText": "Sil", "cancelText": "Vazgeç" } }`.
|
|
406
|
+
|
|
397
407
|
> **Hangi yolu seçeceksin — `errorSteps` mi, ana akışta `condition` mı?** İkisi birden
|
|
398
408
|
> kurulamaz (yukarıdaki 1. madde), yani bu bir tercih değil bir karar:
|
|
399
409
|
>
|
|
@@ -893,6 +903,16 @@ Beş şeyi bilmeden flex kurma:
|
|
|
893
903
|
aradaki boşluklar çizilmez. Yine de bitişik ver (0,1,2…): kapsayıcı ileride `grid`'e
|
|
894
904
|
döndürülürse şema geçerli kalsın. Gateway bu yüzden **flex kapsayıcının İÇİNDE PAGE-010
|
|
895
905
|
boşluk uyarısı üretmez** (ızgarada üretmeye devam eder).
|
|
906
|
+
**Dizi sırası çizimi belirlemez** — `children[]` içindeki yer değil `y` kazanır; `y`'si eşit
|
|
907
|
+
iki çocukta dizi sırası kazanır. Bu yüzden flex kapta sıralamanın yolu `index`'tir:
|
|
908
|
+
`add_component`/`move_component`'e verilen `index` **görünen sıradaki yeri** belirler ve gateway
|
|
909
|
+
kardeşlerin konumunu Studio'nun flex tuvali gibi yeniden yazar (x=0, alt alta birikimli y;
|
|
910
|
+
yanıtın `gatewayNormalized` notu hangi `y`'nin değiştiğini söyler). Grafiğin üstüne başlık:
|
|
911
|
+
`{ "op": "add_component", "parent": "<flex kap>", "index": 0, "component": { … } }` — koordinat
|
|
912
|
+
hesaplamak gerekmez, `remove_component` + `add_component` hiç gerekmez. **Izgara kapta `index`
|
|
913
|
+
çizimi değiştirmez** (her çocuk kendi `position`'ında mutlak çizilir): sırayı
|
|
914
|
+
`move_component { target, position: { x, y } }` ile ver; sona eklemeyen `index` orada
|
|
915
|
+
**PAGE-033 (uyarı)** üretir.
|
|
896
916
|
3. **Flex kapsayıcının yüksekliği içeriğine oturur.** `verticalAlign`'ın dağıtacak boşluğu
|
|
897
917
|
olması için `appearance.heightType: 'fixed'` vermelisin — ölçü `heightString`'den
|
|
898
918
|
(serbest CSS uzunluğu, ör. `"30vh"`), o yoksa `size.h × 10px`'ten gelir. `heightString`
|
|
@@ -1010,7 +1030,8 @@ UYGULAMAZ** — koordinatları aynen kaydeder (aşağı itme yalnız `page_creat
|
|
|
1010
1030
|
> sarmalayıcıya bağla (yukarıdaki `box_multi`). Sarmalayıcıyı **`isWrapper:false`** kur
|
|
1011
1031
|
> (Kural 1f: wrapper = `min-height:80vh`) ve çerçevesini `style` ile kapat:
|
|
1012
1032
|
> `{ background:'transparent', border:'none', '&__body': { padding:'0px' } }`.
|
|
1013
|
-
> `appearance.isHidden` diye bir
|
|
1033
|
+
> `appearance.isHidden` diye bir alan YOKTUR (2026-09-15'te platformdan kaldırıldı, S-16) —
|
|
1034
|
+
> görünürlük yalnız `props.isHidden`'dır.
|
|
1014
1035
|
|
|
1015
1036
|
> **Satır BAŞINA doğrulama kurulamaz.** `validations` komponentin kendisindedir, tüm satırlar
|
|
1016
1037
|
> onu paylaşır — "3. soru zorunlu, 4. soru değil" şemayla ifade edilemez. Zorunluluk satır
|
|
@@ -1559,6 +1580,19 @@ alanına dokunur. **Komponenti silip yeniden eklemeyin:** `remove_component` + `
|
|
|
1559
1580
|
turu o komponente bağlı setter hedeflerini koparır (Kural 1e sonundaki not) ve komponentin tek
|
|
1560
1581
|
referans verdiği akışları kalıcı olarak sildirir (Kural 2'deki yan etki notu).
|
|
1561
1582
|
|
|
1583
|
+
**Kurulu düğümün appearance'ını değiştirmek: `set_appearance`.** Aynı gerekçeyle appearance için
|
|
1584
|
+
de silip yeniden ekleme gerekmez:
|
|
1585
|
+
|
|
1586
|
+
```jsonc
|
|
1587
|
+
{ "op": "set_appearance", "target": "box_summary", "appearance": { "heightType": "auto", "tooltip": null } }
|
|
1588
|
+
```
|
|
1589
|
+
|
|
1590
|
+
Op **birleştirir**: yalnız verilen alanları yazar, gerisini korur; `null` alanı temizler. Alan
|
|
1591
|
+
adları `page_schema_get`'in döndürdüğü appearance anahtarlarıdır; bilinmeyen alan
|
|
1592
|
+
`unknown-appearance-field`, tanınmayan enum değeri (`heightType: "tall"`) 400 ile reddedilir.
|
|
1593
|
+
**`isHidden` bir appearance alanı DEĞİLDİR** — gizlemek için `replace_prop { prop: 'isHidden' }`
|
|
1594
|
+
ya da `set_binding { prop: 'isHidden' }` (Kural 7a'daki `isHidden` notu).
|
|
1595
|
+
|
|
1562
1596
|
**Kip ayrımı query parametresidir:** aynı sayfa `?id=<kayıt>` ile edit, parametresiz create.
|
|
1563
1597
|
|
|
1564
1598
|
`mount` akışı (`page_container` ya da `form` üzerine bağlanır):
|
|
@@ -1671,10 +1705,12 @@ start → [setter] btn_save.isLoading = true
|
|
|
1671
1705
|
> artık doğrudan `props.isHidden` yazılabilir; sırf gizlemek için `container`'a sarmak
|
|
1672
1706
|
> GEREKMEZ. Tek doğru kaynak `component_get` + `page_schema_validate` kuru koşusudur.
|
|
1673
1707
|
>
|
|
1674
|
-
>
|
|
1675
|
-
>
|
|
1676
|
-
>
|
|
1677
|
-
>
|
|
1708
|
+
> **Appearance'ta `isHidden` alanı YOKTUR** (2026-09-15'te platformdan kaldırıldı, S-16): renderer
|
|
1709
|
+
> yalnız `props.isHidden`'a bakar. Başlangıçta gizli bildirim şemada
|
|
1710
|
+
> `"props": { "isHidden": { "type": "static", "data": true } }` ile kurulur, açılışı akıştaki
|
|
1711
|
+
> setter yapar. `add_component` / `page_update` gövdesine yine de `appearance.isHidden` konursa
|
|
1712
|
+
> gateway değeri `props.isHidden`'a taşır ve `gatewayNormalized`'da bildirir (prop zaten verilmişse
|
|
1713
|
+
> o kazanır); `set_appearance` ile `isHidden` yazmak istek gönderilmeden reddedilir.
|
|
1678
1714
|
|
|
1679
1715
|
### 7b — Liste → form geçişi
|
|
1680
1716
|
|
|
@@ -1864,6 +1900,18 @@ hiçbiri** bağlı değildi; üç portalın da rol menüsü boş çıkıyor, pan
|
|
|
1864
1900
|
> hiç görünmeyen düğüm var; `zeroSized` çizilmemiş komponenti gösterir. Runtime düğümleri
|
|
1865
1901
|
> `data-element-id` basmıyorsa yanıt `layoutReportUnavailable` der — tool tahmin üretmez.
|
|
1866
1902
|
>
|
|
1903
|
+
> **Sürükle-bırakı gerçekten sınamak (G-09).** `kanban` ve `eventcalendar` iç öğelerine
|
|
1904
|
+
> `<elementId>__<rol>` kimliği yazar (tablonun `__row-<n>`'i ile aynı kalıp):
|
|
1905
|
+
> kart `kb_board__card-<id>`, kolon `kb_board__col-<value>`; etkinlik `cal_plan__event-<id>`,
|
|
1906
|
+
> gün `cal_plan__day-<yyyy-MM-dd>`, tüm gün hücresi `cal_plan__allday-<yyyy-MM-dd>`, saat dilimi
|
|
1907
|
+
> `cal_plan__slot-<yyyy-MM-dd>T<HH>`. `id`, `idField`'ın değeridir (yoksa `card-<sıra>` /
|
|
1908
|
+
> `event-<sıra>`); tarih yereldir. Tıklama yolu `click` ile, taşıma `drag` ile sınanır:
|
|
1909
|
+
> `actions: [{ action:'drag', target:'kb_board__card-42', to:'kb_board__col-Assigned' }]`.
|
|
1910
|
+
> `actionsReport[].flowRuns`/`requests` sıfırsa `cardMove`/`eventMove` bağı kurulu görünse de
|
|
1911
|
+
> taşıma kalıcılaşmamıştır. Kaynak `draggable` değilse (`isDraggable`/`isEditable` kapalı)
|
|
1912
|
+
> adım `applied:false` ve notla döner. Çok günlü etkinlik aynı kimliği her gün hücresinde taşır;
|
|
1913
|
+
> hedef ilk eşleşmedir.
|
|
1914
|
+
>
|
|
1867
1915
|
> **Üye kimliğiyle doğrulama (`asUser`).** Kapının kapalı olduğunu görmek yarısıdır; açık
|
|
1868
1916
|
> olduğunu görmek diğer yarısı. `page_runtime_get` ve `page_screenshot` aynı `asUser` alanını
|
|
1869
1917
|
> alır: uygulamanın kendi giriş ucundan (`microservice_execute`) aldığın üye jetonunu verirsin,
|
|
@@ -1951,10 +1999,22 @@ micro-op hattına dönün.
|
|
|
1951
1999
|
>
|
|
1952
2000
|
> **Gateway artık bunu söylüyor (FLOW-018).** `remove_component` içeren bir yamada gateway sayfanın
|
|
1953
2001
|
> akışlarını okur ve silinen düğümü hedefleyen setter adımlarını uyarı olarak listeler: hangi akış,
|
|
1954
|
-
> hangi adım, hangi hedef.
|
|
1955
|
-
> yeniden kaydetmektir. Ters yönü (`silinen düğümün referans verdiği` akışların platformca kalıcı
|
|
2002
|
+
> hangi adım, hangi hedef. Ters yönü (`silinen düğümün referans verdiği` akışların platformca kalıcı
|
|
1956
2003
|
> silinmesi) ayrı bir uyarı kapsar; ikisi birlikte çıkabilir. Ölçüm 2026-09-04 (benchmark 4. koşu):
|
|
1957
2004
|
> uyarı yokken aynı tuzak ~8 dakika teşhis aldı ve yalnız ekran görüntüsüyle görüldü.
|
|
2005
|
+
>
|
|
2006
|
+
> **Mekanizma ve onarım (2026-09-15, G-04).** Setter iteratee'si hedefini elementId olarak DEĞİL,
|
|
2007
|
+
> komponentin iç kimliği olarak saklar (`step_iterates.DesignComponentId`, FK `SetNull`); düğüm
|
|
2008
|
+
> yeni kimlikle yazılınca eski satır silinir ve alan boşalır — `flow_get` iteratee'yi `element`'siz
|
|
2009
|
+
> döndürür. Bu yüzden **`flow_get`'ten okunan gövdeyi aynen yeniden kaydetmek onarmaz** (element
|
|
2010
|
+
> zaten yok; `flow_update` FLOW-017'ye takılır). İki güvence var: (1) backend artık AYNI yamada
|
|
2011
|
+
> silinip aynı `elementId` ile eklenen düğüme (alt ağaç dahil) eski kimliğini geri veriyor, bağ
|
|
2012
|
+
> kopmuyor; (2) gateway yamadan sonra akışları yeniden okur ve kopan her iteratee için yanıtta
|
|
2013
|
+
> `flowTargetsLost` ile hazır onarımı verir:
|
|
2014
|
+
> `flow_patch` `{ op: 'add', path: '/steps[stepId=s4]/args/iteratees/0/element', value: 'f_range' }`.
|
|
2015
|
+
> `flow_get` de hedefsiz setter iteratee'sini `flowWarnings` (`FLOW-017 (okuma)`) ile gösterir.
|
|
2016
|
+
> Ayrı isteklerle (önce sil, sonra ekle) yapılan yeniden kurulum ve komple şema yazan `page_update`
|
|
2017
|
+
> bu korumanın DIŞINDADIR — prop tipini değiştirmek için düğümü hiç yeniden kurmayın.
|
|
1958
2018
|
|
|
1959
2019
|
## Bilinen sınırlar
|
|
1960
2020
|
|
|
@@ -2029,8 +2089,11 @@ micro-op hattına dönün.
|
|
|
2029
2089
|
(süssüz) ekrana ifadenin **kendisini** basar; ifade yalnız `data`'da olursa prop **boş**
|
|
2030
2090
|
render edilir. `set_binding` micro-op'u eski sürümlerde `data`'ya yazıyordu — bu davranış
|
|
2031
2091
|
düzeltildi, ama daha önce kurulmuş sayfalarda kalıntı olabilir. Prop nesnesini birebir
|
|
2032
|
-
kontrol etmen gerekirse `
|
|
2033
|
-
`{"type":"code","ref":"{{ … }}"
|
|
2092
|
+
kontrol etmen gerekirse `replace_prop` ile
|
|
2093
|
+
`value: {"type":"code","ref":"{{ … }}"}` yaz — code tipi ve `ref` olduğu gibi kaydedilir
|
|
2094
|
+
(platform code prop'unda `data`'yı saklamaz).
|
|
2095
|
+
`replace_prop`'a `expression` alanı verme: platform onu yalnız `set_binding`'de okur (gateway
|
|
2096
|
+
code sarmalına çevirir).
|
|
2034
2097
|
|
|
2035
2098
|
- **Ana sayfa sayfadan değil application'dan değişir:** `page_create/update` gövdesindeki
|
|
2036
2099
|
`isHomepage` platformca yok sayılır (tasarım). Doğru yol `application_update` →
|
|
@@ -81,22 +81,23 @@ backend'de zaten tanımlı, Studio'nun "Translate" aksiyonunun ürettiği şekil
|
|
|
81
81
|
"value": { "type": "translation", "ref": "home.welcome", "data": "Hoş geldiniz" } }
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
>
|
|
85
|
-
> `
|
|
86
|
-
>
|
|
87
|
-
>
|
|
88
|
-
>
|
|
84
|
+
> **Yukarıdaki `replace_prop` sarmalı olduğu gibi çalışır (2026-09-15, G-04).** Micro-op applier
|
|
85
|
+
> `{type, ref, data}` sözlüğünün tipini korur ve `Translation` Prop'unu `Ref` + metin `Data` ile
|
|
86
|
+
> kurar (`PageSchemaMicroOpApplier.ApplyOne`). Gateway bu kullanımı eskiden reddedip komponenti
|
|
87
|
+
> yeniden eklemeyi öneriyordu; o öneri uygulanınca düğüme yazan setter iteratee'lerinin `element`'i
|
|
88
|
+
> silindi (bir panoda alt başlık ve tarih aralığı boş kaldı). Ref'siz translation sarmalı istek
|
|
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 ve layout ağacında (micro-op hattı yok) tek yoldur:
|
|
89
91
|
>
|
|
90
92
|
> ```jsonc
|
|
91
93
|
> { "op": "set_prop_type", "target": "welcome_text", "prop": "text",
|
|
92
94
|
> "propType": "translation", "ref": "home.welcome" }
|
|
93
95
|
> ```
|
|
94
96
|
>
|
|
95
|
-
>
|
|
96
|
-
>
|
|
97
|
-
>
|
|
98
|
-
>
|
|
99
|
-
> taşıyıcı istek platforma gitmeden reddedilir ve `page_schema_validate` aynı kararı verir.
|
|
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.** Taşıyıcı alan tipe göre değişir: `static` →
|
|
99
|
+
> `data`, `code` ve `translation` → `ref`. Eksik taşıyıcı istek platforma gitmeden reddedilir ve
|
|
100
|
+
> `page_schema_validate` aynı kararı verir.
|
|
100
101
|
>
|
|
101
102
|
> Ölçüldü 2026-09-08 (yerel `dil-dogrulama/dil-app`): kurulu bir `statcard`'ın `title` prop'u tek
|
|
102
103
|
> `set_prop_type` op'uyla `f11.tam` anahtarına bağlandı; gerçek ekranda `tr` → "iki dilde dolu",
|
|
@@ -375,6 +375,22 @@ Tek uçta "başlık + N alt kayıt" yazmanın yolu budur (anket + sorular + seç
|
|
|
375
375
|
başka alana ihtiyacı varsa bunları **`returnFields`** ile iste
|
|
376
376
|
(`{ alias, fieldId, fieldSlug }` öğeleriyle) — `selectFields` write operasyonunda sessizce
|
|
377
377
|
yok sayılır.
|
|
378
|
+
- **Bulk yazma (`bulk-create`/`bulk-update`/`bulk-delete`) table step'te de vardır**, ama tek
|
|
379
|
+
satırlık `create`/`update`'in aksine satır dizisi `fields`'tan değil, adımın **`expression`**
|
|
380
|
+
alanının (JS) sonucundan gelir: `rule.expression` bir **dizi** döndürmeli, dizideki her
|
|
381
|
+
nesnenin anahtarı alan **slug**'ıdır (fieldId değil). `bulk-delete`'te dizi ya birincil anahtar
|
|
382
|
+
değerlerinin düz listesi (`{ value: [...] }` şeklinde tek elemanlı sarmalayıcı) ya da her öğesi
|
|
383
|
+
`{ <pk slug>: <değer> }` olan nesne dizisidir. Tek istekte en fazla 1000 satır
|
|
384
|
+
(`EntityConstants.BulkRowLimit`); aşarsa `BulkRowLimitException`. `fields`'ta tanımlı ve
|
|
385
|
+
**değeri dolu** bir sabit varsa her satıra uygulanır; boş bırakılan alanlar `expression`
|
|
386
|
+
sonucundaki satırı ezmez.
|
|
387
|
+
- **Dosya (ve çoka-çok dosya) alanı `bulk-create`/`bulk-update`'te desteklenir** — microservice
|
|
388
|
+
tarafındaki `bulk-create`/`bulk-update` ile **aynı format**
|
|
389
|
+
(`{ type, fileName, value, clone, override, id }`); her satırın dosya değeri ayrı ayrı
|
|
390
|
+
`fileService`'e yüklenir, dosya alanı olan tabloda bulk artık reddedilmez.
|
|
391
|
+
- **Studio'nun workflow table formunda bulk için `expression` editörü henüz yoktur** — akışı
|
|
392
|
+
UI'dan kurarken bulk operasyonu seçilemez; `rule.expression`'ı JSON/`workflow_patch` ile elle
|
|
393
|
+
yazmak gerekir, yoksa adım `MissingParameterException` ile düşer.
|
|
378
394
|
- **Çıktının ŞEKLİ `isSingle`'a bağlıdır** (ölçüm: 09-04 koşusu Y-15). `isSingle: true` ise
|
|
379
395
|
`<step>.data` nesnedir ve `<step>.data.id` çalışır; **`isSingle: false` ise `data` bir
|
|
380
396
|
DİZİDİR** — `<step>.data.id` `undefined` olur, akış `RowValidationFailed` ile düşer ve hata
|
|
@@ -395,6 +411,38 @@ Tek uçta "başlık + N alt kayıt" yazmanın yolu budur (anket + sorular + seç
|
|
|
395
411
|
> **Gateway table step'lerinde `path`/`sort`/`limit` eksiklerini otomatik dolduruyor**
|
|
396
412
|
> (yanıtta `gatewayNormalized`). Dolu değerlere dokunmaz; yanlış path yine WF/MS block'una takılır.
|
|
397
413
|
|
|
414
|
+
## Table update adımı: yazılan alan kümesi ADIMDAN gelir
|
|
415
|
+
|
|
416
|
+
`operation: 'update'` (aynısı `create`/`upsert`) adımında SET listesi `rule.fields[]`'tir.
|
|
417
|
+
`PrepareParameters` listedeki **her** alanın ifadesini değerlendirir (`TableStep.cs:508-530`),
|
|
418
|
+
`undefined` dönen sonucu `Parse` `null`a çevirir (`CommonFieldType.cs:59`) ve satır sözlüğü
|
|
419
|
+
süzgeçsiz kurulur (`TableStep.ByUpdateAsync`, `:254-262`). İki sonucu vardır:
|
|
420
|
+
|
|
421
|
+
- Gövdede o anahtar yoksa `input.x` **`undefined`**'dır ve kolona **NULL yazılır** — eski değer
|
|
422
|
+
silinir, yanıt yine 200'dür.
|
|
423
|
+
- Adımda listelenmeyen alan hiçbir gövdeyle **değiştirilemez**.
|
|
424
|
+
|
|
425
|
+
Ölçüm (2026-09-15): `fields: [title, owner, status]` olan bir update adımına `{ id, status }`
|
|
426
|
+
gövdesi gitti; uç 200 döndü, `status` değişti, `title` ve `owner` **NULL** oldu. Microservice
|
|
427
|
+
`update` ucuyla birebir aynı davranış; tam tablo ve kısmi güncellemenin üç doğru yolu
|
|
428
|
+
`platform_guide('microservice')` §"Güncelleme sözleşmesi"nde.
|
|
429
|
+
|
|
430
|
+
Gateway bunun tanımdan görülebilen hâlini **WF-031 (warn)** ile keser: yazma adımı akışın giriş
|
|
431
|
+
DTO'sunda OLMAYAN bir `input.x` alanını bağlıyorsa o ifade kesinlikle `undefined` döner ve kural
|
|
432
|
+
eksik alanları adıyla sayar. Uyarıyı susturmanın doğru yolu adımı **eylem başına daraltmaktır**
|
|
433
|
+
(`fields[]` yalnız o eylemin yazdığı alanlar); alanı DTO'ya eklemek yalnız izin verir, çağıranın
|
|
434
|
+
her istekte göndereceğini garanti etmez.
|
|
435
|
+
|
|
436
|
+
Akışta kısmi güncelleme gerekiyorsa **oku-birleştir**: önce `table get`, sonra `table update`,
|
|
437
|
+
gelmeyen alan okunan değere düşsün —
|
|
438
|
+
|
|
439
|
+
```js
|
|
440
|
+
typeof input.title !== 'undefined' && input.title !== null ? input.title : read_row.data.title
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
(ölçüldü: `{ id, status }` gövdesiyle `title`/`owner` korundu). Bedeli fazladan bir okuma turu ve
|
|
444
|
+
**son yazan kazanır**; eylem başına ayrı uç kurmak hâlâ daha ucuz ve daha güvenlidir.
|
|
445
|
+
|
|
398
446
|
## Response step'i gövdeyi `bodyExpression`'dan üretir
|
|
399
447
|
|
|
400
448
|
`rule: { dataTransferObjectId }` **hiçbir şey döndürmez** (`result: null`). Çalışan şekil:
|
|
@@ -615,7 +663,8 @@ Kaydedilen sözleşme üç tüketim yolunda da aynı şekilde bağlanır:
|
|
|
615
663
|
|---|---|
|
|
616
664
|
| `queryStepSourceType: 'library'` (workflow query adımı) | Adımın ifadeleri: `rule.expression` (nesne literali) ya da `rule.queryParameters[]` — ikisi de **JavaScript ifadesidir**; istek girdisini (`input.year`), önceki adım çıktısını **ve bağlı middleware'in `user.*` değişkenini** okur |
|
|
617
665
|
| Query kaynaklı microservice (`source: 'query'`) | Yalnız çağrının kendisi: **body → query-string → header** (`MicroserviceExecuteParameter.FindValue`); ifade YOKTUR, `user.*` bu yola girmez |
|
|
618
|
-
| `query_preview` | `parameters`
|
|
666
|
+
| `query_preview` | Komutun `definition.parameters[].value` alanı; tool'un üst düzey `parameters` argümanı (ad → değer) gateway'de oraya bağlanır. Değer almayan parametre yanıtta `unboundParameters` ile listelenir |
|
|
667
|
+
| `microservice_execute` / `microservice_debug` | Üst düzey `parameters` (ad → değer): gateway GET/DELETE'te query-string'e, POST/PUT'ta gövdeye koyar — yukarıdaki query kaynaklı uç satırının okuduğu yer. `microservice_debug` NULL bağlanan parametreyi `unboundParameters` ile adıyla verir |
|
|
619
668
|
|
|
620
669
|
> **Boş string parametre `NULL`'a çevrilir.** `Query.NormalizePreviewParameters` değeri normalize
|
|
621
670
|
> ederken boş ya da yalnız boşluktan oluşan değeri `null` yapar. `WHERE status = {{durum}}` yazıp
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"hash": "
|
|
3
|
-
"generatedAt": "2026-09-
|
|
2
|
+
"hash": "cafe3a6b082c7828cece4eaa1c0115ba28581f157eac3288abcf068c7f6f8533",
|
|
3
|
+
"generatedAt": "2026-09-15T10:24:42.398Z",
|
|
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
|
@@ -19,6 +19,7 @@ import { registerKnowledgeResources } from './resources/knowledge.js';
|
|
|
19
19
|
import { registerSchemaResources } from './resources/schemas.js';
|
|
20
20
|
import { registerRuleResources } from './resources/rules.js';
|
|
21
21
|
import { instrumentServer } from './observability/trace.js';
|
|
22
|
+
import { rejectUnknownArguments } from './platform/strictArguments.js';
|
|
22
23
|
import { registerProjectTools } from './tools/projects.js';
|
|
23
24
|
import { registerEntityTools } from './tools/entities.js';
|
|
24
25
|
import { registerDependencyTools } from './tools/dependencies.js';
|
|
@@ -72,7 +73,7 @@ const moduleRegistrations = {
|
|
|
72
73
|
revision: registerRevisionTools
|
|
73
74
|
};
|
|
74
75
|
export function createGatewayServer(platform) {
|
|
75
|
-
const server = instrumentServer(new McpServer({ name: 'ngapps', version: '0.1.0' }), platform.config);
|
|
76
|
+
const server = rejectUnknownArguments(instrumentServer(new McpServer({ name: 'ngapps', version: '0.1.0' }), platform.config));
|
|
76
77
|
for (const moduleName of platform.config.modules) {
|
|
77
78
|
moduleRegistrations[moduleName](server, platform);
|
|
78
79
|
}
|
package/dist/tools/flows.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { fetchHost, flowPath, hostParam, hostUpdateBody, unwrap } from './screens.js';
|
|
2
2
|
import { guid, projectParam, environmentParam, readOnly, writes, updates, destructive, microOps } from './common.js';
|
|
3
3
|
import { evaluatePolicy, enforcePolicy, attachFindings } from '../knowledge/policy.js';
|
|
4
|
-
import { normalizeFlowSteps, unknownSetterTargetWarnings, withNormalization } from '../knowledge/normalize.js';
|
|
4
|
+
import { normalizeFlowSteps, targetlessSetterWarnings, unknownSetterTargetWarnings, withNormalization } from '../knowledge/normalize.js';
|
|
5
5
|
import { flowBodyWarnings } from '../knowledge/coverage.js';
|
|
6
6
|
import { PlatformApiError } from '../platform/errors.js';
|
|
7
7
|
import { handle } from '../platform/responses.js';
|
|
@@ -243,10 +243,16 @@ export function registerFlowTools(server, platform) {
|
|
|
243
243
|
}));
|
|
244
244
|
server.registerTool('flow_get', {
|
|
245
245
|
title: 'Akış getir',
|
|
246
|
-
description:
|
|
246
|
+
description: "Tek akışı adımlarıyla getirir; yeni akış yazarken en iyi şablon budur. Hedefi silinmiş (element'siz) setter iteratee'si varsa yanıttaki flowWarnings söyler — o adım koşar ama hiçbir şeye yazmaz.",
|
|
247
247
|
inputSchema: { project: projectParam, environment: environmentParam, host: hostParam, applicationId: guid, hostId: guid, flowId: flowIdParam },
|
|
248
248
|
annotations: readOnly
|
|
249
|
-
}, handle(config, ({ project, environment, host, applicationId, hostId, flowId }) =>
|
|
249
|
+
}, handle(config, async ({ project, environment, host, applicationId, hostId, flowId }) => {
|
|
250
|
+
const response = await platform.tenant('GET', project, flowPath(host, applicationId, hostId, flowId), { environment });
|
|
251
|
+
const warnings = targetlessSetterWarnings(response);
|
|
252
|
+
if (warnings.length === 0 || !response || typeof response !== 'object' || Array.isArray(response))
|
|
253
|
+
return response;
|
|
254
|
+
return { ...response, flowWarnings: warnings };
|
|
255
|
+
}));
|
|
250
256
|
server.registerTool('flow_create', {
|
|
251
257
|
title: 'Akış oluştur',
|
|
252
258
|
description: "Sayfa/layout/komponent için olay akışı oluşturur. Platform bu uçta barındırıcının TAM gövdesini de ister (akış ile şemadaki olay bağı tek işlemde tutarlı kalsın diye); gateway barındırıcıyı okuyup gövdeye kendisi koyar. Akışı bir komponent olayına bağlamak ayrı adımdır: page_schema_patch ile set_event {target, event, eventValue: <flow id>}.",
|
package/dist/tools/layouts.js
CHANGED
|
@@ -2,7 +2,7 @@ import { guid, projectParam, environmentParam, pagingParams, readOnly, writes, u
|
|
|
2
2
|
import { resolvePatchOperations } from '../knowledge/outlines.js';
|
|
3
3
|
import { patchResult, baseVersionOf } from '../platform/patch.js';
|
|
4
4
|
import fastJsonPatch from 'fast-json-patch';
|
|
5
|
-
import { normalizeComponentDefaults, componentDefaultsNote, flexSizeWarnings, verticalGapWarnings, withNormalization } from '../knowledge/normalize.js';
|
|
5
|
+
import { normalizeComponentDefaults, componentDefaultsNote, flexSizeWarnings, spacingLayerWarnings, verticalGapWarnings, withNormalization } from '../knowledge/normalize.js';
|
|
6
6
|
import { fetchHost, layoutUpdateBody, schemaParam, eventsParam, modeParam, summarize, findNode } from './screens.js';
|
|
7
7
|
import { assertScreenWriteGuards, screenCatalogNotes } from './screenWrite.js';
|
|
8
8
|
import { applyPropTypesToSchema, isSetPropTypeOp, setPropTypeErrors } from '../knowledge/propTypes.js';
|
|
@@ -93,7 +93,7 @@ export function registerLayoutTools(server, platform) {
|
|
|
93
93
|
assertScreenWriteGuards('layout', { schema: views, events });
|
|
94
94
|
const fixed = normalizeComponentDefaults(views);
|
|
95
95
|
const catalogNotes = await screenCatalogNotes(platform, project, environment, applicationId, views);
|
|
96
|
-
const gaps = [...verticalGapWarnings(views ?? [], 'LAY-003 (uyarı)'), ...flexSizeWarnings(views ?? [], 'LAY-007 (uyarı)', 'LAY-008 (uyarı)')];
|
|
96
|
+
const gaps = [...verticalGapWarnings(views ?? [], 'LAY-003 (uyarı)'), ...flexSizeWarnings(views ?? [], 'LAY-007 (uyarı)', 'LAY-008 (uyarı)'), ...spacingLayerWarnings(views ?? [], 'LAY-010 (uyarı)', 'LAY-011 (uyarı)')];
|
|
97
97
|
const response = await platform.tenant('POST', project, `/layouts/${applicationId}`, {
|
|
98
98
|
environment,
|
|
99
99
|
body: { name, views: views ?? [], events: events ?? [], parameters: parameters ?? null }
|
|
@@ -126,7 +126,7 @@ export function registerLayoutTools(server, platform) {
|
|
|
126
126
|
const catalogNotes = await screenCatalogNotes(platform, project, environment, applicationId, overrides.views);
|
|
127
127
|
const body = layoutUpdateBody({ ...current, applicationId }, overrides);
|
|
128
128
|
await platform.tenant('PUT', project, `/layouts/${applicationId}/${id}`, { environment, body });
|
|
129
|
-
const gaps = overrides.views === undefined ? [] : [...verticalGapWarnings(body.views, 'LAY-003 (uyarı)'), ...flexSizeWarnings(body.views, 'LAY-007 (uyarı)', 'LAY-008 (uyarı)')];
|
|
129
|
+
const gaps = overrides.views === undefined ? [] : [...verticalGapWarnings(body.views, 'LAY-003 (uyarı)'), ...flexSizeWarnings(body.views, 'LAY-007 (uyarı)', 'LAY-008 (uyarı)'), ...spacingLayerWarnings(body.views, 'LAY-010 (uyarı)', 'LAY-011 (uyarı)')];
|
|
130
130
|
const summary = { id, changed: Object.keys(overrides), preserved: { viewNodes: body.views.length } };
|
|
131
131
|
if (gaps.length > 0)
|
|
132
132
|
summary.layoutWarnings = gaps;
|
|
@@ -193,7 +193,7 @@ export function registerLayoutTools(server, platform) {
|
|
|
193
193
|
body: { baseVersion: baseVersionOf(document, 'layout_get'), ops: netOps }
|
|
194
194
|
});
|
|
195
195
|
const written = patchResult(saved, finalDocument);
|
|
196
|
-
const gaps = [...verticalGapWarnings(body.views, 'LAY-003 (uyarı)'), ...flexSizeWarnings(body.views, 'LAY-007 (uyarı)', 'LAY-008 (uyarı)')];
|
|
196
|
+
const gaps = [...verticalGapWarnings(body.views, 'LAY-003 (uyarı)'), ...flexSizeWarnings(body.views, 'LAY-007 (uyarı)', 'LAY-008 (uyarı)'), ...spacingLayerWarnings(body.views, 'LAY-010 (uyarı)', 'LAY-011 (uyarı)')];
|
|
197
197
|
const summary = {
|
|
198
198
|
id,
|
|
199
199
|
applied: patchOps.length,
|