@appaflytech/zeyrek-ai-mcp 0.0.7 → 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/backendConstraints.js +3 -0
- package/dist/knowledge/componentCatalog.js +172 -33
- package/dist/knowledge/componentEvents.js +35 -4
- package/dist/knowledge/errorPath.js +1 -1
- package/dist/knowledge/normalize.js +474 -23
- package/dist/knowledge/propTypes.js +5 -4
- package/dist/knowledge/rules.js +113 -6
- package/dist/knowledge/styleResolve.js +52 -5
- 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/http.js +10 -2
- package/dist/platform/screenshot.js +492 -29
- package/dist/platform/screenshotMemory.js +55 -0
- package/dist/platform/strictArguments.js +32 -0
- package/dist/platform/writeDiff.js +6 -3
- package/dist/resources/examples/layout-app-shell.json +1 -1
- package/dist/resources/examples/page-sign-in.json +1 -1
- package/dist/resources/examples/theme-brand.json +162 -0
- package/dist/resources/guides/component.md +8 -2
- package/dist/resources/guides/expressions.md +6 -0
- package/dist/resources/guides/getting-started.md +6 -0
- package/dist/resources/guides/layout.md +36 -26
- package/dist/resources/guides/microservice.md +160 -6
- package/dist/resources/guides/page.md +165 -59
- package/dist/resources/guides/theme.md +210 -0
- package/dist/resources/guides/translation.md +13 -10
- package/dist/resources/guides/workflow.md +141 -7
- 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 +52 -42
- package/dist/tools/components.js +8 -0
- package/dist/tools/designSchemaPatch.js +152 -0
- package/dist/tools/flows.js +24 -21
- package/dist/tools/layouts.js +8 -8
- package/dist/tools/microservices.js +74 -10
- package/dist/tools/pages.js +275 -332
- package/dist/tools/projects.js +66 -9
- package/dist/tools/queries.js +72 -6
- 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 +10 -6
- 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
|
|
@@ -115,7 +121,15 @@ servis formunda görünür ve `microservice_get` outline görünümünde geri ok
|
|
|
115
121
|
|
|
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
|
-
adım adım executionItems ağacı döner.
|
|
124
|
+
adım adım executionItems ağacı döner. Zamanlanmış (`schedule-job`) uçta sıra farklıdır:
|
|
125
|
+
`workflow_preview` → `microservice_debug` → `microservice_schedule_control` `trigger` →
|
|
126
|
+
`microservice_job_history`; geçmişteki `completed` başarı kanıtı DEĞİLDİR (§Zamanlanmış işin
|
|
127
|
+
gerçek sonucunu görmek).
|
|
128
|
+
Çağrı parametrelerini (sorgu parametresi, filtre değeri) üst düzey `parameters: { ad: değer }`
|
|
129
|
+
ile ver; gateway GET'te query-string'e, POST/PUT'ta gövdeye koyar. Değeri NULL bağlanan query
|
|
130
|
+
parametresini debug yanıtı `unboundParameters` ile söyler — ağaçta o satırın `value` anahtarı
|
|
131
|
+
görünmez. Tool'un tanımadığı bir üst düzey argüman artık reddedilir (GW-005); 2026-09-15'e
|
|
132
|
+
kadar `parameters` hata vermeden atılıyordu ve dört farklı filtre aynı gövdeyi döndürdü (G-13).
|
|
119
133
|
|
|
120
134
|
## Yanıt sözleşmesi (DTO) uca DEĞİL workflow'a bağlanır (MS-018, block)
|
|
121
135
|
|
|
@@ -159,8 +173,9 @@ DTO'dan süzülmez (WF-026 — `platform_guide('workflow')` §Hata yolu). Sözle
|
|
|
159
173
|
## Asgari doğru table-source microservice (platformda doğrulanmış kurallar)
|
|
160
174
|
|
|
161
175
|
- `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
|
|
176
|
+
`get · create · update · delete · upsert · count · bulk-create · bulk-update · bulk-delete`.
|
|
177
|
+
**`list` yoktur** — liste için `operation: 'get'` + `isSingle: false`, tek kayıt için
|
|
178
|
+
`isSingle: true`.
|
|
164
179
|
- **`upsert` vardır ve tercih edilmelidir.** Aynı formun hem yeni kayıt hem düzenleme
|
|
165
180
|
yapmasını iki ayrı uç + akışta condition dallanmasıyla kurmayın: tek `operation: 'upsert'`
|
|
166
181
|
ucu yeterlidir. Aynı işlem workflow **table step**'inde de desteklenir
|
|
@@ -174,9 +189,42 @@ DTO'dan süzülmez (WF-026 — `platform_guide('workflow')` §Hata yolu). Sözle
|
|
|
174
189
|
|
|
175
190
|
> **Upsert'te üretilen alan tuzağı.** `operation: 'upsert'` UPDATE yolunda da alan ifadelerini
|
|
176
191
|
> 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
|
-
>
|
|
192
|
+
> güncellemede **sessizce değişir** (İK koşusu M-3: EMP-0005 → EMP-0006). Çözüm alan bazlı
|
|
193
|
+
> **`writeOn: create | update | always`**'dir (varsayılan `always`) ve 2026-09-04'ten beri
|
|
194
|
+
> platformdadır: üretilen alana `writeOn: 'create'` verirsen upsert'in UPDATE dalı o alanı satıra
|
|
195
|
+
> hiç koymaz (`ToRow(entityDto, writeOn)` iki satırı ayrı kurar). `writeOn` YALNIZ
|
|
196
|
+
> `operation: 'upsert'` ucunda anlamlıdır — başka operasyonda `always` dışında bir değer
|
|
197
|
+
> **MS-017** ile reddedilir. Gateway **MS-016** ile uyarır; alan `writeOn: 'create'` taşıyorsa
|
|
198
|
+
> susar. **`writeOn` bir "kısmi güncelleme" bayrağı DEĞİLDİR** — hangi DALIN yazacağını söyler,
|
|
199
|
+
> "gövdede gelmeyen alanı atla" demez (aşağıdaki §Güncelleme sözleşmesi).
|
|
200
|
+
- **Toplu yazma için `bulk-create` / `bulk-update` / `bulk-delete` vardır.** Aynı tabloya N satır
|
|
201
|
+
yazmak için akışta döngü kurmayın: bu üç uç gövdedeki **JSON diziyi** tek çağrıda işler
|
|
202
|
+
([TableMicroserviceExecutor](../../../../zeyrek-backend/src/NgApps.Domain/Contexts/Studio/Microservices/Executors/TableMicroserviceExecutor.cs)).
|
|
203
|
+
Kurallar:
|
|
204
|
+
- Gövde bir **dizi** olur; her eleman bir satırdır. `bulk-delete` gövdesinde yalnız birincil
|
|
205
|
+
anahtar alanı aranır ve tek bir `IN` filtresine çevrilir.
|
|
206
|
+
- `filters` **kullanılmaz** — satırlar ve anahtarlar gövdeden okunur.
|
|
207
|
+
- Tek istekte en fazla **1000 satır** (`EntityConstants.BulkRowLimit`); aşılırsa
|
|
208
|
+
`BulkRowLimitException` (422).
|
|
209
|
+
- Parti **hep-ya-hiç**tir: bir satır doğrulamadan geçmezse `BulkRowFailedException` hangi
|
|
210
|
+
satırın (index) patladığını söyler ve hiçbir satır yazılmaz.
|
|
211
|
+
- **Dosya alanı olan tablolarda `bulk-create`/`bulk-update` da desteklenir** — her satırın
|
|
212
|
+
dosya (ve çoka-çok dosya) alanı, tekil `create`/`update` ile **aynı format** üzerinden
|
|
213
|
+
(`{ type, fileName, value, clone, override, id }`) satır satır `fileService`'e gönderilir;
|
|
214
|
+
artık dosya alanı yüzünden 422 dönmez. Aynı entegrasyon workflow **table step**'inde de
|
|
215
|
+
vardır (satır dizisindeki dosya değeri de aynı formatı izler).
|
|
216
|
+
- **Bulk upsert yoktur.**
|
|
217
|
+
- `bulk-update` gövdesinde birincil anahtar **bulunur ve zorunludur** — tekil `update`'in
|
|
218
|
+
aksine satırı belirleyen filtre değil, gövdedeki anahtardır. `UpdateRowsAsync` bu anahtarı
|
|
219
|
+
`SET` listesinden dışlayıp `WHERE`'e taşır, bu yüzden alan listesinde görünmesi doğrudur ve
|
|
220
|
+
GENERATED ALWAYS koruması onu es geçer.
|
|
221
|
+
- Workflow **table step**'inde de aynı üç işlem vardır; orada satır dizisi adımın `expression`
|
|
222
|
+
alanından (JS) gelir, gövdeden değil. **Ancak studio'nun workflow table formunda bu
|
|
223
|
+
`expression` alanı için editör henüz yoktur** — akış adımında bulk seçilirse satır dizisi
|
|
224
|
+
girilemez ve adım `MissingParameterException` ile düşer. v1'de bulk yalnız microservice
|
|
225
|
+
ucundan kullanılır.
|
|
226
|
+
- Adımda tanımlı ama değeri boş bırakılan alanlar gövdeden/expression'dan gelen veriyi
|
|
227
|
+
**ezmez**; yalnız değeri dolu olan sabitler her satıra uygulanır.
|
|
180
228
|
- **`count` vardır** — kayıt sayısı için tüm satırları çekip uzunluğuna bakmayın; panel/KPI
|
|
181
229
|
sayaçlarının doğru şekli budur.
|
|
182
230
|
- Gövde kökünde **`entityId` zorunlu**. (Eski "kökte datasourceId zorunlu" bilgisi yanlıştı —
|
|
@@ -233,6 +281,61 @@ DTO'dan süzülmez (WF-026 — `platform_guide('workflow')` §Hata yolu). Sözle
|
|
|
233
281
|
}
|
|
234
282
|
```
|
|
235
283
|
|
|
284
|
+
## Güncelleme sözleşmesi: yazılan alan kümesi TANIMDAN gelir, gövdeden DEĞİL
|
|
285
|
+
|
|
286
|
+
`create` / `update` / `upsert` ucunda **SET listesi `fields[]`'tir**; gövde yalnız o alanların
|
|
287
|
+
DEĞERİNİ taşır. Studio'daki karşılığı "Oluşturulacak veya güncellenecek alanlar" ekranındaki
|
|
288
|
+
**İstek alanları** listesidir: önce hangi alanların yazılacağı seçilir, gövde sonra gelir.
|
|
289
|
+
İki yön de sessizdir, ikisi de 200 döner (ölçüm: 2026-09-15, `emrah/test`, `development`):
|
|
290
|
+
|
|
291
|
+
| Tanımda (`fields[]`) | Gövdede | Sonuç |
|
|
292
|
+
|---|---|---|
|
|
293
|
+
| alan **var** | anahtar **yok** | kolona **NULL yazılır** — eski değer silinir |
|
|
294
|
+
| alan **var** | anahtar var | değer yazılır |
|
|
295
|
+
| alan **yok** | anahtar var | **yok sayılır** — o alan bu uçtan hiç değiştirilemez |
|
|
296
|
+
|
|
297
|
+
Kod yolu: gövdede anahtar yoksa alan `null` değerini alır
|
|
298
|
+
(`MicroserviceRuntimeCacheDto.SetSourceEntityFieldAndFilterValue`, `:145-148`), `ToRow` Default
|
|
299
|
+
modlu **bütün** alanları sözlüğe basar (`:169-175`) ve `UpdateRowAsync` SET listesini doğrudan o
|
|
300
|
+
sözlüğün anahtarlarından kurar (`PostgreSqlEntityConnector.cs:262-273`; null → `DBNull.Value`).
|
|
301
|
+
"Yalnız gövdede gelen alanı yaz" diye bir bayrak **yoktur**.
|
|
302
|
+
|
|
303
|
+
Ölçülen üç vaka (`pu_test`: `title` · `owner` · `status`):
|
|
304
|
+
|
|
305
|
+
| # | Uç tanımı | Gövde | Sonuç |
|
|
306
|
+
|---|---|---|---|
|
|
307
|
+
| 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) |
|
|
308
|
+
| 2 | `fields: [status]` | `{ id, status, title: '…', owner: '…' }` | 200 — yalnız `status` değişti; listelenmeyen iki alan **yazılmadı** |
|
|
309
|
+
| 3 | `fields: [title, owner, status]`, `status` kolonu NOT NULL | `{ id, title }` | **400 `RowValidationFailed`** ("Please complete all required fields") — satır hiç değişmedi |
|
|
310
|
+
|
|
311
|
+
Yani kolon `nullable` ise kayıp **sessizdir**, NOT NULL ise istek **gürültülü** düşer. Kanban'da
|
|
312
|
+
kart sürüklemek, satır içi tek alan düzenlemek, "arşivle" düğmesi — hepsi 1. satırın tuzağıdır:
|
|
313
|
+
kart doğru sütuna geçer, başlığı ve sorumlusu silinir.
|
|
314
|
+
|
|
315
|
+
### Kısmi güncellemenin üç doğru yolu
|
|
316
|
+
|
|
317
|
+
1. **Eylem başına uç (varsayılan tercih).** Kartı taşıyan uç yalnız `status` yazar, başlığı
|
|
318
|
+
düzenleyen uç yalnız `title`: `fields[]` = o eylemin gerçekten yazdığı alanlar. Fazladan okuma
|
|
319
|
+
yok, eşzamanlı düzenlemede birbirini ezme yok, yetki yüzeyi de dar kalır (2. ölçüm bunun
|
|
320
|
+
kanıtıdır — uç, gövdeye konan `title`/`owner`'ı yok sayar).
|
|
321
|
+
2. **Tam form ucunda gövde de tam olur.** Düzenleme formu kaydediyorsa gövde `fields[]`'teki HER
|
|
322
|
+
alanı taşır; kullanıcının dokunmadığı alan da forma yüklendiği hâliyle geri gönderilir. Uçta
|
|
323
|
+
yapılacak bir şey yoktur — eksik gönderen istemci alanı siler.
|
|
324
|
+
3. **Oku-birleştir (alan kümesi ancak çağrı anında belliyse).** Akışta önce `table get`, sonra
|
|
325
|
+
`table update`; gelmeyen alan okunan değere düşer:
|
|
326
|
+
|
|
327
|
+
```js
|
|
328
|
+
typeof input.title !== 'undefined' && input.title !== null ? input.title : read_row.data.title
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Ölçüldü: `{ id, status }` gövdesiyle `title` ve `owner` korundu, `status` yazıldı. Bedeli iki
|
|
332
|
+
veritabanı turu ve **son yazan kazanır** — okuma ile yazma arasında başkasının yazdığı alan
|
|
333
|
+
geri alınır. Bu yüzden 1. yol varken bu yola girilmez.
|
|
334
|
+
|
|
335
|
+
> Aynı kural workflow **table step**'inde birebir geçerlidir; orada değer gövdeden değil
|
|
336
|
+
> ifadeden gelir ve `undefined` dönen ifade de `null` yazar —
|
|
337
|
+
> `platform_guide('workflow')` §"Table update adımı".
|
|
338
|
+
|
|
236
339
|
## İlişki alanı: `row_list` NESNE döner, uç/step JOIN'siz DÜZ FK döner
|
|
237
340
|
|
|
238
341
|
Aynı alan iki yoldan farklı şekilde gelir ve bu fark sessizce yanlış sonuç üretir:
|
|
@@ -590,6 +693,57 @@ Yeni işte tanımı `typeParameters.schedule` ile yazın ve kaydetmeden önce
|
|
|
590
693
|
`cronExpression`'ı değiştiren PUT/PATCH `422 ScheduleCronConflict` alır — sessizce eski cron
|
|
591
694
|
kalmaz. `typeParameters: null` işi zamanlayıcıdan siler.
|
|
592
695
|
|
|
696
|
+
### Zamanlanmış işin gerçek sonucunu görmek: geçmiş `failed` yazar, adım izini önizleme verir
|
|
697
|
+
|
|
698
|
+
Zamanlanmış koşu Quartz işi `MicroserviceJob` içinde koşar: `ExecuteAsync(microservice, BOŞ
|
|
699
|
+
parametre)`. 2026-09-16'dan beri iki hata yolu da geçmişe `failed` olarak düşer ve transaction geri
|
|
700
|
+
alınır:
|
|
701
|
+
|
|
702
|
+
| Geçmişte görünen | Gerçekte olan |
|
|
703
|
+
|---|---|
|
|
704
|
+
| `failed`, `errorMessage: "Step 'boom' failed: <sebep>"` | fail dalı bağlanmamış adım patladı; motor `WorkflowStepFailedException` fırlattı |
|
|
705
|
+
| `failed`, `errorMessage: "The job's workflow returned 500 (JavaScriptException): <mesaj>"` | akış bağlı global-error dalından (gateway'in eklediği `gatewayOnError` dâhil) 2xx dışı sonuç döndü; `MicroserviceJob` `ScheduleJobWorkflowFailedException` fırlattı |
|
|
706
|
+
| `failed`, başka mesaj | motor dışı exception: tanım/cache hatası, sonsuz döngü, canlı `revert`, DTO davranış uyumsuzluğu |
|
|
707
|
+
| `completed`, beklenen süre | akış 2xx ile bitti, yazmalar commit edildi — kalıcı etkiyi yine `row_list` ile say |
|
|
708
|
+
| satır yok | koşu veto edildi (deployment/şablon kurulumu sürüyor) ya da zamanlayıcıda kayıt yok — `microservice_schedule_get` |
|
|
709
|
+
|
|
710
|
+
Eski davranış (2026-09-16 öncesi imaj): adım hatası exception değildi; geçmişe `completed` + kısa
|
|
711
|
+
süre + boş `errorMessage` yazılır, yazmalar commit edilirdi — "90 ms'de tamamlandı ama hiçbir şey
|
|
712
|
+
yapmadı". Karşındaki platform hâlâ bunu yapıyorsa imaj eskidir.
|
|
713
|
+
|
|
714
|
+
Dört gerçek daha:
|
|
715
|
+
|
|
716
|
+
- **Geçmiş satırı `{ status, triggeredAt, completedAt, durationMs, errorMessage }`'dan ibarettir.**
|
|
717
|
+
Mesaj patlayan adımı ve sebebini söyler ama adım adım girdi/çıktı vermez; son koşunun adım izini
|
|
718
|
+
döndüren bir MCP aracı **yoktur** (açık backend işi P-19c). Adım izi için aynı tanımı önizlemede
|
|
719
|
+
koştur.
|
|
720
|
+
- **Zamanlanmış koşunun bağlamı boştur:** girdi yok (`MicroserviceExecuteParameter.Create()`),
|
|
721
|
+
middleware koşmaz (`user` yok), `request` yok, `context`/`triggerSource` kurulmaz. Akış
|
|
722
|
+
`input.x`, `user.id`, `request.*`, `context.language` okuyorsa zamanlanmış koşuda hepsi
|
|
723
|
+
`undefined`'dır — önizlemede geçen akış bu yüzden zamanlayıcıda patlayabilir.
|
|
724
|
+
- `microservice_schedule_get` içindeki `lastExecution` aynı geçmiş satırıdır.
|
|
725
|
+
- Geçmiş mesajları resx varsayılanıyla (İngilizce) yazılır; iş iş parçacığında istek dili yoktur.
|
|
726
|
+
|
|
727
|
+
**Sıra — tetiklemeden önce gör** (Studio'daki akış "Önizleme"si + servis önizlemesinin MCP karşılığı):
|
|
728
|
+
|
|
729
|
+
1. **Akışı `workflow_preview` ile koştur** (`platform_guide('workflow')` §Önizleme çıktısını
|
|
730
|
+
okumak): `workflow_get` gövdesini olduğu gibi ver, **`previewPayload` VERME** — iş girdisiz
|
|
731
|
+
koşar, önizleme de girdisiz koşsun. Akış `parameterDtoId` taşıyorsa zamanlanmış koşuda DTO boş
|
|
732
|
+
bağlanır; zorunlu alanı olan DTO'yu zamanlanmış akışa bağlama. Hata varsa `runtimeErrors` +
|
|
733
|
+
`steps[].hasError` / `errorMessage` / `input[]` patlayan adımı ve sebebini verir.
|
|
734
|
+
2. **Kayıtlı ucu `microservice_debug` ile koştur:**
|
|
735
|
+
`{ application: '<app slug>', microservice: '<uç slug>', method: 'POST' }` — schedule-job için
|
|
736
|
+
de slug yolu çalışır (tip denetimi yok), rollback'lidir, `httpStatus` akışın kendi sonucudur
|
|
737
|
+
(4xx/5xx'te gateway `runtimeErrors` ekler) ve `executionItems` ağacı adım adım girdi/çıktıyı
|
|
738
|
+
verir. Düğümlerde hata bayrağı yoktur: patlayan adımın `output`'u boştur, hata gövdesi hata
|
|
739
|
+
dalındaki response adımının çıktısındadır. Fark: debug ucun middleware'lerini de koşturur,
|
|
740
|
+
zamanlayıcı koşturmaz.
|
|
741
|
+
3. **`microservice_preview({ id })`** en kısa "geçer mi" sondasıdır: yanıt `httpStatus` + gövdeden
|
|
742
|
+
ibarettir, adım ağacı DÖNMEZ (`executionItems` yalnız `/debug/` yolunda).
|
|
743
|
+
4. Ancak sonra `microservice_schedule_control` `trigger` → `microservice_job_history`. `failed`
|
|
744
|
+
ise mesaj patlayan adımı ve sebebini söyler; adım adım girdi/çıktı gerekiyorsa 1-2'ye dön.
|
|
745
|
+
`completed` ise kalıcı etkiyi `row_list` ile say.
|
|
746
|
+
|
|
593
747
|
## Sık hatalar
|
|
594
748
|
|
|
595
749
|
- `description` boş (MS-014, block — uç listesinde ne işe yaradığı okunamaz)
|
|
@@ -78,27 +78,33 @@ 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
|
-
`data
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
2026-09-06 koşusunda on bir etiket bu yolla kuruldu ve
|
|
88
|
-
|
|
89
|
-
`
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
- **`blocks[].size
|
|
93
|
-
varsayılanı aşabiliyor (`page-header` default `h:8`, `maxSize` `h:4`) — varsayılanı körü
|
|
94
|
-
kopyalama
|
|
86
|
+
(platformun kendi op'u — 2026-09-14'e kadar gateway emülasyonuydu — ve yamanın geri kalanıyla
|
|
87
|
+
aynı PATCH'te gider; mevcut `data`'yı tasarım yedeği olarak taşır). Taşıyıcı alan tipe göre
|
|
88
|
+
değişir — `static` değeri `data`'da, `code` ve `translation` `ref`'te taşır; eksik taşıyıcı istek
|
|
89
|
+
gönderilmeden reddedilir ve `page_schema_validate` aynı kararı verir. Eski yol
|
|
90
|
+
`remove_component` + `add_component` idi: 2026-09-06 koşusunda on bir etiket bu yolla kuruldu ve
|
|
91
|
+
onlara yazan **dokuz setter iteratee'si** sessizce silindi; 2026-09-15'te (G-04) aynı zincir bir
|
|
92
|
+
`daterangepicker` yer tutucusunu çeviriye bağlarken tekrarlandı — setter hedefi elementId değil
|
|
93
|
+
komponentin iç kimliğidir (aşağıda Kural 2, `FLOW-018`).
|
|
94
|
+
|
|
95
|
+
- **`blocks[].size`'ı komponentin `component_get`'teki `minSize`..`maxSize` aralığında tut.** Dikkat:
|
|
96
|
+
katalog varsayılanı aşabiliyor (`page-header` default `h:8`, `maxSize` `h:4`) — varsayılanı körü
|
|
97
|
+
körüne kopyalama. Sınır grid kanvasının kuralıdır; API 2026-09-15'ten beri reddetmez, ama aşan
|
|
98
|
+
blok kanvasta boyutlandırılamaz (aşağıda Kural 7 "Boyut tuzağı").
|
|
95
99
|
- **Kurulmuş bir düğümün boyutunu `resize_component` micro-op'u değiştirir.**
|
|
96
100
|
`{ op: 'resize_component', target: '<elementId>', size: { w, h } }` ızgara boyutunu,
|
|
97
101
|
`{ …, appearance: { heightType: 'fixed', heightString: '340px' } }` flex ölçüsünü yazar; ikisi
|
|
98
|
-
aynı op'ta verilebilir, `breakpoint` varsayılanı 1024'tür.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
+
aynı op'ta verilebilir, `breakpoint` varsayılanı 1024'tür. Gateway op'u platformun
|
|
103
|
+
`set_block {target, breakpoint, size}` + `set_appearance {target, appearance}` +
|
|
104
|
+
`set_states {target, states}` op'larına çevirir ve yamanın geri kalanıyla **aynı PATCH'te** yollar
|
|
105
|
+
(o üç op'u doğrudan da gönderebilirsin). `move_component` gövdesine konan `size` gateway'de
|
|
106
|
+
reddedilir ve buraya yönlendirir; konumu belirli bir breakpoint'e yazmak için
|
|
107
|
+
`move_component`'e `breakpoint` ver. Ebeveynin düzeni yazdığın alanı etkisiz kılıyorsa (flex kabın
|
|
102
108
|
içine `size`, ızgaranın içine `appearance`) yanıt `PAGE-019` uyarısı taşır — istek yine geçer.
|
|
103
109
|
**Düğümü silip yeniden kurmayın:** o yol ona yazan akış setter'larını sessizce öldürür
|
|
104
110
|
(`FLOW-018`, aşağıda Kural 2).
|
|
@@ -164,8 +170,10 @@ uymayan adı **PAGE-008** ile istek gitmeden reddeder.
|
|
|
164
170
|
**Olay KALDIRMAK için `remove_event` kullan.** Platformun `set_event` micro-op'u olay silemez:
|
|
165
171
|
`eventValue: null` verildiğinde kayıt `{ name: 'click' }` olarak (değersiz) kalır, diziden
|
|
166
172
|
çıkmaz — şemada ölü bağ artığı bırakır. `{ "op": "remove_event", "target": "<elementId>",
|
|
167
|
-
"event": "click" }`
|
|
168
|
-
|
|
173
|
+
"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. Sayfa düzeyi olaylar için
|
|
175
|
+
`target: "page"`. Referanssız kalan akış silineceği için `allowFlowDeletion` kuralı (G-21) bu op'ta
|
|
176
|
+
da geçerlidir.
|
|
169
177
|
|
|
170
178
|
**Olay YÜKÜ komponente özeldir ve `component_get` onu da veriyor** (`events[].payload`, gerekirse
|
|
171
179
|
`events[].reads`) — **ama yük akışa `event.data` ile GELMEZ.** Motor emit'in `data`'sını önce
|
|
@@ -394,6 +402,14 @@ göstermek error flow'un işidir.
|
|
|
394
402
|
> "branches": [{ "id": "<GUID>", "name": "always", "nextStepId": null }] }
|
|
395
403
|
> ```
|
|
396
404
|
|
|
405
|
+
> **`confirm` adımının diyalog çerçevesi de yazılabilir.** `args` dört düz metin alanı taşır:
|
|
406
|
+
> `message` (gövde), `title` (başlık), `confirmText` (onay düğmesi, `yes` dalı), `cancelText`
|
|
407
|
+
> (vazgeç düğmesi, `no` dalı). Son üçü isteğe bağlıdır; boş bırakılan alan dile göre sabit metne
|
|
408
|
+
> düşer ("Emin misiniz?" / "Evet" / "Hayır" — `dialog.functions.ts` `resolveDialogFrame`).
|
|
409
|
+
> Dördü de `alert`'in `message`'ı gibi DÜZ METİNDİR (FLOW-022 hepsini denetler):
|
|
410
|
+
> `{ "type": "confirm", "args": { "message": "Bu risk ve 4 aksiyonu silinecek.", "title": "Riski sil",
|
|
411
|
+
> "confirmText": "Sil", "cancelText": "Vazgeç" } }`.
|
|
412
|
+
|
|
397
413
|
> **Hangi yolu seçeceksin — `errorSteps` mi, ana akışta `condition` mı?** İkisi birden
|
|
398
414
|
> kurulamaz (yukarıdaki 1. madde), yani bu bir tercih değil bir karar:
|
|
399
415
|
>
|
|
@@ -600,8 +616,8 @@ Türkçe başlık `props.title` / `props.text` / `props.label` / `props.pageTitl
|
|
|
600
616
|
> `elementId` ile eşit tutmazsan `element:` alanı çalışır ama ifadedeki değişken `undefined` kalır.
|
|
601
617
|
>
|
|
602
618
|
> Gateway bunu **PAGE-009** ile HER sayfa ve layout yazma yolunda istek gitmeden reddeder:
|
|
603
|
-
> `page_create`, `page_update(schema)`, `add_component
|
|
604
|
-
> ve `layout_patch`.
|
|
619
|
+
> `page_create`, `page_update(schema)`, `add_component` (sayfa, `layout_schema_patch` ve
|
|
620
|
+
> `component_schema_patch` yamalarında), `layout_create`, `layout_update(views)` ve `layout_patch`.
|
|
605
621
|
|
|
606
622
|
## Kural 1d — Sayfa iskeleti: `page_container` ve boyutlandırma
|
|
607
623
|
|
|
@@ -893,6 +909,16 @@ Beş şeyi bilmeden flex kurma:
|
|
|
893
909
|
aradaki boşluklar çizilmez. Yine de bitişik ver (0,1,2…): kapsayıcı ileride `grid`'e
|
|
894
910
|
döndürülürse şema geçerli kalsın. Gateway bu yüzden **flex kapsayıcının İÇİNDE PAGE-010
|
|
895
911
|
boşluk uyarısı üretmez** (ızgarada üretmeye devam eder).
|
|
912
|
+
**Dizi sırası çizimi belirlemez** — `children[]` içindeki yer değil `y` kazanır; `y`'si eşit
|
|
913
|
+
iki çocukta dizi sırası kazanır. Bu yüzden flex kapta sıralamanın yolu `index`'tir:
|
|
914
|
+
`add_component`/`move_component`'e verilen `index` **görünen sıradaki yeri** belirler ve gateway
|
|
915
|
+
kardeşlerin konumunu Studio'nun flex tuvali gibi yeniden yazar (x=0, alt alta birikimli y;
|
|
916
|
+
yanıtın `gatewayNormalized` notu hangi `y`'nin değiştiğini söyler). Grafiğin üstüne başlık:
|
|
917
|
+
`{ "op": "add_component", "parent": "<flex kap>", "index": 0, "component": { … } }` — koordinat
|
|
918
|
+
hesaplamak gerekmez, `remove_component` + `add_component` hiç gerekmez. **Izgara kapta `index`
|
|
919
|
+
çizimi değiştirmez** (her çocuk kendi `position`'ında mutlak çizilir): sırayı
|
|
920
|
+
`move_component { target, position: { x, y } }` ile ver; sona eklemeyen `index` orada
|
|
921
|
+
**PAGE-033 (uyarı)** üretir.
|
|
896
922
|
3. **Flex kapsayıcının yüksekliği içeriğine oturur.** `verticalAlign`'ın dağıtacak boşluğu
|
|
897
923
|
olması için `appearance.heightType: 'fixed'` vermelisin — ölçü `heightString`'den
|
|
898
924
|
(serbest CSS uzunluğu, ör. `"30vh"`), o yoksa `size.h × 10px`'ten gelir. `heightString`
|
|
@@ -1010,7 +1036,8 @@ UYGULAMAZ** — koordinatları aynen kaydeder (aşağı itme yalnız `page_creat
|
|
|
1010
1036
|
> sarmalayıcıya bağla (yukarıdaki `box_multi`). Sarmalayıcıyı **`isWrapper:false`** kur
|
|
1011
1037
|
> (Kural 1f: wrapper = `min-height:80vh`) ve çerçevesini `style` ile kapat:
|
|
1012
1038
|
> `{ background:'transparent', border:'none', '&__body': { padding:'0px' } }`.
|
|
1013
|
-
> `appearance.isHidden` diye bir
|
|
1039
|
+
> `appearance.isHidden` diye bir alan YOKTUR (2026-09-15'te platformdan kaldırıldı, S-16) —
|
|
1040
|
+
> görünürlük yalnız `props.isHidden`'dır.
|
|
1014
1041
|
|
|
1015
1042
|
> **Satır BAŞINA doğrulama kurulamaz.** `validations` komponentin kendisindedir, tüm satırlar
|
|
1016
1043
|
> onu paylaşır — "3. soru zorunlu, 4. soru değil" şemayla ifade edilemez. Zorunluluk satır
|
|
@@ -1030,8 +1057,9 @@ UYGULAMAZ** — koordinatları aynen kaydeder (aşağı itme yalnız `page_creat
|
|
|
1030
1057
|
> (iç repeater bir kez `item` olmadan da değerlendiriliyor).
|
|
1031
1058
|
>
|
|
1032
1059
|
> **Gateway bunu `PAGE-013` ile istek gitmeden reddediyor** — `page_create` / `page_update(schema)` /
|
|
1033
|
-
> `layout_create` / `layout_update(views)` / `layout_patch` gönderilen ağaca
|
|
1034
|
-
> eklenen alt ağaca hem op'lar UYGULANDIKTAN
|
|
1060
|
+
> `layout_create` / `layout_update(views)` / `layout_patch` gönderilen ağaca; `page_schema_patch`,
|
|
1061
|
+
> `layout_schema_patch` ve `component_schema_patch` hem eklenen alt ağaca hem op'lar UYGULANDIKTAN
|
|
1062
|
+
> SONRAKİ ağaca bakarak. Layout'ta da geçerlidir: kırılma
|
|
1035
1063
|
> `_repeaterValues` geri yazmasındadır, barındıranın sayfa mı layout mu olduğuna bakmaz.
|
|
1036
1064
|
>
|
|
1037
1065
|
> **Yapılacak:** satır içi listeyi tek bir `textarea`'da **satır başına bir öğe** olarak topla
|
|
@@ -1060,6 +1088,12 @@ yapmanın yolu budur — ölçülmüş kurallar (anket-doldur, 2026-08-19):
|
|
|
1060
1088
|
> Bu kural TEMA/GÖRSELLİK içindir. Çocukların dizilimi (ortalama, yaslama, aralık, "kalanı
|
|
1061
1089
|
> doldur") `style` ile değil kapsayıcının kendi `layout` prop grubuyla kurulur — Kural 1f-2.
|
|
1062
1090
|
|
|
1091
|
+
> **ÖNCE PROJE TEMASI.** Bir markayı uygulamanın birinci yolu `theme_update`'tir
|
|
1092
|
+
> (`platform_guide('theme')`): tema kaydı BÜTÜN sayfalara iner, `theme_get(view:'resolved')`
|
|
1093
|
+
> hangi değişkenin hangi değeri aldığını söyler. Aşağıdaki `page_container.style` yöntemi
|
|
1094
|
+
> yalnız O SAYFAYA özgü sapma içindir — her sayfada tekrarlanan bir ezme, temaya taşınmamış
|
|
1095
|
+
> bir karardır.
|
|
1096
|
+
|
|
1063
1097
|
> **Stil anahtarları camelCase'dir: `minHeight`, `fontSize`, `letterSpacing`.** Kebab-case anahtar
|
|
1064
1098
|
> (`min-height`) platform tarafından KABUL EDİLİR, `page_schema_get` ile aynen geri okunur ve
|
|
1065
1099
|
> runtime onu HİÇ UYGULAMAZ; tek işaret tarayıcı konsolundaki tek satırdır ve `page_screenshot`
|
|
@@ -1120,6 +1154,8 @@ işareti taşıyan input'un **sonraki kardeşini** boya (`&__item-input:checked
|
|
|
1120
1154
|
### 1h-2 — Tema değişkeni envanteri (`Theme.svelte`, tamamı)
|
|
1121
1155
|
|
|
1122
1156
|
Bunlar **runtime'da her sayfada tanımlıdır**; `style` içinde yeniden tanımlayarak eziyorsun.
|
|
1157
|
+
Bir projedeki GÜNCEL değerleri (ve buradaki listenin tamamını) `theme_get(view:'resolved')`
|
|
1158
|
+
`cssVars` alanından okursun — aşağıdaki tablo kümeleri anlatır, değerleri değil.
|
|
1123
1159
|
Varsayılan palet `white.ts` (accent `#0052CC`, border `#dfe1e6`, text `#262626`) — yani hiçbir şey
|
|
1124
1160
|
yapmazsan ekran "platform mavisi" görünür; marka rengine çevirmek tek satırdır.
|
|
1125
1161
|
|
|
@@ -1245,8 +1281,9 @@ kaldırır); sayı `0` "seçilmedi" sayılır.
|
|
|
1245
1281
|
tipli grup alanları temayı alan alan EZER; düğümün serbest `style`'ı en üstte SON SÖZDÜR.
|
|
1246
1282
|
Boyut alanları CSS uzunluğu metnidir (`'18px'`, `'1.2em'`); `radius` tek alanda preset
|
|
1247
1283
|
anahtarı YA DA CSS uzunluğu kabul eder.
|
|
1248
|
-
**Tema preset'i bağlamak:** `style: { $preset: 'card' }` (adlar `
|
|
1249
|
-
`componentStyles[type]` referanssız uygulanır).
|
|
1284
|
+
**Tema preset'i bağlamak:** `style: { $preset: 'card' }` (adlar `theme_get` → `presets`, sayfa
|
|
1285
|
+
bağlamında `page_runtime_get` → `theme.presets`; `componentStyles[type]` referanssız uygulanır).
|
|
1286
|
+
Preset'in kendisini yazmak/silmek `theme_update` işidir — `platform_guide('theme')`. Bir alanı temaya bırakmak = o alanı hiç yazmamak;
|
|
1250
1287
|
studio'da bunun adı "Temaya dön"dür. Tema değerini gruba kopyalama — bağ kopar, tema değişince izlemez.
|
|
1251
1288
|
|
|
1252
1289
|
**Efektif stili okumak:** `page_runtime_get(resolveStyles: true)` her düğüme `resolvedStyle`
|
|
@@ -1299,12 +1336,14 @@ dokunuldu" sorusunun kanıtı) ve **`newVersion`** (`UpdatedAt.Ticks`).
|
|
|
1299
1336
|
> yamadan sonra şemayı okuyup gönderdiğinle karşılaştırarak söyler. Kırpma bu yüzden kanıt kaybı
|
|
1300
1337
|
> değildir; `view: 'full'`e yalnız gerçekten platformun ham gövdesini incelerken düş.
|
|
1301
1338
|
|
|
1302
|
-
**Sürüm kontrolü
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
`
|
|
1306
|
-
|
|
1307
|
-
|
|
1339
|
+
**Sürüm kontrolü `baseVersion` ile yapılır.** `page_schema_get` yanıtı `version` taşır (mikrosaniye,
|
|
1340
|
+
STRING — sayıya çevirme); `page_schema_patch`'e `baseVersion` olarak ver. Sayfa o sürümden beri
|
|
1341
|
+
değiştiyse platform **409** döner ve hiçbir op uygulanmaz; yanıttaki `newVersion` bir sonraki
|
|
1342
|
+
yamanın `baseVersion`'ıdır. Kontrol platformda atomiktir (satır kilidi + sürüm koşulu tek
|
|
1343
|
+
`UPDATE`'te), yani iki çağrı arasına giren yazarı da yakalar. `baseVersion` vermezsen gateway yalnız
|
|
1344
|
+
bu çağrıda zaten okuduğu sayfanın sürümünü gönderir; hiç okumadıysa yama sürümsüz gider ve son
|
|
1345
|
+
yazan kazanır. Eski `expectedUpdatedAt` hâlâ çalışır ama `baseVersion`'ın yerini tutmaz.
|
|
1346
|
+
Yanıttaki `touched`, kaydı değişen elementId'leri listeler (eklenen alt ağaç dâhil).
|
|
1308
1347
|
|
|
1309
1348
|
> **Büyük şemada çalışma sırası:** `mode:'summary'` ile ağacı çıkar (props yok, 500 KB'lık sayfada
|
|
1310
1349
|
> bile küçük) → hedefin `elementId`'sini al → gerekiyorsa `mode:'subtree'` ile yalnız o dalı oku →
|
|
@@ -1319,14 +1358,15 @@ korumayı isteyen ham HTTP ile `baseVersion` göndermelidir.
|
|
|
1319
1358
|
> `set_event` ile bağla ya da `flow_get` ile gövdesini yedekle. Ayrıntılı analiz:
|
|
1320
1359
|
> `PatchPageSchemaCommandHandler` (backend) — kilit, sürüm ve hep-ya-hiç davranışının kaynağı.
|
|
1321
1360
|
|
|
1322
|
-
## Kural 3 — Flow yazımı
|
|
1361
|
+
## Kural 3 — Flow yazımı yalnız akışı yazar, bağ ayrı yamadır
|
|
1323
1362
|
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1363
|
+
2026-09-14'ten beri `flow_create` / `flow_update` / `flow_delete` barındırıcının şemasına
|
|
1364
|
+
**dokunmaz**: gövde yalnız akıştır (silmede yalnız `id`). Eskiden gateway barındırıcının tam
|
|
1365
|
+
güncelleme komutunu da gönderiyordu; bu, her akış yazmasında sayfayı, layout'u ya da widget'ı
|
|
1366
|
+
baştan yazıyor ve açık bir Studio designer'ının kayıtlı tabanını eskitiyordu.
|
|
1328
1367
|
|
|
1329
|
-
Akışı bir komponente bağlamak ayrı adımdır
|
|
1368
|
+
Akışı bir komponente bağlamak ayrı adımdır ve akış kaydedildikten **sonra** yapılır (layout'ta
|
|
1369
|
+
`layout_schema_patch`, widget'ta `component_schema_patch`, op'lar aynı):
|
|
1330
1370
|
|
|
1331
1371
|
```
|
|
1332
1372
|
flow_create(host:'page', hostId:<pageId>, name:'Save order', slug:'save-order', steps:[…])
|
|
@@ -1368,18 +1408,13 @@ Sonradan akış eklemen gerekirse sayfayı baştan kurmana gerek yok — **bağ
|
|
|
1368
1408
|
`eventValue: null` olay kaydını bırakıp değerini boşaltır ve kilidi açar.
|
|
1369
1409
|
|
|
1370
1410
|
> **Aynı kilit LAYOUT'ta da vardır** (ölçüm 2026-08-18: menüye yeni bağlantı eklerken
|
|
1371
|
-
> `POST /layouts/<id>/flows` aynı hatayı verdi). Layout'
|
|
1372
|
-
>
|
|
1373
|
-
>
|
|
1411
|
+
> `POST /layouts/<id>/flows` aynı hatayı verdi). Layout'ta sıra sayfadakiyle aynıdır ve bağlar
|
|
1412
|
+
> `layout_schema_patch` ile yazılır: `flow_create × N` → TEK `layout_schema_patch` (bütün
|
|
1413
|
+
> `set_event`'ler). Sıfırdan kurarken kilide takılmazsın (akışları bağlamadan önce yaratırsın).
|
|
1374
1414
|
>
|
|
1375
|
-
>
|
|
1376
|
-
>
|
|
1377
|
-
>
|
|
1378
|
-
> 3) layout_update → tam ağaç + bütün events'ler
|
|
1379
|
-
> ```
|
|
1380
|
-
>
|
|
1381
|
-
> Sıfırdan kurarken kilide takılmazsın (akışları bağlamadan önce yaratırsın); kilit yalnız
|
|
1382
|
-
> **mevcut ve bağlı** bir layout'a yeni akış eklerken çıkar.
|
|
1415
|
+
> **Yeniden ölçülmeli (2026-09-14):** iki ölçüm de flow isteğinin barındırıcıyı baştan yazdığı
|
|
1416
|
+
> dönemdendi. Zarfsız istekte barındırıcı yazılmadığı için kilit kalkmış olabilir; ölçülene kadar
|
|
1417
|
+
> kuruluş sırasını koru.
|
|
1383
1418
|
|
|
1384
1419
|
## Kural 4 — Komponent güncellemesi slug ile, silme id ile
|
|
1385
1420
|
|
|
@@ -1559,6 +1594,21 @@ alanına dokunur. **Komponenti silip yeniden eklemeyin:** `remove_component` + `
|
|
|
1559
1594
|
turu o komponente bağlı setter hedeflerini koparır (Kural 1e sonundaki not) ve komponentin tek
|
|
1560
1595
|
referans verdiği akışları kalıcı olarak sildirir (Kural 2'deki yan etki notu).
|
|
1561
1596
|
|
|
1597
|
+
**Kurulu düğümün appearance'ını değiştirmek: `set_appearance`.** Aynı gerekçeyle appearance için
|
|
1598
|
+
de silip yeniden ekleme gerekmez:
|
|
1599
|
+
|
|
1600
|
+
```jsonc
|
|
1601
|
+
{ "op": "set_appearance", "target": "box_summary", "appearance": { "heightType": "auto", "tooltip": null } }
|
|
1602
|
+
```
|
|
1603
|
+
|
|
1604
|
+
Op **birleştirir**: yalnız verilen alanları yazar, gerisini korur; `null` alanı temizler (null
|
|
1605
|
+
kabul etmeyen `heightType` gibi alanlar hariç). Alan adları `page_schema_get`'in döndürdüğü
|
|
1606
|
+
appearance anahtarlarıdır; bilinmeyen alan `unknown-appearance-field`, tanınmayan ya da null
|
|
1607
|
+
kabul etmeyen değer (`heightType: "tall"`) `invalid-appearance` ile 422 döner ve yama atomik
|
|
1608
|
+
olduğu için hiçbir op yazılmaz. Kurulu düğümün `states` bayrakları için eşi `set_states`'tir.
|
|
1609
|
+
**`isHidden` bir appearance alanı DEĞİLDİR** — gizlemek için `replace_prop { prop: 'isHidden' }`
|
|
1610
|
+
ya da `set_binding { prop: 'isHidden' }` (Kural 7a'daki `isHidden` notu).
|
|
1611
|
+
|
|
1562
1612
|
**Kip ayrımı query parametresidir:** aynı sayfa `?id=<kayıt>` ile edit, parametresiz create.
|
|
1563
1613
|
|
|
1564
1614
|
`mount` akışı (`page_container` ya da `form` üzerine bağlanır):
|
|
@@ -1671,10 +1721,12 @@ start → [setter] btn_save.isLoading = true
|
|
|
1671
1721
|
> artık doğrudan `props.isHidden` yazılabilir; sırf gizlemek için `container`'a sarmak
|
|
1672
1722
|
> GEREKMEZ. Tek doğru kaynak `component_get` + `page_schema_validate` kuru koşusudur.
|
|
1673
1723
|
>
|
|
1674
|
-
>
|
|
1675
|
-
>
|
|
1676
|
-
>
|
|
1677
|
-
>
|
|
1724
|
+
> **Appearance'ta `isHidden` alanı YOKTUR** (2026-09-15'te platformdan kaldırıldı, S-16): renderer
|
|
1725
|
+
> yalnız `props.isHidden`'a bakar. Başlangıçta gizli bildirim şemada
|
|
1726
|
+
> `"props": { "isHidden": { "type": "static", "data": true } }` ile kurulur, açılışı akıştaki
|
|
1727
|
+
> setter yapar. `add_component` / `page_update` gövdesine yine de `appearance.isHidden` konursa
|
|
1728
|
+
> gateway değeri `props.isHidden`'a taşır ve `gatewayNormalized`'da bildirir (prop zaten verilmişse
|
|
1729
|
+
> o kazanır); `set_appearance` ile `isHidden` yazmak istek gönderilmeden reddedilir.
|
|
1678
1730
|
|
|
1679
1731
|
### 7b — Liste → form geçişi
|
|
1680
1732
|
|
|
@@ -1797,8 +1849,9 @@ Komponentlerin **`style` prop'u** vardır ve iç parçalara iner (`textinput.sty
|
|
|
1797
1849
|
`&__body`). Tasarım kararlarını buradan uygula — varsayılan görünümle bırakmak zorunda değilsin.
|
|
1798
1850
|
|
|
1799
1851
|
> **Boyut tuzağı:** katalog varsayılan `size`'ı `maxSize`'ı aşan komponentler var
|
|
1800
|
-
> (`textinput` default `h:8`, `maxSize.h:5`).
|
|
1801
|
-
>
|
|
1852
|
+
> (`textinput` default `h:8`, `maxSize.h:5`). Boyut sınırı grid kanvasının kuralıdır, API
|
|
1853
|
+
> reddetmez; ama aşan blok kanvasta boyutlandırılamaz. Gateway aşan değeri `maxSize`'a kırpar ve
|
|
1854
|
+
> `gatewayNormalized` ile bildirir.
|
|
1802
1855
|
|
|
1803
1856
|
## Kural 8 — Korunan sayfa: `middlewareIds` vermeden `Page.user` YOKTUR
|
|
1804
1857
|
|
|
@@ -1859,11 +1912,49 @@ hiçbiri** bağlı değildi; üç portalın da rol menüsü boş çıkıyor, pan
|
|
|
1859
1912
|
> `Host: <org>.<suffix>` + `X-Environment` başlıklarıyla. Ham `curl` yerine tool'u kullanmak
|
|
1860
1913
|
> yeterlidir.
|
|
1861
1914
|
>
|
|
1915
|
+
> **Kareyi GÖRMEDEN doğrulamak — önce bunu dene.** `page_screenshot` her yanıtta `summaryText`
|
|
1916
|
+
> döner: her kök düğüm için tek satır — kimlik (tip) · görünür/GİZLİ/ekran dışı · metnin ilk 80
|
|
1917
|
+
> karakteri · `rows=<satır>` · `tab=<açık sekme>` · `value=<kutudaki değer>` · `BOŞ` ·
|
|
1918
|
+
> `errors=<sayı>`, sonda toast ve hata mesajları. "Kart göründü mü, tablo doldu mu, hata var mı"
|
|
1919
|
+
> sorularının cevabı budur ve **kareye gerek yoktur**: `image: 'none'` ile kare hiç çekilmez.
|
|
1920
|
+
> Ölçüldü (2026-09-16, 40 satırlık tablo taşıyan sayfa): özet **416** karakter, aynı sayfanın
|
|
1921
|
+
> `fullPage` karesi **151 276** karakter. Görsel soru (renk, hizalama, referansa sadakat) için
|
|
1922
|
+
> kareyi al ama küçült: `clip: { element: '<elementId>' }` yalnız o bölgeyi keser, `scale: 0.5`
|
|
1923
|
+
> rasteri yarıya indirir (sayfa yine 1280 CSS pikselinde çizilir — kırılım noktaları kaymaz),
|
|
1924
|
+
> `format: 'jpeg'` + `quality: 60` ölçekle BİRLİKTE kazandırır (tek başına neredeyse hiç).
|
|
1925
|
+
> Aynı sayfayı yeniden koştururken `diff: true` neyin değiştiğini listeler ve
|
|
1926
|
+
> `image: 'ifChanged'` değişmemiş kareyi hiç göndermez. `summary: 'full'` yapısal `domSummary`
|
|
1927
|
+
> dizisini de verir; runtime `data-component-type` basmıyorsa tipler yazılmaz ve `summaryNote`
|
|
1928
|
+
> bunu söyler.
|
|
1929
|
+
>
|
|
1930
|
+
> **Sekme, açılır kutu, form.** `actions` sözlüğünde üç fiil daha var.
|
|
1931
|
+
> `{ action: 'tab', target: 'tabs_settings', value: 'iot' }` sekmeyi ANAHTARIYLA seçer — sekme
|
|
1932
|
+
> grubunun köküne `click` göndermek DOM sırasındaki İLK sekmeye gider ve bu yüzden artık
|
|
1933
|
+
> reddedilir. **Etkin olmayan sekmenin içeriği DOM'da yoktur**: o sekmedeki bir düğüme yazmadan
|
|
1934
|
+
> ya da onu kırpmadan önce `tab` adımı koy. `{ action: 'select', target: 'dd_city', value: '34' }`
|
|
1935
|
+
> açılır kutudan seçer (kutu native alan değildir; `set` de aynı yola devreder) ve seçenekler
|
|
1936
|
+
> sorgudan geliyorsa listeyi 3 sn'ye kadar bekler — `optionsSeen: 0` görürsen kusur kutuda değil
|
|
1937
|
+
> sorgudadır, `query_preview` ile bak. `{ action: 'submit', target: 'frm_note' }` formu gönder
|
|
1938
|
+
> butonu olmadan gönderir. Her adımın raporu `matchedBy` · `activeTab` · `optionsSeen` ·
|
|
1939
|
+
> `waitedMs` · `submitVia` ile ne olduğunu söyler.
|
|
1940
|
+
>
|
|
1862
1941
|
> **Yerleşimi görüntüsüz ölçmek.** Taşma/çakışma şüphesinde `page_screenshot(layoutReport: true)`:
|
|
1863
1942
|
> `layoutSummary.overflowing` boş değilse içeriğine sığmayan kutu, `outsideViewport` boş değilse
|
|
1864
1943
|
> hiç görünmeyen düğüm var; `zeroSized` çizilmemiş komponenti gösterir. Runtime düğümleri
|
|
1865
1944
|
> `data-element-id` basmıyorsa yanıt `layoutReportUnavailable` der — tool tahmin üretmez.
|
|
1866
1945
|
>
|
|
1946
|
+
> **Sürükle-bırakı gerçekten sınamak (G-09).** `kanban` ve `eventcalendar` iç öğelerine
|
|
1947
|
+
> `<elementId>__<rol>` kimliği yazar (tablonun `__row-<n>`'i ile aynı kalıp):
|
|
1948
|
+
> kart `kb_board__card-<id>`, kolon `kb_board__col-<value>`; etkinlik `cal_plan__event-<id>`,
|
|
1949
|
+
> gün `cal_plan__day-<yyyy-MM-dd>`, tüm gün hücresi `cal_plan__allday-<yyyy-MM-dd>`, saat dilimi
|
|
1950
|
+
> `cal_plan__slot-<yyyy-MM-dd>T<HH>`. `id`, `idField`'ın değeridir (yoksa `card-<sıra>` /
|
|
1951
|
+
> `event-<sıra>`); tarih yereldir. Tıklama yolu `click` ile, taşıma `drag` ile sınanır:
|
|
1952
|
+
> `actions: [{ action:'drag', target:'kb_board__card-42', to:'kb_board__col-Assigned' }]`.
|
|
1953
|
+
> `actionsReport[].flowRuns`/`requests` sıfırsa `cardMove`/`eventMove` bağı kurulu görünse de
|
|
1954
|
+
> taşıma kalıcılaşmamıştır. Kaynak `draggable` değilse (`isDraggable`/`isEditable` kapalı)
|
|
1955
|
+
> adım `applied:false` ve notla döner. Çok günlü etkinlik aynı kimliği her gün hücresinde taşır;
|
|
1956
|
+
> hedef ilk eşleşmedir.
|
|
1957
|
+
>
|
|
1867
1958
|
> **Üye kimliğiyle doğrulama (`asUser`).** Kapının kapalı olduğunu görmek yarısıdır; açık
|
|
1868
1959
|
> olduğunu görmek diğer yarısı. `page_runtime_get` ve `page_screenshot` aynı `asUser` alanını
|
|
1869
1960
|
> alır: uygulamanın kendi giriş ucundan (`microservice_execute`) aldığın üye jetonunu verirsin,
|
|
@@ -1951,10 +2042,22 @@ micro-op hattına dönün.
|
|
|
1951
2042
|
>
|
|
1952
2043
|
> **Gateway artık bunu söylüyor (FLOW-018).** `remove_component` içeren bir yamada gateway sayfanın
|
|
1953
2044
|
> 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ı
|
|
2045
|
+
> hangi adım, hangi hedef. Ters yönü (`silinen düğümün referans verdiği` akışların platformca kalıcı
|
|
1956
2046
|
> silinmesi) ayrı bir uyarı kapsar; ikisi birlikte çıkabilir. Ölçüm 2026-09-04 (benchmark 4. koşu):
|
|
1957
2047
|
> uyarı yokken aynı tuzak ~8 dakika teşhis aldı ve yalnız ekran görüntüsüyle görüldü.
|
|
2048
|
+
>
|
|
2049
|
+
> **Mekanizma ve onarım (2026-09-15, G-04).** Setter iteratee'si hedefini elementId olarak DEĞİL,
|
|
2050
|
+
> komponentin iç kimliği olarak saklar (`step_iterates.DesignComponentId`, FK `SetNull`); düğüm
|
|
2051
|
+
> yeni kimlikle yazılınca eski satır silinir ve alan boşalır — `flow_get` iteratee'yi `element`'siz
|
|
2052
|
+
> döndürür. Bu yüzden **`flow_get`'ten okunan gövdeyi aynen yeniden kaydetmek onarmaz** (element
|
|
2053
|
+
> zaten yok; `flow_update` FLOW-017'ye takılır). İki güvence var: (1) backend artık AYNI yamada
|
|
2054
|
+
> silinip aynı `elementId` ile eklenen düğüme (alt ağaç dahil) eski kimliğini geri veriyor, bağ
|
|
2055
|
+
> kopmuyor; (2) gateway yamadan sonra akışları yeniden okur ve kopan her iteratee için yanıtta
|
|
2056
|
+
> `flowTargetsLost` ile hazır onarımı verir:
|
|
2057
|
+
> `flow_patch` `{ op: 'add', path: '/steps[stepId=s4]/args/iteratees/0/element', value: 'f_range' }`.
|
|
2058
|
+
> `flow_get` de hedefsiz setter iteratee'sini `flowWarnings` (`FLOW-017 (okuma)`) ile gösterir.
|
|
2059
|
+
> Ayrı isteklerle (önce sil, sonra ekle) yapılan yeniden kurulum ve komple şema yazan `page_update`
|
|
2060
|
+
> bu korumanın DIŞINDADIR — prop tipini değiştirmek için düğümü hiç yeniden kurmayın.
|
|
1958
2061
|
|
|
1959
2062
|
## Bilinen sınırlar
|
|
1960
2063
|
|
|
@@ -2029,8 +2132,11 @@ micro-op hattına dönün.
|
|
|
2029
2132
|
(süssüz) ekrana ifadenin **kendisini** basar; ifade yalnız `data`'da olursa prop **boş**
|
|
2030
2133
|
render edilir. `set_binding` micro-op'u eski sürümlerde `data`'ya yazıyordu — bu davranış
|
|
2031
2134
|
düzeltildi, ama daha önce kurulmuş sayfalarda kalıntı olabilir. Prop nesnesini birebir
|
|
2032
|
-
kontrol etmen gerekirse `
|
|
2033
|
-
`{"type":"code","ref":"{{ … }}"
|
|
2135
|
+
kontrol etmen gerekirse `replace_prop` ile
|
|
2136
|
+
`value: {"type":"code","ref":"{{ … }}"}` yaz — code tipi ve `ref` olduğu gibi kaydedilir
|
|
2137
|
+
(platform code prop'unda `data`'yı saklamaz).
|
|
2138
|
+
`replace_prop`'a `expression` alanı verme: platform onu yalnız `set_binding`'de okur (gateway
|
|
2139
|
+
code sarmalına çevirir).
|
|
2034
2140
|
|
|
2035
2141
|
- **Ana sayfa sayfadan değil application'dan değişir:** `page_create/update` gövdesindeki
|
|
2036
2142
|
`isHomepage` platformca yok sayılır (tasarım). Doğru yol `application_update` →
|