@appaflytech/zeyrek-ai-mcp 0.0.24 → 0.0.26
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/.env.example +0 -15
- package/dist/config.js +0 -11
- package/dist/index.js +0 -2
- package/dist/knowledge/componentCatalog.js +25 -13
- package/dist/knowledge/componentEvents.js +6 -13
- package/dist/knowledge/normalize.js +17 -68
- package/dist/knowledge/rules.js +49 -137
- package/dist/knowledge/styleResolve.js +4 -50
- package/dist/knowledge/themeResolve.js +3 -3
- package/dist/observability/trace.js +1 -1
- package/dist/platform/diagnostics.js +4 -10
- package/dist/platform/domSummary.js +1 -1
- package/dist/platform/http.js +7 -23
- package/dist/platform/responses.js +2 -6
- package/dist/platform/{capture/capture.js → screenshot.js} +514 -52
- package/dist/platform/secrets.js +0 -9
- package/dist/platform/strictArguments.js +12 -68
- package/dist/platform/tokenVault.js +4 -187
- package/dist/resources/examples/workflow-http-step.json +2 -2
- package/dist/resources/guides/component.md +1 -6
- package/dist/resources/guides/expressions.md +2 -2
- package/dist/resources/guides/functions.md +1 -1
- package/dist/resources/guides/layout.md +7 -11
- package/dist/resources/guides/microfunction.md +28 -0
- package/dist/resources/guides/microservice.md +4 -10
- package/dist/resources/guides/middleware.md +1 -5
- package/dist/resources/guides/page.md +55 -215
- package/dist/resources/guides/theme.md +1 -4
- package/dist/resources/guides/translation.md +1 -1
- package/dist/resources/guides/workflow.md +9 -12
- package/dist/resources/schema-fingerprint.json +2 -2
- package/dist/resources/schemas/CreateWorkflowCommand.json +3 -0
- package/dist/resources/schemas/PreviewWorkflowCommand.json +3 -0
- package/dist/resources/schemas/StepDto.json +12 -9
- package/dist/resources/schemas/UpdateWorkflowCommand.json +3 -0
- package/dist/server.js +1 -3
- package/dist/tools/applications.js +3 -60
- package/dist/tools/components.js +10 -50
- package/dist/tools/datasources.js +1 -1
- package/dist/tools/designSchemaPatch.js +6 -16
- package/dist/tools/externalComponents.js +4 -25
- package/dist/tools/flows.js +6 -79
- package/dist/tools/layouts.js +12 -44
- package/dist/tools/microservices.js +10 -26
- package/dist/tools/pages.js +67 -303
- package/dist/tools/platformInfo.js +2 -6
- package/dist/tools/rows.js +1 -7
- package/dist/tools/schemaOps.js +1 -1
- package/dist/tools/screenWrite.js +5 -6
- package/dist/tools/screens.js +3 -90
- package/dist/tools/workflows.js +1 -1
- package/package.json +1 -1
- package/dist/knowledge/mobileComponentCatalog.js +0 -801
- package/dist/knowledge/mobileComponentEvents.js +0 -225
- package/dist/knowledge/platform/lint.js +0 -312
- package/dist/knowledge/platform/mobile.js +0 -78
- package/dist/knowledge/platform/mobileRules.js +0 -182
- package/dist/knowledge/platform/mobileTabs.js +0 -108
- package/dist/knowledge/platform/profile.js +0 -20
- package/dist/knowledge/platform/resolve.js +0 -122
- package/dist/knowledge/platform/web.js +0 -38
- package/dist/knowledge/styleResolveNative.js +0 -510
- package/dist/platform/argumentAliases.js +0 -128
- package/dist/platform/bodyFile.js +0 -103
- package/dist/platform/capture/actions.js +0 -333
- package/dist/platform/capture/browser.js +0 -1
- package/dist/platform/capture/console-log.js +0 -80
- package/dist/platform/capture/index.js +0 -11
- package/dist/platform/capture/readiness.js +0 -103
- package/dist/platform/capture/summary.js +0 -77
- package/dist/platform/capture/target.js +0 -5
- package/dist/platform/capture/targets/studio-mobile.js +0 -15
- package/dist/platform/capture/targets/studio-web.js +0 -5
- package/dist/platform/schemaReadMemory.js +0 -60
- package/dist/resources/examples/mobile-app-shell-drawer.json +0 -209
- package/dist/resources/examples/mobile-app-shell-stack.json +0 -123
- package/dist/resources/examples/mobile-app-shell-tab.json +0 -174
- package/dist/resources/examples/mobile-list-detail-form.json +0 -656
- package/dist/resources/guides/mobile.md +0 -419
- package/dist/tools/mobile.js +0 -203
- package/dist/tools/profileWrite.js +0 -45
|
@@ -4,10 +4,6 @@ Studio'nun tuval tarafı. Buradaki kurallar controller + komut kodundan doğrula
|
|
|
4
4
|
(`zeyrek-mcp/docs/13-faz2-envanter.md` §4); veri/mantık tarafı için
|
|
5
5
|
`platform_guide('entity')`, `('microservice')`, `('workflow')`.
|
|
6
6
|
|
|
7
|
-
> **Mobil uygulamada** (`type: 'mobile'`) şema ve micro-op'lar aynıdır ama yerleşim yalnız flex'tir
|
|
8
|
-
> (blocks çizilmez), görünüm tipli gruplarla yazılır ve `page_create` kökü flex sütun kurar —
|
|
9
|
-
> `platform_guide('mobile')`. Bu rehberdeki "dar ekran" notları WEB uygulamasının telefon kırılımıdır.
|
|
10
|
-
|
|
11
7
|
## Kuruluş sırası
|
|
12
8
|
|
|
13
9
|
```
|
|
@@ -226,7 +222,7 @@ döndürür; hata yok, sayfalama yok. (Bağımsız `pagination` komponenti bu tu
|
|
|
226
222
|
| `dropdown.search` · `multi-select.search` | `{ searchText }` | `self.searchText` |
|
|
227
223
|
| `tabs.tab` | `{ selected }` | `self.selected` ya da `event.data.selected` |
|
|
228
224
|
| `chart.dataPointClick` | `{ name, seriesName, value, dataIndex, row }` | `self.row` (kaynak satırın tamamı) |
|
|
229
|
-
| `repeater.change` · `repeater.select` | `{ selectedIndex }` | `self.selectedIndex` · `self.selectedItem` (akış satır bağlamında koşmaz, `item`/`Row` boş)
|
|
225
|
+
| `repeater.change` · `repeater.select` | `{ selectedIndex }` | `self.selectedIndex` · `self.selectedItem` (akış satır bağlamında koşmaz, `item`/`Row` boş) |
|
|
230
226
|
| `html` aksiyonu (`fireEvent`) | ikinci argüman | **`event.data`** |
|
|
231
227
|
| `kanban.cardMove` | `{ id, row, from, to }` | **`event.data`** (self'e yazılmaz) |
|
|
232
228
|
| `kanban.cardAdd` · `kanban.cardRemove` | `{ column }` · `{ id, row, column }` | **`event.data`** (self'e yazılmaz; kart eklenmez/gizlenmez, akış yazıp `rows`'u tazeler) |
|
|
@@ -249,8 +245,7 @@ dalı bulamaz ve akışı **sessizce durdurur** (`flow-engine.ts:79`); Studio da
|
|
|
249
245
|
`sourceBranch === 'always'` ile çizdiği için panelde **Start kartından sonrası boş görünür**.
|
|
250
246
|
İstisnalar: `condition` → dal adı rule id'sidir (ve o id bir **GUID**'dir — aşağıdaki tuzak 6),
|
|
251
247
|
`confirm` → `yes|no|always`, `microservice` →
|
|
252
|
-
`always` (eski akışlarda `success` de çalışır)
|
|
253
|
-
yerine ondan sürer (2026-09-26, ADR 0004; ayrıntı aşağıdaki §"4xx de hatadır").
|
|
248
|
+
`always` (eski akışlarda `success` de çalışır).
|
|
254
249
|
|
|
255
250
|
**2. `iteratees[].type` yalnız `change` | `fill`.** `setter.ts` başka değerde hiçbir dala
|
|
256
251
|
girmez — adım çalışır, hiçbir şey yapmaz. `change` tek prop'a değer yazar, `fill` diziyi
|
|
@@ -376,42 +371,36 @@ Satır eşlemeli tablo yüklemesinin tam şekli (yükleniyor bayrağı → uç
|
|
|
376
371
|
göstermek error flow'un işidir.
|
|
377
372
|
|
|
378
373
|
> **4xx de hatadır ve `always` dalı seni KURTARMAZ.** `microservice.ts` `.catch` bloğu
|
|
379
|
-
> reddedilen her istekte koşar — 401/403/404/422 dâhil
|
|
380
|
-
>
|
|
381
|
-
> 2026-09-26 — eskiden hata gövdesi `data`'ya yazılıyordu). `.finally` sonra ÜÇ yoldan birini
|
|
382
|
-
> dener, SIRAYLA:
|
|
374
|
+
> reddedilen her istekte koşar — 401/403/404/422 dâhil. Sonrası iki yoldan biridir ve ikisi de
|
|
375
|
+
> "ekranda hiçbir şey olmadı" ile biter:
|
|
383
376
|
>
|
|
384
|
-
> 1. **
|
|
385
|
-
>
|
|
386
|
-
>
|
|
387
|
-
>
|
|
388
|
-
>
|
|
389
|
-
>
|
|
390
|
-
>
|
|
391
|
-
> akış sessizce diğer dala düşer — `else` dalı bağlı değilse akış orada biter. `data`yı bir
|
|
392
|
-
> liste prop'una yazan bir setter artık patlayan bir nesne değil `null` görür (repeater/table
|
|
393
|
-
> `null`'ı boş liste sayar), ama hata OLDUĞUNU fark etmeden geçer — gateway bunu **FLOW-028**
|
|
394
|
-
> ile uyarır.
|
|
377
|
+
> 1. **Hata yolu VARSA** `engine.onError` true döner ve `.finally` `return` eder —
|
|
378
|
+
> `engine.next('always')` **hiç çağrılmaz**. Yani `always` ile `errorSteps` birbirini dışlar;
|
|
379
|
+
> ikisini birden kuramazsın, hata yolu ana akışın devamını devralır.
|
|
380
|
+
> 2. **Hata yolu YOKSA** `always` koşar, ama storage artık `{ error, data }`'dır ve
|
|
381
|
+
> `Steps.<ad>.data` başarı gövdesi değil **hata gövdesidir**. Sıradaki `condition`
|
|
382
|
+
> `!!Steps.signIn.data.token` gibi bir ifadeyi `undefined` üzerinden değerlendirir, sessizce
|
|
383
|
+
> diğer dala düşer ve `else` dalı bağlı değilse akış orada biter.
|
|
395
384
|
>
|
|
396
385
|
> **`errorSteps` yalnız `start` taşıyorsa hata yolu YOKTUR:** `hasErrorFlow`
|
|
397
386
|
> `errorTasks.some(t => t.type !== 'start')` arar. Start'ın ardına en az bir adım bağla —
|
|
398
387
|
> gateway `FLOW-021` ile uyarır.
|
|
399
388
|
>
|
|
400
|
-
> **
|
|
401
|
-
> `
|
|
389
|
+
> **Mobilde `errorSteps` diye bir şey YOK.** `ScreenRuntime.tsx` `mapFlowsToMachine` yalnız
|
|
390
|
+
> `tasks` üretir (web `Runtime.svelte` ayrıca `errorTasks` verir), yani mobil uygulamada
|
|
391
|
+
> `hasErrorFlow` her zaman false: hata yolu hiç koşmaz ve akış yukarıdaki 2. yoldan —
|
|
392
|
+
> `always` + hata gövdeli storage — devam eder. Mobil sayfada hata yolunu `condition
|
|
393
|
+
> Steps.<adımAdı>.error` ile kur.
|
|
402
394
|
|
|
403
|
-
> **Hata metni
|
|
395
|
+
> **Hata metni ÜÇ ayrı yerde durur ve ikisi kullanıcıya gösterilecek metin DEĞİLDİR.**
|
|
404
396
|
> `onError` hata akışını koşturmadan önce `machine.setStorage('error', errorInfo)` yapar
|
|
405
|
-
> (`flow-engine.ts`), yani hata akışının adımları `Steps.error`'ı okuyabilir
|
|
406
|
-
> KENDİ storage'ı ise (bağlı `error` dalı da `always` da) `Steps.<adımAdı>.error` nesnesini taşır:
|
|
397
|
+
> (`flow-engine.ts`), yani hata akışının adımları `Steps.error`'ı okuyabilir:
|
|
407
398
|
>
|
|
408
399
|
> | İfade | Ne taşır | Kaynak |
|
|
409
400
|
> |---|---|---|
|
|
410
|
-
> | **`Steps.error.message`** | **
|
|
411
|
-
> | `Steps.<adımAdı>.error
|
|
412
|
-
> | `Steps.<adımAdı>.
|
|
413
|
-
> | `Steps.<adımAdı>.error.body` | Ucun hata gövdesi — eski `Steps.<adımAdı>.data`'nın taşındığı yer | `microservice.ts` `.catch` |
|
|
414
|
-
> | `Steps.<adımAdı>.data` | **HER ZAMAN `null`**'dır — başarı gövdesi değil, hiçbir gövde değil (eskiden hata gövdesiydi) | `microservice.ts` `.catch` |
|
|
401
|
+
> | **`Steps.error.message`** | **Ucun kendi mesajı** — `err.response.data.message`; boşsa HTTP durum metnine düşer. **Kullanıcıya gösterilecek metin budur.** Yanında `Steps.error.code` · `Steps.error.step.name` (patlayan adım) · `Steps.error.step.data` (ucun gövdesi) gelir | `microservice.ts` `err.reason \|\| HttpStatusText[err.code]` → `flow-engine.ts` `onError` |
|
|
402
|
+
> | `Steps.<adımAdı>.error` | Yalnız HTTP **durum metni** — 401 için `'Unauthorized'`. Hata OLDUĞUNU anlamaya yarar, göstermeye değil | `microservice.ts` `.catch` `HttpStatusText[err.code]` |
|
|
403
|
+
> | `Steps.<adımAdı>.data` | Ucun **hata gövdesi** (`err.response.data`) — başarı gövdesi değil. `.message` alanı burada da vardır | `microservice.ts` `.catch` |
|
|
415
404
|
>
|
|
416
405
|
> **`alert` adımının `message`'ı DÜZ METİNDİR — ifade yazarsan ekranda o ifade görünür.**
|
|
417
406
|
> `alert.ts` `task.argument.message`'ı doğrudan `toast.error()`'a geçirir ve `args` hiçbir yerde
|
|
@@ -439,24 +428,15 @@ göstermek error flow'un işidir.
|
|
|
439
428
|
> `{ "type": "confirm", "args": { "message": "Bu risk ve 4 aksiyonu silinecek.", "title": "Riski sil",
|
|
440
429
|
> "confirmText": "Sil", "cancelText": "Vazgeç" } }`.
|
|
441
430
|
|
|
442
|
-
> **Hangi yolu seçeceksin —
|
|
443
|
-
>
|
|
444
|
-
> olabilir ama aynı anda yalnız biri koşar: **`error` dalı bağlıysa o kazanır**, yoksa
|
|
445
|
-
> `errorSteps`, ikisi de yoksa `always` + `condition`:
|
|
446
|
-
>
|
|
447
|
-
> | | adımın kendi `error` dalı (g-02) | `errorSteps` | ana akışta `condition !!Steps.<adımAdı>.error` |
|
|
448
|
-
> |---|---|---|---|
|
|
449
|
-
> | Kapsam | yalnız BU adımın hatası | akıştaki HERHANGİ bir adımın hatası | yalnız BU adımın hatası |
|
|
450
|
-
> | Ana akışın kalanı | **koşmaz** — bu dal devralır | **koşmaz** — hata akışı devralır | koşar, dalı sen seçersin |
|
|
451
|
-
> | Yükleniyor bayrağı · modal kapatma · tablo tazeleme | dalda **yeniden kurmak zorundasın** | hata akışında **yeniden kurmak zorundasın**; kurmazsan bayrak açık kalır | zaten ana akışta duruyor |
|
|
452
|
-
> | Hata metni | `Steps.<adımAdı>.error.message` | `Steps.error.message` (yukarıdaki tablo) | `Steps.<adımAdı>.error.message`; hata olduğunu `!!Steps.<adımAdı>.error` söyler — `.error.status` parametre ifadesi patladıysa `null`dur, o yolu KAÇIRIR |
|
|
453
|
-
> | Ne zaman doğru | hata anında BU adımın sonrası **tamamen başka bir yola** sapacaksa | hata anında akış **tamamen başka bir yola** sapacaksa (başarısız giriş, yetkisiz sayfa) | kalan adımların çoğu hata hâlinde de koşacaksa — **form gönderimlerinin varsayılanı budur** (Kural 7) |
|
|
431
|
+
> **Hangi yolu seçeceksin — `errorSteps` mi, ana akışta `condition` mı?** İkisi birden
|
|
432
|
+
> kurulamaz (yukarıdaki 1. madde), yani bu bir tercih değil bir karar:
|
|
454
433
|
>
|
|
455
|
-
>
|
|
456
|
-
>
|
|
457
|
-
>
|
|
458
|
-
>
|
|
459
|
-
>
|
|
434
|
+
> | | `errorSteps` | ana akışta `condition Steps.<adımAdı>.error` |
|
|
435
|
+
> |---|---|---|
|
|
436
|
+
> | Ana akışın kalanı | **koşmaz** — hata akışı devralır | koşar, dalı sen seçersin |
|
|
437
|
+
> | Yükleniyor bayrağı · modal kapatma · tablo tazeleme | hata akışında **yeniden kurmak zorundasın**; kurmazsan bayrak açık kalır | zaten ana akışta duruyor |
|
|
438
|
+
> | Hata metni | `Steps.error.message` (yukarıdaki tablo) | `Steps.<adımAdı>.data.message`, hata olduğunu `Steps.<adımAdı>.error` söyler |
|
|
439
|
+
> | Ne zaman doğru | hata anında akış **tamamen başka bir yola** sapacaksa (başarısız giriş, yetkisiz sayfa) | kalan adımların çoğu hata hâlinde de koşacaksa — **form gönderimlerinin varsayılanı budur** (Kural 7) |
|
|
460
440
|
|
|
461
441
|
Zorunlu filtresi olan uçlarda (`patient-*`, `doctor-appointments` gibi `isRequired: true`
|
|
462
442
|
filtreli microservice'ler) parametreyi adımda ver, yoksa uç `MissingParameterException` atar:
|
|
@@ -533,21 +513,21 @@ Tarif: `platform_guide('middleware')`.
|
|
|
533
513
|
|
|
534
514
|
**Sözlükler** (`StepType.cs`, `StepParameterValueType.cs` — hepsi küçük harf):
|
|
535
515
|
`start · microservice · setter · setcookie · validation · condition · redirect · alert ·
|
|
536
|
-
confirm · flow-trigger · storage · navigate · code · download · function ·
|
|
516
|
+
confirm · flow-trigger · storage · navigate · code · download · function · end`
|
|
537
517
|
değer tipleri: `static · page · property · storage · variable · code · item · state`
|
|
538
518
|
|
|
539
519
|
> **Sözlükte olmak KOŞACAĞI anlamına gelmez — koşan tipler barındırıcıdan gelir.** Motor yedi
|
|
540
520
|
> tip register eder, gerisini uygulama ekler. Bir sayfa TEK bir uygulamaya aittir
|
|
541
521
|
> (`Page.ApplicationId`) ve uygulamanın tipi `web` ya da `mobile`'dır (`ApplicationType.cs`), yani
|
|
542
522
|
> sayfanın barındırıcısı bellidir — matris "hangi tip sende çalışır"ı söyler, iki barındırıcıda
|
|
543
|
-
> birden koşmayı değil (web `Runtime.svelte`, mobil
|
|
523
|
+
> birden koşmayı değil (web `Runtime.svelte`, mobil `ScreenRuntime.tsx`):
|
|
544
524
|
>
|
|
545
|
-
> | Adım tipi | Web | Mobil
|
|
525
|
+
> | Adım tipi | Web | Mobil | Nerede register ediliyor |
|
|
546
526
|
> |---|---|---|---|
|
|
547
|
-
> | `start` · `setter` · `code` · `condition` · `microservice` · `validation` · `flow-trigger` · `function` | ✅ | ✅ | `flow-engine.ts` — motorun kendisi |
|
|
548
|
-
> | `alert` · `redirect` · `setcookie` · `storage` | ✅ | ✅ |
|
|
549
|
-
> | `confirm` · `download`
|
|
550
|
-
> | `navigate` | ❌ | ✅
|
|
527
|
+
> | `start` · `setter` · `code` · `condition` · `microservice` · `validation` · `flow-trigger` · `function` | ✅ | ✅ | `flow-engine.ts` — motorun kendisi (`function` mobilde kayıtlıdır ama mobil runtime `Functions`'ı boş kurar — K11, çağrı çalışmaz) |
|
|
528
|
+
> | `alert` · `redirect` · `setcookie` · `storage` | ✅ | ✅ | uygulama; mobilde `redirect` navigate, `setcookie` storage uygulamasına eşlenir |
|
|
529
|
+
> | `confirm` · `download` | ✅ | ❌ | yalnız `Runtime.svelte` |
|
|
530
|
+
> | `navigate` | ❌ | ✅ | yalnız `ScreenRuntime.tsx` — web'deki karşılığı `redirect` |
|
|
551
531
|
> | `end` · `query` | ❌ | ❌ | hiçbir yerde — üstelik `query` backend sözlüğünde de yok (`StepType.cs` onu saymaz), yalnız frontend enum'unda duruyor |
|
|
552
532
|
>
|
|
553
533
|
> **Register edilmemiş bir tipe gelen akış SESSİZCE durur.** `flow-engine.ts` `process()`
|
|
@@ -583,19 +563,6 @@ değer tipleri: `static · page · property · storage · variable · code · it
|
|
|
583
563
|
> adımında ve `{{ }}` bağlamasında `Functions.<ad>(…)` ile de çağrılır; gateway bilinmeyen adı ve
|
|
584
564
|
> fazla argümanı FLOW-025 ile uyarır. Tam gövde `ngapps://examples/flow-call-function`, kurallar
|
|
585
565
|
> **`platform_guide('functions')`**.
|
|
586
|
-
>
|
|
587
|
-
> **`share` adımı ("Share")** metin ve bağlantı paylaşır: `args: { title, message, path }`. `title`
|
|
588
|
-
> DÜZ METİNDİR (ifade yazılırsa FLOW-022 uyarır); `message` ve `path` `storage.value` gibi
|
|
589
|
-
> İFADEDİR — düz metin tırnak ister (`"'Şuna bak'"`, `"'https://…/urun/' + Page.queryParams.id"`).
|
|
590
|
-
> Bağlantının adı `url` DEĞİL `path`'tir: backend `Title`/`Message`/`Path` alanlarında saklar ve
|
|
591
|
-
> tanımadığı anahtarı 200 ile sessizce düşürür (FLOW-027 `url`/`link`/`text`'i ve tırnaksız adresi
|
|
592
|
-
> bloklar). Bağlantı ŞEMALI TAM ADRES olmalı (`https://…`, `mailto:…`): şemasız değer (`www.…`,
|
|
593
|
-
> `urun/42`) adres sayılmaz, metnin sonuna eklenir. İfadenin sonucu yalnız dize ya da sayıysa
|
|
594
|
-
> paylaşılır; `false` (`koşul && 'x'`), `null` ve nesne boş sayılır. Cihazda paylaşım sayfası açılır
|
|
595
|
-
> (Android'de bağlantı metnin sonuna eklenir), web'de tarayıcının paylaşım penceresi, yoksa ya da
|
|
596
|
-
> reddederse metin + bağlantı panoya yazılır ve bildirim çıkar. Tek dal `always`: iOS'ta sayfa
|
|
597
|
-
> kapanınca, Android'de seçici açılır açılmaz (RN seçicinin kapanışını bildirmez) sürer; metin de
|
|
598
|
-
> bağlantı da boşsa hiçbir şey açılmaz, akış hemen sürer.
|
|
599
566
|
|
|
600
567
|
> Bir microservice adımı kaydedildiğinde platform `args.microserviceSchema`'yı
|
|
601
568
|
> (parameterScheme + returnScheme + `isReturnArray`) kendisi doldurur — `flow_get` ile geri
|
|
@@ -894,7 +861,7 @@ kullanır: `page.mappers.ts` `mapPageLayoutToPreview` — layout varsa çizilen
|
|
|
894
861
|
> `add_component` ile yeniden kurmaktır (sonrasında Kural 2'deki flow yeniden kaydetme adımı
|
|
895
862
|
> ZORUNLU olur).
|
|
896
863
|
|
|
897
|
-
|
|
864
|
+
Mobil not: <768px'te ızgara tek kolona düşer (`RenderComponent` media query'si) — y sırası
|
|
898
865
|
dikey sıraya dönüşür, x/w yok sayılır. Yerleşimi masaüstü (breakpoint 1024) bloğuyla kur.
|
|
899
866
|
|
|
900
867
|
## Kural 1f-2 — Kapsayıcı düzeni: `flex` (varsayılan) ↔ `grid`
|
|
@@ -983,10 +950,10 @@ Beş şeyi bilmeden flex kurma:
|
|
|
983
950
|
4. **`layout: 'grid'` iken diğer altı prop ÖLÜDÜR.** Katalogda tanımlı oldukları için
|
|
984
951
|
doğrulama duvarı susar, renderer da okumaz: ızgara kapsayıcıya `direction: 'column'` yazmak
|
|
985
952
|
sessizce hiçbir şey yapmaz. Gateway bunu **PAGE-015 (uyarı)** ile söyler.
|
|
986
|
-
5. **Flex düzeni kırılım BİLMEZ.** `direction`/`gap`/hizalama masaüstü ve
|
|
987
|
-
sıra ve span'lar Desktop (1024) bloğundandır — Studio,
|
|
953
|
+
5. **Flex düzeni kırılım BİLMEZ.** `direction`/`gap`/hizalama masaüstü ve mobilde AYNIDIR;
|
|
954
|
+
sıra ve span'lar Desktop (1024) bloğundandır — Studio, mobil kırılım düzenlenirken flex
|
|
988
955
|
bölgeyi salt-okunur kilitler. Kırılım bilen yalnız `blocks[]` ve `appearance.hideOn`'dur;
|
|
989
|
-
|
|
956
|
+
mobilde farklı davranış gereken satır için `layout: 'grid'` kullan (Kural 1f mobil notu).
|
|
990
957
|
|
|
991
958
|
```jsonc
|
|
992
959
|
// Ortalanmış giriş kartı — style ile CSS hack'i YOK, kabın kendi düzeni
|
|
@@ -1113,22 +1080,15 @@ UYGULAMAZ** — koordinatları aynen kaydeder (aşağı itme yalnız `page_creat
|
|
|
1113
1080
|
> SONRAKİ ağaca bakarak. Layout'ta da geçerlidir: kırılma
|
|
1114
1081
|
> `_repeaterValues` geri yazmasındadır, barındıranın sayfa mı layout mu olduğuna bakmaz.
|
|
1115
1082
|
>
|
|
1116
|
-
> **Mobil uygulamada** başlıklar altında gruplu liste (güne/kategoriye göre) iç içe repeater
|
|
1117
|
-
> gerektirmez: tek `grouped-list` (`groupBy` + başlık `{{ Section.title }}` + öğe şablonu) —
|
|
1118
|
-
> `platform_guide('mobile')` §Güne göre görev listesi. PAGE-013 mesajı mobilde bunu önerir.
|
|
1119
|
-
>
|
|
1120
1083
|
> **Yapılacak:** satır içi listeyi tek bir `textarea`'da **satır başına bir öğe** olarak topla
|
|
1121
1084
|
> (`options_text`), kaydederken `split('\n')`'le böl. Ölçülmüş çalışan sürüm: anket editörü
|
|
1122
1085
|
> (`anket-admin/anket-duzenle`). Gerçekten satır satır düzenleme gerekiyorsa iç listeyi AYRI bir
|
|
1123
1086
|
> sayfada/modalda yönet — iç içe repeater bunu karşılamıyor.
|
|
1124
1087
|
|
|
1125
1088
|
> **Repeater satırını akıştan silmek/eklemek:** repeater ÇOCUĞUNDAKİ bir butonun click akışında
|
|
1126
|
-
>
|
|
1127
|
-
>
|
|
1128
|
-
>
|
|
1129
|
-
> `q_list.rows = (q_list.rows || []).filter(function(r, i){ return i !== q_list.selectedIndex; })`.
|
|
1130
|
-
> `RowIndex` de aynı satırı verir, ama yalnız ARC-121 düzeltmesini (2026-09-27) taşıyan runtime'da;
|
|
1131
|
-
> eskisinde akışta tanımsızdı.
|
|
1089
|
+
> `RowIndex` doğru satırı verir, ve hedef repeater'ın KENDİSİ olduğu için `rows`'a yazmak serbesttir
|
|
1090
|
+
> (`isRepeaterSelf` dalı satır-değeri yoluna girmez). Ölçülmüş desen:
|
|
1091
|
+
> `q_list.rows = (q_list.rows || []).filter(function(r, i){ return i !== RowIndex; })`.
|
|
1132
1092
|
> Ekleme aynı şekilde `.slice()` + `push` ile yapılır; satır numarasını ekledikten sonra yeniden ata.
|
|
1133
1093
|
|
|
1134
1094
|
**Gönderimi saklamak:** satır başına normalize kayıt yerine tek `TEXT` kolonda anlık görüntü
|
|
@@ -1137,45 +1097,6 @@ kendisi nesneye çevirir; Studio tablosunda `[object Object]` görünmesi normal
|
|
|
1137
1097
|
(`platform_guide('entity')` → "TEXT kolonunda JSON"). Ekranın görsel tarafı için **Kural 1h**:
|
|
1138
1098
|
tema `--ng-*` değişkenleriyle tek yerden çevrilir, `html` kaçış kapısına gerek kalmaz.
|
|
1139
1099
|
|
|
1140
|
-
## Kural 1g-2 — Mobil davranış: dört ayar, dört ayrı sahip
|
|
1141
|
-
|
|
1142
|
-
Mobil listelerin davranışı TEK bileşende toplanmaz. Hangi ayarın kimde olduğunu bilmeden yazılan
|
|
1143
|
-
şema sessizce çalışmaz — prop var olmayan bileşene yazılır ve `page_schema_patch` onu düşürmez,
|
|
1144
|
-
çizer yok sayar.
|
|
1145
|
-
|
|
1146
|
-
| Davranış | Sahip bileşen | Prop / olay |
|
|
1147
|
-
|---|---|---|
|
|
1148
|
-
| Çekerek yenile | `scroll-view` (listeyi SARAN kap) | `refreshable: true` + `refresh` olayı |
|
|
1149
|
-
| Sonsuz kaydırma | `scroll-view` | `scrollEnd` olayı (prop yok) |
|
|
1150
|
-
| Kaydırma eylemleri | `repeater` | `swipeActions: [{ key, label, tone, icon }]` + `swipe` olayı, payload `{ key, index, row }` |
|
|
1151
|
-
| Satıra dokunma | `repeater` | `itemPressable: true` + `itemPress` olayı, payload `{ index, row }` |
|
|
1152
|
-
|
|
1153
|
-
Çekerek yenileyi `repeater`'a yazmak en sık hatadır: liste kendi kaydırmasını yapmaz, onu saran
|
|
1154
|
-
`scroll-view` yapar. `repeater` kökteyse (kap yok) yenileme hiç çizilmez.
|
|
1155
|
-
|
|
1156
|
-
Satıra dokunmanın kartın `click`'iyle yapılan eski yolu mobilde bırakıldı: `itemPress` satır
|
|
1157
|
-
bağlamını payload'da taşır ve seçimi (`selectedIndex`) de yazar, yani akış satırı
|
|
1158
|
-
`<tekrarlayıcı>.selectedItem` ile okumaya devam eder.
|
|
1159
|
-
|
|
1160
|
-
### `redirect.presentation`
|
|
1161
|
-
|
|
1162
|
-
`redirect` adımının `args.presentation` alanı ekranın NASIL açıldığını söyler ve kapalı bir küme
|
|
1163
|
-
alır:
|
|
1164
|
-
|
|
1165
|
-
- `push` — yığına ekler, geri düğmesi önceki ekrana döner (**varsayılan**; alan yazılmayabilir)
|
|
1166
|
-
- `modal` — alttan açılan ayrı bir sunum; geri onu kapatır, altındaki ekran yerinde kalır
|
|
1167
|
-
- `replace` — geçerli ekranı değiştirir, geçmişe girmez (giriş → ana ekran için doğru olan)
|
|
1168
|
-
|
|
1169
|
-
Küme dışı bir değer **MOB-008** uyarısıdır ve backend doğrulayıcısı 422 döner. Alanı hiç yazmamak
|
|
1170
|
-
kusur değildir.
|
|
1171
|
-
|
|
1172
|
-
**Sekme hedefinde `modal` çalışmaz.** Hedef sayfa bir sekmeyse gezinme her zaman `navigate`'e
|
|
1173
|
-
düşer: sekme yığını kendi geçmişini tutar ve modal onu kırardı. `presentation`ı yazabilirsiniz,
|
|
1174
|
-
çizer sessizce yok sayar — sekme dışı bir sayfaya modal istiyorsanız o sayfayı sekme listesinden
|
|
1175
|
-
çıkarın.
|
|
1176
|
-
|
|
1177
|
-
Web uygulamasında alan yok sayılır; gateway web profilinde bu konuda bulgu üretmez.
|
|
1178
|
-
|
|
1179
1100
|
## Kural 1h — Tasarım: `style` prop'u ve tema değişkenleri
|
|
1180
1101
|
|
|
1181
1102
|
Her komponentin `style` prop'u vardır ve emotion `css()` bloğudur: iç seçiciler, pseudo-class'lar
|
|
@@ -1402,16 +1323,6 @@ alanları silinir. Gateway bu yüzden `page_update`'te sayfayı önce okur, yaln
|
|
|
1402
1323
|
alanları değiştirip tam gövdeyi geri yazar (`layout_update` ve `component_update` de aynı).
|
|
1403
1324
|
Yine de `schema` parametresini elle doldurursan okuduğun hâli değil, **verdiğin liste** yazılır.
|
|
1404
1325
|
|
|
1405
|
-
**`page_update` sürümsüz yazmaz (PAGE-039).** Platform sayfa PUT'unu `baseVersion` olmadan reddeder.
|
|
1406
|
-
`baseVersion` vermezsen gateway bu sayfada en son gördüğü sürümü gönderir: `page_get` ya da
|
|
1407
|
-
`page_schema_get` yanıtındaki `version`, `page_schema_patch`'in `newVersion`'ı ya da önceki
|
|
1408
|
-
`page_update`'in yazdığı sürüm. Hiçbiri yoksa istek **gönderilmez** — önce oku. Sayfa o sürümden beri
|
|
1409
|
-
değiştiyse (Studio'da açık sekme, başka ajan) 409 döner; mesaj güncel sürümü ve son yazmayı (zaman,
|
|
1410
|
-
kullanıcı, kaynak, revizyon) söyler ve hiçbir şey yazılmaz. Doğru yol yeniden okuyup değişikliği
|
|
1411
|
-
`page_schema_patch` ile yapmaktır; aradaki değişikliği bilerek ezmek için `force: true` son sürümü
|
|
1412
|
-
okuyup onun üstüne yazar ve yanıt `forced: true` taşır. Sebep: Bitki Bakım koşusunda sürümsüz bir
|
|
1413
|
-
tam gövde yazımı ana sayfayı ve profili boşalttı, akışları sildirdi (14:02).
|
|
1414
|
-
|
|
1415
1326
|
### Atomiklik: 500 KB'lık şemada tek komponente dokunmak
|
|
1416
1327
|
|
|
1417
1328
|
`page_schema_patch` şemanın tamamını göndermez — yalnız op'ları gönderir. Tam gövde ne LLM
|
|
@@ -1421,8 +1332,7 @@ ve geri yazar. Sözleşme (`PatchPageSchemaCommandHandler`):
|
|
|
1421
1332
|
| Aşama | Ne yapar |
|
|
1422
1333
|
|---|---|
|
|
1423
1334
|
| Kilit | Sayfa başına 60 sn'lik dağıtık kilit; başka bir aktör yazıyorsa istek `PageSchemaLockedException` ile döner (409) |
|
|
1424
|
-
| Sürüm | `baseVersion` verdiysen `UpdatedAt.Ticks` ile karşılaştırılır; tutmazsa `PageSchemaVersionConflictException` (409) ve **hiçbir op uygulanmaz**
|
|
1425
|
-
| Tekrar | `add_component`'in `elementId`'si zaten varsa ve düğüm istenen ebeveynde, istenen içerikle duruyorsa op **etkisizdir** (hata değil; konum karşılaştırılmaz). Hedef düğümü değiştirmeyen `replace_prop`/`set_*`/`add_event` da etkisizdir. Bütün op'lar etkisizse yama yazılmaz, sürüm artmaz ve eski `baseVersion`'a rağmen 200 `noop: true` döner; sürüm eskiyse `stale: true` ve `newVersion` sizin gönderdiğinizdir. Aynı id'de farklı düğüm hâlâ 422 `duplicate-id`'dir |
|
|
1335
|
+
| Sürüm | `baseVersion` verdiysen `UpdatedAt.Ticks` ile karşılaştırılır; tutmazsa `PageSchemaVersionConflictException` (409) ve **hiçbir op uygulanmaz** |
|
|
1426
1336
|
| Uygulama | Her op hedefini ağaçta arar (`Find` → JSON Pointer) ve **yalnız o düğüme** dokunur; kardeşler, üst düğümler ve diğer alt ağaçlar bit düzeyinde korunur |
|
|
1427
1337
|
| Hep-ya-hiç | Op'lar önce bellekte uygulanır; **tek bir hata** (bilinmeyen op, bulunamayan hedef, tekrar eden elementId, doğrulama) tüm komutu düşürür — kısmi yazma yoktur |
|
|
1428
1338
|
| Doğrulama | Tam şema `PageSchemaValidator`'dan geçer (422 + alan bazlı `errors`) |
|
|
@@ -1431,18 +1341,7 @@ ve geri yazar. Sözleşme (`PatchPageSchemaCommandHandler`):
|
|
|
1431
1341
|
|
|
1432
1342
|
Yanıt üç alan döner: `applied` (uygulanan op sayısı), **`appliedPatch`** (her op'un şemada tam
|
|
1433
1343
|
olarak hangi JSON Pointer'a ne yaptığı — RFC 6902 biçiminde; "gerçekten yalnız o komponente mi
|
|
1434
|
-
dokunuldu" sorusunun kanıtı) ve **`newVersion`** (`UpdatedAt.Ticks`).
|
|
1435
|
-
(elementId listesi) ve `alreadyApplied` cümlesi gelir; hepsi etkisizse `noop: true`.
|
|
1436
|
-
|
|
1437
|
-
**Yanıt kaybolursa aynı gövdeyle tekrarla.** Ağ koptu, zaman aşımı oldu ve yamanın uygulanıp
|
|
1438
|
-
uygulanmadığını bilmiyorsan aynı `page_schema_patch`'i **aynı gövde ve aynı `baseVersion`** ile
|
|
1439
|
-
yeniden gönder. Uygulanmışsa `noop: true` + `alreadyApplied` döner, hiçbir şey ikinci kez yazılmaz;
|
|
1440
|
-
uygulanmamışsa yama şimdi uygulanır. `add_component` (gövdede `id` verme — platform her istekte yeni
|
|
1441
|
-
`id` üretir, karşılaştırma onu yok sayar), aynı değeri yazan `replace_prop`/`set_*` ve aynı bağı kuran
|
|
1442
|
-
`add_event` tekrarda etkisizdir. İki istisna: `remove_component` ikinci kez `unknown-target` döner — o
|
|
1443
|
-
durumda `page_schema_get` ile bak; eklediğin düğümün bir prop'unu aynı yamanın sonraki op'u
|
|
1444
|
-
değiştirdiyse tekrar `duplicate-id` alır. Yanıt `stale: true` taşıyorsa sayfa sürümünden beri başka bir
|
|
1445
|
-
yazımla da değişmiştir: devam etmeden önce yeniden oku. `idempotencyKey` yoktur ve gerekmez.
|
|
1344
|
+
dokunuldu" sorusunun kanıtı) ve **`newVersion`** (`UpdatedAt.Ticks`).
|
|
1446
1345
|
|
|
1447
1346
|
> **`appliedPatch` gövdesi VARSAYILAN OLARAK iskelettir.** Girdi `{ op, path }` döner; eklenen
|
|
1448
1347
|
> düğüm `component` altında yalnız `id`/`elementId`/`name`/`type`/`children` taşır. Kanıt zaten
|
|
@@ -1462,29 +1361,12 @@ yamanın `baseVersion`'ıdır. Kontrol platformda atomiktir (satır kilidi + sü
|
|
|
1462
1361
|
`UPDATE`'te), yani iki çağrı arasına giren yazarı da yakalar. `baseVersion` vermezsen gateway yalnız
|
|
1463
1362
|
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
|
|
1464
1363
|
yazan kazanır. Eski `expectedUpdatedAt` hâlâ çalışır ama `baseVersion`'ın yerini tutmaz.
|
|
1465
|
-
|
|
1466
|
-
**Studio da sürüm gönderir (2026-09-26, ZM-27).** Önceden Studio'da açık kalan bir sekme, yayını
|
|
1467
|
-
kaçırdığı yamalarının üstüne kendi eski (bir kez boş) şemasını yazıyor ve bağı kalmayan akışları
|
|
1468
|
-
sildiriyordu. Artık Studio'nun her kaydı sürüm taşır: eski sekme 409 alır ve taslağını senin
|
|
1469
|
-
yazdığının üstüne birleştirir. `revision_list`'te yamandan sonra `source: studio` satırı görürsen bu
|
|
1470
|
-
artık bir üzerine yazma değil, birleştirilmiş bir kayıttır — yine de `revision_diff` ile bak.
|
|
1471
1364
|
Yanıttaki `touched`, kaydı değişen elementId'leri listeler (eklenen alt ağaç dâhil).
|
|
1472
1365
|
|
|
1473
1366
|
> **Büyük şemada çalışma sırası:** `mode:'summary'` ile ağacı çıkar (props yok, 500 KB'lık sayfada
|
|
1474
1367
|
> bile küçük) → hedefin `elementId`'sini al → gerekiyorsa `mode:'subtree'` ile yalnız o dalı oku →
|
|
1475
1368
|
> op'ları `page_schema_validate` ile kuru koştur → `page_schema_patch`. `mode:'full'` yalnız
|
|
1476
1369
|
> gerçekten tüm şema gerektiğinde çağrılır.
|
|
1477
|
-
>
|
|
1478
|
-
> **`full` sığmazsa hata verir, kırpmaz.** Yanıt boyut sınırını aşan şemada `mode:'full'` hata döner
|
|
1479
|
-
> ve düğüm sayısını söyler. Tamamı gerekiyorsa `cursor:'0'` ile oku ve `nextCursor` gelmeyene kadar
|
|
1480
|
-
> sür: her parça `items[]` taşır, kalem `parentElementId` düğümünün `children[index]`'inin yerine
|
|
1481
|
-
> geçer (`parentElementId` yoksa kök dizinin `[index]`'i); alt ağacı sığmayan düğüm kabuk gelir
|
|
1482
|
-
> (`children: [{ elementId, deferred: true }]`) ve sonraki kalemler onu doldurur. Toplanan düğüm sayısı
|
|
1483
|
-
> `nodeCount`'a eşit değilse okuma eksiktir. Okuma arasında sayfa değişirse 409 — baştan başla.
|
|
1484
|
-
> `allowTruncated:true` kırpılmış gövdeyi açıkça verir (`truncated: true`); o gövdeye dayanan
|
|
1485
|
-
> `page_schema_patch` PAGE-038 uyarısı taşır. **`page_update`'e kırpık ya da yarım şema gönderme:**
|
|
1486
|
-
> PUT tam REPLACE'tir, eksik düğümler geri dönüşsüz silinir — gateway düğüm eksilten şemayı
|
|
1487
|
-
> `allowNodeLoss:true` olmadan PAGE-037 ile reddeder.
|
|
1488
1370
|
|
|
1489
1371
|
> **`remove_component`'in yan etkisi — tek istisna.** Sayfa kaydedilirken artık hiçbir komponent
|
|
1490
1372
|
> olayının, prop'unun ya da sayfa olayının referans vermediği akışlar platformca **kalıcı olarak
|
|
@@ -1909,24 +1791,15 @@ page_container
|
|
|
1909
1791
|
```
|
|
1910
1792
|
start → [setter] btn.isLoading = true, btn.isDisabled = true, notification gizle
|
|
1911
1793
|
→ [microservice] sign-in (POST; email + password body'den)
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
│ → [redirect] hedef sayfaya
|
|
1920
|
-
└─ else → [setter] notification.content =
|
|
1921
|
-
{ type:'code', ref:'Steps.signIn.error?.message ?? "Giriş başarısız"' }
|
|
1794
|
+
→ [condition] !!Steps.signIn.data.token
|
|
1795
|
+
├─ always → [setter] buton durumunu sıfırla
|
|
1796
|
+
├─ if → [setcookie] { name:'APP_Token', value:'Steps.signIn.data.token',
|
|
1797
|
+
│ expiresInHours: 240 }
|
|
1798
|
+
│ → [redirect] hedef sayfaya
|
|
1799
|
+
└─ else → [setter] notification.content =
|
|
1800
|
+
{ type:'code', ref:'Steps.signIn.data.message || "Giriş başarısız"' }
|
|
1922
1801
|
```
|
|
1923
1802
|
|
|
1924
|
-
- **`sign-in` adımının `error` dalı burada ZORUNLUDUR, süs değil.** Dal bağlı değilken bu şablonun
|
|
1925
|
-
`condition`'ı `Steps.signIn.data.token`'ı okur ve gateway'i **FLOW-028** ile uyarır (yukarıdaki
|
|
1926
|
-
"Hangi yolu seçeceksin" notu): hata anında `data` `null`'dur, token okuması sessizce `undefined`
|
|
1927
|
-
döner. Dal bağlanınca hata onun üzerinden sürer — `always`/`condition` yalnız BAŞARIDA çalışır,
|
|
1928
|
-
yani `data.token` orada gerçek bir iş kuralıdır (uç 200 dönüp token'sız yanıt verirse), hata
|
|
1929
|
-
algılama YÖNTEMİ değil.
|
|
1930
1803
|
- **Cookie adı middleware'in okuduğu adla birebir aynı olmalı** (`cookie.APP_Token` —
|
|
1931
1804
|
`platform_guide('middleware')` Tarif 1). Uyuşmazlık sessizce "hep 401" demektir.
|
|
1932
1805
|
- `redirect` adımı `isRaw: true` iken `path` **çok satırlı JS bloğudur** (son ifade değeri döner) —
|
|
@@ -2116,14 +1989,9 @@ hiçbiri** bağlı değildi; üç portalın da rol menüsü boş çıkıyor, pan
|
|
|
2116
1989
|
> (`dto_get` ile bak: genelde `role`, `role_name`, `roles_csv` vardır). Sayfa tarafında CSV
|
|
2117
1990
|
> kullan — ayrıntı ve şablon `platform_guide('expressions')` §2.
|
|
2118
1991
|
>
|
|
2119
|
-
> **Uç hata dönerse `.data`
|
|
2120
|
-
>
|
|
2121
|
-
>
|
|
2122
|
-
> dönünce `data` **null**'dur ve bu adım boş veriyle koşar — `rows` gibi bir listeye bağlarsan
|
|
2123
|
-
> bileşen `null`'ı boş liste sayar, `Array.isArray(...) ? ... : []` sarmalamaya artık gerek yok.
|
|
2124
|
-
> Hata OLDUĞUNU fark etmeden geçmemek için `error` dalı bağlayın (yukarıdaki §"4xx de hatadır",
|
|
2125
|
-
> gateway bunu bağlı değilken **FLOW-028** ile uyarır); hata gövdesini görmek istiyorsan
|
|
2126
|
-
> `Steps.x.error.body`'yi okuyun.
|
|
1992
|
+
> **Uç hata dönerse `.data` dizi değildir.** 401/404 sonrası `Steps.x.data` bir nesnedir ve
|
|
1993
|
+
> `rows || []` bunu yakalamaz (nesne truthy) → `rows.filter is not a function` /
|
|
1994
|
+
> `(items ?? []).map is not a function`. `Array.isArray(Steps.x?.data) ? Steps.x.data : []` yaz.
|
|
2127
1995
|
|
|
2128
1996
|
## ⚠️ `page_schema_patch` `html` komponentini reddediyor — katalogda mükerrer kayıt (2026-08-19)
|
|
2129
1997
|
|
|
@@ -2186,31 +2054,6 @@ micro-op hattına dönün.
|
|
|
2186
2054
|
> uyarı yoktu. Silinmesini bilerek istiyorsanız çağrıyı `allowFlowDeletion: true` ile tekrarlayın;
|
|
2187
2055
|
> yanıt `deletedFlows` ile hangi akışların gittiğini listeler.
|
|
2188
2056
|
>
|
|
2189
|
-
> **Silinen akış geri kurulabilir (2026-09-26, ZM-27).** Sayfa kaydının sildiği akış artık revizyon
|
|
2190
|
-
> defterine `operation: delete` satırı olarak düşer (kaynağı `studio` ya da `mcp`). `flow_restore`
|
|
2191
|
-
> akışı son revizyonundaki ad, slug ve adımlarla AYNI id ile yeniden kurar; olaya bağlamaz —
|
|
2192
|
-
> geri geldikten sonra `set_event`. İki sınır: revizyon saklama süresi (budanan akış 404) ve
|
|
2193
|
-
> adımların hedeflediği komponentler — akış bir komponenti tetikleyen/parametre olarak
|
|
2194
|
-
> gösteriyorsa o komponent şemada durmalıdır (canlı ölçüldü: `flow_restore` "Trigger Element Id"
|
|
2195
|
-
> dış anahtarına çarpar).
|
|
2196
|
-
>
|
|
2197
|
-
> **Boşalan sayfa: `page_restore` (2026-09-26).** Sayfayı ve akışlarını birlikte geri kurar:
|
|
2198
|
-
> `revision_list(module: 'page', recordId: <pageId>)` → boşalmadan önceki revizyonu bul (`source` ve
|
|
2199
|
-
> `correlationId` yardım eder; `revision_get` ile içeriğine bak) → `page_restore({ revisionNo })`.
|
|
2200
|
-
> Platform önce eksik akışları adımsız kurar, sonra şemayı eski komponent id'leriyle yazar, sonra
|
|
2201
|
-
> adımları yazar — akış→komponent ve olay→akış dış anahtarları bu sırayla tek transaction'da çözülür.
|
|
2202
|
-
> Yanıt `restoredFlows` ve `deletedFlows` (N'den sonra bağlanmış, şimdi yetim kalan) döner.
|
|
2203
|
-
> Revizyonu kalmamış bir akış varsa 409 ve hiçbir şey yazılmaz.
|
|
2204
|
-
>
|
|
2205
|
-
> **Doğru revizyonu seç.** Şemayı yüklemeyen komutların (`UpdateProjectCommand`,
|
|
2206
|
-
> `UpdateApplicationCommand`…) yazdığı sayfa revizyonları komponent taşımaz; komponenti olan sayfayı
|
|
2207
|
-
> böyle bir revizyona döndürmek 409 `PageRevisionEmptyException` ile reddedilir (bilerek boşaltmak için
|
|
2208
|
-
> `allowEmpty: true`). `correlationId`'si `PatchPageSchemaCommand` ya da `UpdatePageCommand` olan
|
|
2209
|
-
> revizyonu seç. İki sınır daha: N'den beri silinen layout/rol/middleware/özel komponent ya da başka
|
|
2210
|
-
> sayfanın aldığı slug geri yüklemeyi dış anahtar/benzersizlik hatasıyla düşürür (transaction geri
|
|
2211
|
-
> alınır, veri kaybı yok); yalnız başka bir akışın adımından çağrılan (olaya bağlı olmayan) akışlar
|
|
2212
|
-
> geri kurulmaz — onlar için `flow_restore`.
|
|
2213
|
-
>
|
|
2214
2057
|
> **FLOW-018 artık silinen düğümün ALT AĞACINI da görüyor.** Eskiden yalnız op'un kendi
|
|
2215
2058
|
> `target`'ına bakılıyordu: bir kapsayıcı silinince ÇOCUĞUNA yazan setter sessizce kopuyor ve
|
|
2216
2059
|
> uyarı hiç çıkmıyordu (09-05, `sign_in_form` → `btn_sign_in`).
|
|
@@ -2254,9 +2097,6 @@ micro-op hattına dönün.
|
|
|
2254
2097
|
style + Kural 1h deseniyle yeniden kurulunca kart 400px'e ve ortaya oturdu. Gateway bunu **PAGE-014 (uyarı)** ile
|
|
2255
2098
|
yanıtın `layoutWarnings` alanında bildirir. **Düzeni `style` ile kurmaya hiç kalkışma:**
|
|
2256
2099
|
ortalama/yaslama/aralık işi kapsayıcının kendi `layout: 'flex'` prop grubuna aittir (Kural 1f-2).
|
|
2257
|
-
**İstisna `html`:** onun `style`'ı yazarın işaretlemesine kapsamlı giren CSS metnidir (web'de iç
|
|
2258
|
-
seçicili sınıf, mobilde belgenin stil bloğu) — string asıl biçimdir ve PAGE-014 onda susar. Mobilde
|
|
2259
|
-
`html`'e nesne `style` verme: çizilmez (MOB-002).
|
|
2260
2100
|
- **Menüde "bulunduğun sayfa" vurgusu: `sidebar`/`layout`'ta `activeHref`, `header`'da
|
|
2261
2101
|
`activeNavHref`.** `sidebar` ve `layout` menü ağacını ortak renderer'la çizer: `activeHref` boşken
|
|
2262
2102
|
tarayıcıdaki adrese uyan satırı kendileri vurgular, prop yazılırsa o satır vurgulanır (akıştan
|
|
@@ -98,10 +98,7 @@ theme_update({ theme: {
|
|
|
98
98
|
```
|
|
99
99
|
|
|
100
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
|
-
aynı kural geçerlidir: cihaz aynı adı Google Fonts'tan TTF olarak indirip `expo-font` ile yükler
|
|
103
|
-
(400 ve 700 kalınlık) — Android'de kalın yüz SENTETİKTİR (iOS gerçek kalın dosyayı çizer,
|
|
104
|
-
ZM-10, 2026-09-26).
|
|
101
|
+
fontu ADIYLA Google'dan çeker, tanınmayan ad sessizce sans-serif'e düşer (THEME-008).
|
|
105
102
|
|
|
106
103
|
```jsonc
|
|
107
104
|
theme_update({ theme: {
|
|
@@ -208,7 +208,7 @@ gerekmez — `schema.ts`'e dokunulmaz, katalog yeniden yüklenmez.
|
|
|
208
208
|
`translation_update` artık uygulamanın bütün sayfalarının önbellek satırlarını düşürüyor
|
|
209
209
|
(`RefreshPageCacheWhenTranslationChangedCommand`), okuma yolu cache-aside olduğu için bir
|
|
210
210
|
sonraki `page_runtime_get` taze değeri kurar. Yazmadan hemen sonra okuyabilirsin.
|
|
211
|
-
- Mobil
|
|
211
|
+
- Mobil runtime (`apps/mobile`) bu özelliği henüz beslemiyor — yalnız web.
|
|
212
212
|
|
|
213
213
|
## Backend doğrulama sınırları (TR-001)
|
|
214
214
|
|
|
@@ -373,7 +373,7 @@ gidilir, hiçbiri tutmazsa `else` dalı yürür:
|
|
|
373
373
|
|
|
374
374
|
| Step | workflow | automation | middleware |
|
|
375
375
|
|------|:-:|:-:|:-:|
|
|
376
|
-
| start, condition, code, loop, table, query, http, workflow, email, file-upload | ✓ | ✓ | ✓ |
|
|
376
|
+
| start, condition, code, loop, table, query, http, workflow, microfunction, email, file-upload | ✓ | ✓ | ✓ |
|
|
377
377
|
| variable (Set Variable), set-user, setcookie, redirect | – | – | ✓ |
|
|
378
378
|
| response | ✓ | – | ✓ |
|
|
379
379
|
| convert | ✓ | – | – |
|
|
@@ -426,13 +426,15 @@ bakar (`HttpStep.cs:32,42,59`).
|
|
|
426
426
|
| Yanıt JSON değil | Gövde **sessizce** boş nesne olur (`:92`) — XML dönen uçtan veri de hata da alamazsınız |
|
|
427
427
|
| Adım adında boşluk | Çıktıya adım adıyla erişilir; ad geçerli JS tanımlayıcısı olmalı (`call_roles`, `Call Roles` değil) |
|
|
428
428
|
|
|
429
|
-
**Çı
|
|
430
|
-
`
|
|
431
|
-
|
|
429
|
+
**Çıktının şekli (ölçüldü 2026-09-16).** Koşumda ifade bağlamındaki adım
|
|
430
|
+
`{ data, meta: { elapsedTime, httpStatusCode, totalCount }, error }` şeklindedir.
|
|
431
|
+
`workflow_step_schema('http')` `returnScheme`'i yalnız gövdeyi anlatır — adsız, tipsiz
|
|
432
|
+
(`anonymous`) tek girdi, çünkü dış yanıtın şekli bilinmez; zarf her adımda aynıdır ve şemada
|
|
433
|
+
yer almaz:
|
|
432
434
|
|
|
433
435
|
- gövde → **`<adım>.data`**
|
|
434
436
|
- durum kodu → **`<adım>.meta.httpStatusCode`**
|
|
435
|
-
- `<adım>.httpStatusCode` → **undefined**
|
|
437
|
+
- `<adım>.httpStatusCode` → **undefined**
|
|
436
438
|
|
|
437
439
|
Tam örnek ve POST varyantı: `ngapps://examples/workflow-http-step`.
|
|
438
440
|
|
|
@@ -519,6 +521,7 @@ Tek uçta "başlık + N alt kayıt" yazmanın yolu budur (anket + sorular + seç
|
|
|
519
521
|
`fields[].value` / `filters[].value` ifadelerinde `loopItem.<alan>` yazılır (ölçüldü 2026-09-16:
|
|
520
522
|
`table` çocuğunun filtresinde `loopItem.slug` → `'super-admin'`); `input` ve önceki adımlar
|
|
521
523
|
(`createSurvey.data.id`) da görünmeye devam eder.
|
|
524
|
+
- **`microfunction` çocuğunda `loopItem` argüman ifadesinde görünür** (`stepRule.expression`, loop'un motorunda değerlendirilir); fonksiyon öğeyi yalnız `args` ile alır. Ayrıntı: `platform_guide('microfunction')` §Workflow adımı → Loop içinde.
|
|
522
525
|
- **`code` çocuğunda `loopItem` YOKTUR (ölçüm 2026-09-16).** `code` adımı kendi JS motorunu kurar
|
|
523
526
|
ve `LoopStep`'in `loopItem` ataması oraya ulaşmaz: adım **`Error: loopItem is not defined`** ile
|
|
524
527
|
düşer, o yinelemenin çıktısında `result` hiç oluşmaz. Motorda görünenler `input` · `system` ·
|
|
@@ -648,15 +651,9 @@ Tam örnek, ölçülen çıktı şekli ve `code` çocuğu tuzağının çıkış
|
|
|
648
651
|
|
|
649
652
|
```js
|
|
650
653
|
// dizi (isSingle:false) · nesne (isSingle:true) · düz değer (yalnız pk dönen yazma)
|
|
651
|
-
(
|
|
654
|
+
(Array.isArray(x.data) ? (x.data[0] && x.data[0].id) : (x.data && x.data.id !== undefined ? x.data.id : x.data))
|
|
652
655
|
```
|
|
653
656
|
|
|
654
|
-
Diziyi `Array.isArray` ile değil `.length` ile tanıyın: 2026-09-27'den önceki backend'de tablo
|
|
655
|
-
adımının listesi Jint'e sarılı bir CLR nesnesi olarak iniyordu ve `Array.isArray(x.data)` `false`
|
|
656
|
-
dönüyordu — koşuda (2026-09-24) giriş akışı bu yüzden her kullanıcıyı 401 ile reddetti
|
|
657
|
-
(`zeyrek-backend/docs/incident-log.md` #89). `.length`, `.map`, `.filter` o sürümde de çalışıyordu;
|
|
658
|
-
düzeltilmiş backend'de `Array.isArray` de doğrudur.
|
|
659
|
-
|
|
660
657
|
Şekli bilmiyorsan bu yazımı kullan; `workflow_preview` çıktısında `steps[].output`'a bakarak
|
|
661
658
|
hangi vakada olduğunu da görebilirsin.
|
|
662
659
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"hash": "
|
|
3
|
-
"generatedAt": "2026-09-
|
|
2
|
+
"hash": "06f7d6b64937424fcbe7a9c8751e90a5224556e0c970199fb199cfa3a147c7d2",
|
|
3
|
+
"generatedAt": "2026-09-28T09:04:34.182Z",
|
|
4
4
|
"types": 186,
|
|
5
5
|
"files": 108,
|
|
6
6
|
"note": "Şemaları üreten backend kaynaklarının parmak izi. Elle düzenlemeyin: 'npm run generate-schemas' yazar, 'npm run schema:check' denetler.",
|
|
@@ -134,6 +134,9 @@
|
|
|
134
134
|
},
|
|
135
135
|
"nullable": true
|
|
136
136
|
},
|
|
137
|
+
"returnBehavior": {
|
|
138
|
+
"$ref": "#/components/schemas/NgApps.Domain.Contexts.Shared.DataTransferObjects.DataTransferObjectBehavior"
|
|
139
|
+
},
|
|
137
140
|
"relationTree": {
|
|
138
141
|
"$ref": "#/components/schemas/NgApps.Domain.Contexts.Datastore.Entities.EntityRelationDto"
|
|
139
142
|
}
|
|
@@ -128,6 +128,9 @@
|
|
|
128
128
|
},
|
|
129
129
|
"nullable": true
|
|
130
130
|
},
|
|
131
|
+
"returnBehavior": {
|
|
132
|
+
"$ref": "#/components/schemas/NgApps.Domain.Contexts.Shared.DataTransferObjects.DataTransferObjectBehavior"
|
|
133
|
+
},
|
|
131
134
|
"relationTree": {
|
|
132
135
|
"$ref": "#/components/schemas/NgApps.Domain.Contexts.Datastore.Entities.EntityRelationDto"
|
|
133
136
|
}
|
|
@@ -45,6 +45,9 @@
|
|
|
45
45
|
},
|
|
46
46
|
"nullable": true
|
|
47
47
|
},
|
|
48
|
+
"returnBehavior": {
|
|
49
|
+
"$ref": "#/components/schemas/NgApps.Domain.Contexts.Shared.DataTransferObjects.DataTransferObjectBehavior"
|
|
50
|
+
},
|
|
48
51
|
"relationTree": {
|
|
49
52
|
"$ref": "#/components/schemas/NgApps.Domain.Contexts.Datastore.Entities.EntityRelationDto"
|
|
50
53
|
}
|
|
@@ -413,6 +416,15 @@
|
|
|
413
416
|
},
|
|
414
417
|
"additionalProperties": false
|
|
415
418
|
},
|
|
419
|
+
"NgApps.Domain.Contexts.Shared.DataTransferObjects.DataTransferObjectBehavior": {
|
|
420
|
+
"enum": [
|
|
421
|
+
"primitive",
|
|
422
|
+
"object",
|
|
423
|
+
"array"
|
|
424
|
+
],
|
|
425
|
+
"type": "string",
|
|
426
|
+
"format": ""
|
|
427
|
+
},
|
|
416
428
|
"NgApps.Domain.Contexts.Datastore.Entities.EntityRelationDto": {
|
|
417
429
|
"type": "object",
|
|
418
430
|
"properties": {
|
|
@@ -804,15 +816,6 @@
|
|
|
804
816
|
"type": "string",
|
|
805
817
|
"format": ""
|
|
806
818
|
},
|
|
807
|
-
"NgApps.Domain.Contexts.Shared.DataTransferObjects.DataTransferObjectBehavior": {
|
|
808
|
-
"enum": [
|
|
809
|
-
"primitive",
|
|
810
|
-
"object",
|
|
811
|
-
"array"
|
|
812
|
-
],
|
|
813
|
-
"type": "string",
|
|
814
|
-
"format": ""
|
|
815
|
-
},
|
|
816
819
|
"NgApps.Domain.Contexts.Datastore.Entities.EntityType": {
|
|
817
820
|
"enum": [
|
|
818
821
|
"normal",
|
|
@@ -134,6 +134,9 @@
|
|
|
134
134
|
},
|
|
135
135
|
"nullable": true
|
|
136
136
|
},
|
|
137
|
+
"returnBehavior": {
|
|
138
|
+
"$ref": "#/components/schemas/NgApps.Domain.Contexts.Shared.DataTransferObjects.DataTransferObjectBehavior"
|
|
139
|
+
},
|
|
137
140
|
"relationTree": {
|
|
138
141
|
"$ref": "#/components/schemas/NgApps.Domain.Contexts.Datastore.Entities.EntityRelationDto"
|
|
139
142
|
}
|