@appaflytech/zeyrek-ai-mcp 0.0.45 → 0.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/knowledge/mobileComponentCatalog.js +1 -1
- package/dist/knowledge/platform/lint.js +23 -0
- package/dist/knowledge/platform/mobileOffline.js +45 -0
- package/dist/knowledge/platform/mobileRules.js +6 -0
- package/dist/knowledge/rules.js +25 -3
- package/dist/resources/examples/mobile-offline-list.json +357 -0
- package/dist/resources/examples/mobile-offline-queue.json +82 -0
- package/dist/resources/examples/mobile-offline-seamless.json +1520 -0
- package/dist/resources/guides/access.md +1 -1
- package/dist/resources/guides/expressions.md +1 -1
- package/dist/resources/guides/mobile-steps.md +4 -1
- package/dist/resources/guides/mobile.md +4 -0
- package/dist/resources/guides/page.md +111 -0
- package/dist/resources/guides/translation.md +2 -2
- package/dist/resources/schema-fingerprint.json +2 -2
- package/dist/resources/schemas/CreateMicroserviceCommand.json +3 -0
- package/dist/resources/schemas/MicroserviceDto.json +3 -0
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +3 -0
- package/dist/tools/accessRuntime.js +1 -1
- package/dist/tools/applications.js +16 -2
- package/dist/tools/flows.js +89 -4
- package/package.json +2 -2
|
@@ -374,7 +374,7 @@ Kompleks projede kimliği platform yönetir; uygulamanın kendi kimlik middlewar
|
|
|
374
374
|
| `POST …/auth/refresh` | yenileme çerezi (ya da gövdede `refreshToken`) → yeni jetonlar; eski yenileme jetonu tekrar gelirse bütün aile iptal, 401 |
|
|
375
375
|
| `POST …/auth/sign-out` | çerezleri siler |
|
|
376
376
|
| `GET …/auth/me` | kullanıcı, roller, pozisyonlar, birimler, şirketler |
|
|
377
|
-
| `GET /{proje}/runtime/{app}/access` | izin özeti: `mode`, izinli sayfa ve uç slug'ları, entity başına eylemler ve alan düzeyleri (arayüzde gizleme için; `enforce` dışında her şey açık döner) |
|
|
377
|
+
| `GET /{proje}/runtime/{app}/access` | izin özeti: `mode`, izinli sayfa ve uç slug'ları, entity başına eylemler ve alan düzeyleri (arayüzde gizleme için; `enforce` dışında her şey açık döner — basit projede `off` ve listeler boş, kompleks projede `off`/`shadow` her şeyi listeler). **Runtime basit projede bu ucu çağırmaz:** tür sayfa yanıtının `project.accessModel`'inde ve `uiActions` yanıtının `accessModel`'inde gelir; özet istemcide kurulur (ADR 0021) |
|
|
378
378
|
|
|
379
379
|
- Jeton önce çerezden, yoksa `Authorization: Bearer`'dan okunur. Çerezle gelen **durum değiştiren**
|
|
380
380
|
istek `X-ZY-CSRF` başlığında `ZY_Csrf_{proje}` değerini ister (yoksa `403 CsrfTokenMismatch`);
|
|
@@ -111,7 +111,7 @@ dalından devam eder.
|
|
|
111
111
|
| `setComponentProperty(name, key, value)` / `getComponentProperty(name, key)` | fonksiyon alternatifi |
|
|
112
112
|
| `resetForm(name)` | Formu sıfırlar: alanlar başlangıç değerine döner, form "gönderilmemiş" olur, doğrulama mesajları silinir. Kayıt sonrası "yeni kayıt" için alanları tek tek `null`'a çekme — gönderilmiş formda her biri "zorunlu alan" mesajı çıkarır. Ad ya da komponent değişkeni alır: `resetForm('risk_form')` / `resetForm(risk_form)`. **Yalnız UI flow kodunda** |
|
|
113
113
|
| `LocalStorage` · `Widget` · `params` | yerel veri · widget bağlamı · olay parametreleri. `LocalStorage` barındırıcının deposudur, salt okunur ve değerler METİNdir: web'de uygulamanın kökenindeki `localStorage` (Studio önizlemesinde Studio'nun kendi anahtarları da görünür), cihazda akışın `storage` deposu. `storage` adımı düz bir anahtara yazınca `LocalStorage.<anahtar>` aynı akışta yeni değeri verir ve sayfanın bağları yeniden değerlendirilir (`isSelected: {{ LocalStorage['zeyrek:theme-mode'] === 'dark' }}`). `state.page\|app.<key>`'e yazan adım `LocalStorage`'a girmez (ARC-147, 2026-09-29) |
|
|
114
|
-
| `Device` | Salt okunur cihaz durumu, barındırıcı günceller: `Device.isOnline` — ağ bağlantısı var mı (bilinmiyorsa `true`). Değişince sayfanın bütün bağları yeniden değerlendirilir; çevrimdışı bandı: `isHidden: {{ Device.isOnline }}`. Cihazda `expo-network`, web'de tarayıcının `online`/`offline` olayları. `Device.biometric = { available, enrolled, kinds }` (kök ADR 0021): `available` cihaz kullanıcıyı şu an doğrulayabilir (biyometri **ya da** cihaz parolası kurulu), `enrolled` biyometri kayıtlı, `kinds` ⊆ `face · fingerprint · iris`; barındırıcı vermezse (web, derleme taşımıyor) `{ available: false, enrolled: false, kinds: [] }`, Studio önizlemesi ve kanvas senaryosu `{ true, true, ['face'] }`. Uygulama ön plana dönünce yeniden okunur. `Device` adında komponent ifade bağlamından süzülür (ayrılmış ad) |
|
|
114
|
+
| `Device` | Salt okunur cihaz durumu, barındırıcı günceller: `Device.isOnline` — ağ bağlantısı var mı (bilinmiyorsa `true`). Değişince sayfanın bütün bağları yeniden değerlendirilir; çevrimdışı bandı: `isHidden: {{ Device.isOnline }}`. Cihazda `expo-network`, web'de tarayıcının `online`/`offline` olayları. `Device.biometric = { available, enrolled, kinds }` (kök ADR 0021): `available` cihaz kullanıcıyı şu an doğrulayabilir (biyometri **ya da** cihaz parolası kurulu), `enrolled` biyometri kayıtlı, `kinds` ⊆ `face · fingerprint · iris`; barındırıcı vermezse (web, derleme taşımıyor) `{ available: false, enrolled: false, kinds: [] }`, Studio önizlemesi ve kanvas senaryosu `{ true, true, ['face'] }`. Uygulama ön plana dönünce yeniden okunur. Ağ yokken okumaların ne döndüğü (`Steps.<ad>.cache.at`, `error.network`): `platform_guide('page')` §Kural 1g-4. `Device.offline` (yalnız cihazda): `{ ready, total }` — uygulamanın kaç ekranı çevrimdışı açılmaya hazır; paket inmeden ve web/önizlemede yoktur (`Device.offline?.ready`); servis yazması kuyruğu varsa `queue: { pending, rejected }` ve `rejected` (reddedilen kayıtlar) da buradadır. `Device` adında komponent ifade bağlamından süzülür (ayrılmış ad) |
|
|
115
115
|
| **Ayrılmış adlar** | Bu tablodaki globallerle (ve önsözün iç adlarıyla: `payload`, `error`, `repeaterId`, `_` ile başlayanlar…) aynı `name`'i taşıyan komponent (runtime yalnız İLK `-`'yi siler: `ite-m` da `item` sayılır) ifadede kendi adıyla GÖRÜNMEZ — süzülür, uyarı loglanır (liste: `@ng-apps/flow` `EXPRESSION_PRELUDE_NAMES`). Eskiden aynı ad sayfanın BÜTÜN ifadelerini `SyntaxError`'la düşürürdü (ARC-143). Gateway artık bu adların HEPSİNİ **PAGE-009** ile sayfa/layout yazma yollarında ve `page_schema_validate`'te istek gitmeden reddeder — komponente `t`, `state`, `event`, `item`, `self`, `Page`, `Row` gibi ad verme |
|
|
116
116
|
| `t(key)` | Çeviri anahtarını çözer: aktif dil → projenin varsayılan dili → anahtarın kendisi. Boş string de "eksik" sayılır. Sözlük `machine.context.state.translations`'tan gelir; dil `language-selector` ile değişince bir sonraki çağrı yeni dili görür. **Yalnız UI flow kodunda vardır** — backend ifadelerinde karşılığı `Loc()`'tur (`platform_guide('workflow')`) | `t('home.welcome')` |
|
|
117
117
|
| `log(...)` | console (proxy'leri temizler) |
|
|
@@ -36,7 +36,10 @@ Motorun kendi adımları (`setter`, `condition`, `microservice`, `code`, `functi
|
|
|
36
36
|
Bildirim adımları paletten yalnız mobil uygulamada sunulur. Tarif — S04 "her gün hatırlat": önce
|
|
37
37
|
`notification-permission` (S03 düğmesi), sonra `timepicker`'ın değeriyle `notification-schedule`
|
|
38
38
|
(`value: "<saat>.value"`, değer `HH:mm`) ve `error` dalında kullanıcıya mesaj. Çevrimdışı bandı adım değil
|
|
39
|
-
ifadedir: `isHidden: {{ Device.isOnline }}` (`platform_guide('expressions')`)
|
|
39
|
+
ifadedir: `isHidden: {{ Device.isOnline }}` (`platform_guide('expressions')`) — ağı CANLI izler, ekran açıkken bağlantı
|
|
40
|
+
gidince çıkar. Kabuğun kendi bandı ayrıdır: yalnız sayfa isteği (açılış ya da yenileme) düşünce çıkar — ağ yoksa
|
|
41
|
+
"Çevrimdışı · son güncelleme …", sunucu 5xx dönerse "Yenilenemedi". İkisi aynı anda görünebilir; sayfa bandını
|
|
42
|
+
ekranın tepesine değil, anlattığı verinin yanına koyun (`platform_guide('page')` §Kural 1g-4).
|
|
40
43
|
|
|
41
44
|
## İzin tarifi
|
|
42
45
|
|
|
@@ -562,3 +562,7 @@ yaptıkları. Derlenen uygulama
|
|
|
562
562
|
Web'in `theme-toggle`'ı mobilde yoktur. Seçili düğme saklanan seçimi `LocalStorage`'dan okur:
|
|
563
563
|
`{{ LocalStorage['zeyrek:theme-mode'] || 'light' }}` (ARC-147).
|
|
564
564
|
- Dar ekran kırılımı (`hideOn: 'mobile'`) mobil uygulamada anlamsızdır: ekran zaten tek boydur.
|
|
565
|
+
- Ağ yokken ekranlar ve (açıksa) son okunan veri cihazdaki kopyadan gelir: `properties.mobile.offline`
|
|
566
|
+
(MOB-033), `Steps.<ad>.cache.at`, `error.network` — `platform_guide('page')` §Kural 1g-4. Önizleme önbellek kullanmaz.
|
|
567
|
+
"Uygulama ağsızken de çalışsın" isteğinin tarifi (okuma GET, yazma kuyruğu, liste birleştirme, düğme kilidi, korumasız
|
|
568
|
+
açılış, bant kapalı): §Kural 1g-4 "Ağsızken fark göstermeyen uygulama", örnek `ngapps://examples/mobile-offline-seamless`.
|
|
@@ -443,6 +443,8 @@ göstermek error flow'un işidir.
|
|
|
443
443
|
> | `Steps.<adımAdı>.error.message` | Patlayan adımın KENDİ storage'ında ucun mesajı — `error` dalında da `always`'te de okunur, sıra aynı: `err.reason` → HTTP durum metni → `'Service request failed'` | `microservice.ts` `.catch` |
|
|
444
444
|
> | `Steps.<adımAdı>.error.status` | HTTP durum KODU (sayı) — parametre ifadesi patladıysa `null` | `microservice.ts` `.catch` |
|
|
445
445
|
> | `Steps.<adımAdı>.error.body` | Ucun hata gövdesi — eski `Steps.<adımAdı>.data`'nın taşındığı yer | `microservice.ts` `.catch` |
|
|
446
|
+
> | `Steps.<adımAdı>.error.network` | **Yalnız mobil, veri önbelleği açıkken:** yanıt hiç alınamadı (bağlantı yok; süre sınırı yalnız saklanan okumalarda, 8 sn) — `true`; `status` yine 503. Önbellek kapalıyken ve web'de alan yoktur (Kural 1g-4) | `microservice.ts` `.catch` |
|
|
447
|
+
> | `Steps.<adımAdı>.cache.at` | Hata değil, BAŞARI şekli: yanıt cihazdaki kayıttan geldi, `at` saklandığı an (ms). Ağdan gelen yanıtta `cache` yoktur (Kural 1g-4) | `microservice.ts` `.then` |
|
|
446
448
|
> | `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` |
|
|
447
449
|
>
|
|
448
450
|
> **`alert` adımının `message`'ı ve `description`'ı METİN ŞABLONUDUR — yalnız `{{ }}` içi çözülür.**
|
|
@@ -1507,6 +1509,115 @@ Liste → ayrıntı, üç adım:
|
|
|
1507
1509
|
|
|
1508
1510
|
Web uygulamasında alan yoktur.
|
|
1509
1511
|
|
|
1512
|
+
## Kural 1g-4 — Mobil çevrimdışı: ayar, önbellek işareti, ağ hatası
|
|
1513
|
+
|
|
1514
|
+
Mobil uygulama ağ yokken iki şeyi cihazdaki kopyadan açar. Hangisinin açık olduğu uygulamanın ayarıdır:
|
|
1515
|
+
`application_update` `properties.mobile.offline` (`properties.mobile.tabs`'in yanındaki anahtar). Gövde REPLACE'tir:
|
|
1516
|
+
`application_get`'teki `properties`'in TAMAMI aynen gönderilir, yalnız `offline` eklenir — eksik anahtar silinir. Studio'da Nav Bar panelinin "Çevrimdışı" bölümü aynı alanı yazar.
|
|
1517
|
+
|
|
1518
|
+
| Alan | Değer | Varsayılan | Ne saklanır |
|
|
1519
|
+
|---|---|---|---|
|
|
1520
|
+
| `screens` | boolean | `true` | Ekran tanımları: açılan ekranların kopyası + uygulama paketi (korumasız ekranların gövdesi hiç açılmadan iner, korumalı ekranlar oturumluya ön yüklenir). Ağ yokken ekran kopyadan çizilir; sayfa isteği düşünce kabuk üstte "Çevrimdışı · son güncelleme …" bandını kendisi gösterir. Hazırlık: `Device.offline` |
|
|
1521
|
+
| `data` | boolean | `false` | Son okunan veri: `isRaw: false` YAZILMIŞ GET `microservice` adımı ve connectData okumaları (`list`, `describe`, `lookup`). `isRaw` yazılmamış ya da `true` olan adım ve dosya/akış sonucu dönen servis saklanmaz |
|
|
1522
|
+
| `maxAgeDays` | `1` · `7` · `30` | `7` | İkisinin de kayıt ömrü |
|
|
1523
|
+
| `banner` | boolean | `true` | Kabuğun çevrimdışı bandı ("Çevrimdışı · son güncelleme", "Yenilenemedi"). `false`: uygulama ağsızken fark göstermez — kendi uyarılarını da kaldırmak yazarın işidir (kök ADR 0026). Saklama ve kuyruk değişmez |
|
|
1524
|
+
|
|
1525
|
+
Yalnız varsayılandan ayrılan alanı yazın (`{ data: true }` yeter). Backend alanı doğrulamaz; cihaz okuyamadığı değeri
|
|
1526
|
+
(nesne olmayan ayar, boolean olmayan `screens`/`data`/`banner`, kümede olmayan ya da metin `maxAgeDays`, tanınmayan anahtar)
|
|
1527
|
+
SESSİZCE varsayılana düşürür — bunu söyleyen tek yer `application_create` / `application_update` yanıtındaki
|
|
1528
|
+
`platformWarnings`'tir (**MOB-033**).
|
|
1529
|
+
|
|
1530
|
+
**Saklanmayan:** yazma servisleri (POST/PUT/DELETE) ve connectData yazmaları — önbellekten yanıt almazlar.
|
|
1531
|
+
Kayıtlar kullanıcıya, ortama ve veri diline bağlıdır; çıkışta ve kullanıcı değişince silinir.
|
|
1532
|
+
|
|
1533
|
+
**Yazma kuyruğu (kök ADR 0022) — iki taraf da izin vermeli:**
|
|
1534
|
+
|
|
1535
|
+
- **Servis:** tanımında `offlineWritable: true` (`microservice_patch` `/offlineWritable`). Anlamı: "aynı istek iki kez
|
|
1536
|
+
gelirse bir kez uygulanır, çakışmada son yazan kazanır". Platform yazmayı sınıflamaz — iş akışı kaynaklı servisin
|
|
1537
|
+
yazıp yazmadığını bildirimi veren söyler. Okuyan uca (tablo `get`/`count`, görünüm kaynağı) verilirse **MS-025** uyarır.
|
|
1538
|
+
- **Akış:** `microservice` adımına `queued` dalı (yalnız mobil). Ağ hatasında (yanıt hiç yok) dal bağlıysa, yöntem
|
|
1539
|
+
yazansa (POST/PUT/DELETE) ve dosya parametresi yoksa kayıt kuyruğa girer ve `queued` koşar; `Steps.<ad>.data` `null`,
|
|
1540
|
+
`Steps.<ad>.queued = { clientRequestId, at }`. Dal bağlı değilse adım bugünkü gibi `error`'a gider; dosya
|
|
1541
|
+
parametresinde `Steps.<ad>.error.code = 'fileNotQueued'`. HTTP hatası — önündeki vekil sunucunun 502/503'ü dahil —
|
|
1542
|
+
kuyruğa girmez. Web uygulamasında ya da bildirimsiz servise bağlanan `queued` için yazım **FLOW-043** uyarısı alır.
|
|
1543
|
+
- **Sunucu karar verir:** cihaz servisin bildirimini bilmez. `queued` dalı bağlı yazmanın İLK isteği de
|
|
1544
|
+
`Idempotency-Key` taşır ve kuyruğa aynı kimlikle girer; aynı anahtar bir kez uygulanır, ikincisi 200
|
|
1545
|
+
`{ code: "Duplicate" }` alır — yanıtı yolda kaybolan yazma iki kez uygulanmaz. Bildirimsiz servis anahtarlı isteği
|
|
1546
|
+
422 `OfflineReplayNotAllowedException` ile reddeder: `queued` bağlı adım çevrimiçiyken de HER ÇAĞRIDA `error`'a gider.
|
|
1547
|
+
FLOW-043 uyarısını bu yüzden geçiştirmeyin.
|
|
1548
|
+
- **Sınır:** kuyruktaki kayda bağlı ikinci işlem (yarat → sonra güncelle) yoktur; dönen kimliği bekleyen adım
|
|
1549
|
+
(`Steps.<ad>.data.id` ile yönlendirme, bildirim kurma) çevrimdışıyken koşamaz — o akışa `queued` dalı vermeyin.
|
|
1550
|
+
- **Gönderim:** bağlantı dönünce, uygulama ön plana dönünce ve ağla soğuk açılışta; kuyruğa giriş sırasıyla tek tek.
|
|
1551
|
+
4xx kaydı reddeder ve sıra sürer; oturum (401/403), 408, 429, 5xx ve ağ hatası sırayı durdurur. 7 günde
|
|
1552
|
+
gönderilemeyen kayıt `expired` ile reddedilir. Kayıtlar kullanıcıya bağlıdır, çıkışta silinmez. Ağ açık ama
|
|
1553
|
+
sunucu ulaşılmazken bağlantı dönüşü tetiği gelmez — beklemesini istemediğiniz akışta `Page.offline.sync()` çağırın.
|
|
1554
|
+
- **Görünürlük:** kaydın sonucu akışa dönmez. `Device.offline.queue = { pending, rejected }` ve
|
|
1555
|
+
`Device.offline.rejected` (`id`, `service`, `at`, `status`, `code`, `message`); kod adımında `Page.offline.list()`,
|
|
1556
|
+
`.count()`, `.sync()`, `.resolve(id, 'retry' | 'discard')`. Süresi dolan kayıt yeniden denenmez.
|
|
1557
|
+
- **Önizleme:** Studio ve web'de kuyruk yoktur, `queued` hiç koşmaz; `page_screenshot` ağı kesemez. Açık ekran ilk
|
|
1558
|
+
çizildiği kopyayla kalır — akışa eklenen dal ekran bir sonraki açılışta etkindir.
|
|
1559
|
+
|
|
1560
|
+
Örnek: `ngapps://examples/mobile-offline-queue` (doz işaretleme: servis bildirimi + `queued` dalı).
|
|
1561
|
+
|
|
1562
|
+
**Veri önbelleği açıkken akış ne görür:**
|
|
1563
|
+
|
|
1564
|
+
- Saklanan okuma 8 sn süre sınırı taşır; yanıt gelirse olduğu gibi döner ve arkada saklanır. Saklanmayan isteklerde
|
|
1565
|
+
(yazmalar dahil) süre sınırı YOKTUR: yanıt vermeyen sunucuda adım bekler.
|
|
1566
|
+
- Yanıt gelmezse (bağlantı yok, süre doldu) ve kayıt varsa adım **başarı yolundan** sürer; storage'ı
|
|
1567
|
+
`{ data, headers, error: null, cache: { at } }` olur — `at` kaydın saklandığı an (ms). Ağdan gelen yanıtta `cache`
|
|
1568
|
+
alanı YOKTUR: "son güncelleme" satırını `Steps.<ad>.cache`'ten kurun, ağ varken gizli kalır.
|
|
1569
|
+
- Kayıt da yoksa adım hata yoluna gider: `Steps.<ad>.error.network` `true`, `status` 503. "Bağlantı yok" demek için
|
|
1570
|
+
**önce `error.network`'e bakın** — 503'ü sunucu da döner (bakım, aşırı yük); sunucu arızası
|
|
1571
|
+
`status == 503 && !error.network`'tür. Akış 503'ü `network`'süz karşılaştırıyorsa yazım **MOB-033** bilgi notu alır.
|
|
1572
|
+
Bağlantı yoksa `network` her istekte yazılır (saklanmayanlarda da); önbellek kapalıyken hiç yazılmaz.
|
|
1573
|
+
- connectData bağı kayıttan dolarsa düğüme `cachedAt` yazar (`{{ <öğe>.cachedAt }}`; ağdan gelince `null`), yükleme ve
|
|
1574
|
+
hata görünümü çıkmaz; bağlantı dönünce bağ sunucudan yeniden okunur. Kayıttan dönen `lookup` sonucu `cachedAt` taşır.
|
|
1575
|
+
- **Önbellek son başarılı yanıtı aynen verir.** Her çağrıda değişen bir GET (sayaç, saat, rastgele değer) ağ yokken
|
|
1576
|
+
eski değerini döner. Parametre, sayfa, arama ve süzgeç isteğin parçasıdır: başka parametreli çağrı başka kayıttır,
|
|
1577
|
+
hiç açılmamış sayfa ağ yokken gelmez.
|
|
1578
|
+
|
|
1579
|
+
**Doğrulama sınırı:** önizleme (`/dev`, Studio kanvası) ve `page_screenshot` önbellek KULLANMAZ — ayar açık olsa da her
|
|
1580
|
+
okuma ağdan gider, `cache` ve `cachedAt` hiç yazılmaz. `page_screenshot` ağı kesemez; çevrimdışı davranış yalnız
|
|
1581
|
+
cihazda görülür (uçak modu). Ölçüldü 2026-10-20 (simülatör, mağaza kabuğu): GET servis okuması ağ varken 149 ms'de
|
|
1582
|
+
ağdan, sunucu yanıt vermezken 8,03 sn'de kesilip kayıttan döndü.
|
|
1583
|
+
|
|
1584
|
+
Örnek: `ngapps://examples/mobile-offline-list` (liste + "son güncelleme" satırı + bağlantı yok uyarısı). Web
|
|
1585
|
+
uygulamasında alan yoktur; gateway web profilinde bu konuda bulgu üretmez.
|
|
1586
|
+
|
|
1587
|
+
### Ağsızken fark göstermeyen uygulama (tarif)
|
|
1588
|
+
|
|
1589
|
+
Kullanıcı "uygulama internet yokken de normal çalışsın" dediğinde hedef: ağsızken ekran, uyarılar ve akış çevrimiçiyle
|
|
1590
|
+
AYNI; veri bağlantı gelince Zeyrek'e kendiliğinden gider. Altı adım birlikte kurulur — biri eksikse fark görünür
|
|
1591
|
+
(iPhone'da uçak kipiyle ölçüldü 2026-10-22, `mobile-offline-seamless` örneğinin kaynağı):
|
|
1592
|
+
|
|
1593
|
+
1. **Ayar:** `properties.mobile.offline = { data: true, banner: false }` — veri önbelleği açık, kabuğun
|
|
1594
|
+
"Çevrimdışı · son güncelleme" bandı kapalı (kök ADR 0026).
|
|
1595
|
+
2. **Okuma GET:** okuyan uç `httpMethod: 'get'`, adım `isRaw: false`; uç filtreleri ve adım parametreleri
|
|
1596
|
+
`source: 'query-string'` (GET'te gövde gitmez). Önbellek yalnız GET okumayı saklar; POST ile okuyan adım ağsızken
|
|
1597
|
+
kayıttan dönemez ve hata yoluna düşer — **FLOW-044** uyarır (yöntem servis tanımındandır, adıma yazılan saklanmaz).
|
|
1598
|
+
(Ölçüm: POST okuyan bir uygulamanın listesi ağsızken "yüklenemedi" dedi.)
|
|
1599
|
+
3. **Yazma kuyruğu, uyarısız:** yazan uç `offlineWritable: true`; `microservice` adımının `queued` dalı `always` ile
|
|
1600
|
+
**aynı adıma** bağlanır — ağsız yazma da çevrimiçi gibi biter. Adımın `error` dalı çevrimiçi reddi uyarır; kuyruktaki
|
|
1601
|
+
kayıt sonradan reddedilirse (4xx, 7 günde `expired`) bu akışa DÖNMEZ — `Device.offline.rejected` ile gösterin,
|
|
1602
|
+
`Page.offline.resolve(id, 'retry' | 'discard')` ile karar verdirin; göstermemek bilinçli bir ödünleşimdir.
|
|
1603
|
+
4. **Liste bekleyenleri gösterir:** yükleme akışı sunucunun yanıtına `await Page.offline.list()`'teki
|
|
1604
|
+
`status === 'pending'` kayıtları katar (`service` yazma ucunun slug'ı, alan değeri `parameters[].value`'dan); ağ
|
|
1605
|
+
yokluğu hata metni göstermez (`Steps.<ad>.error && !Steps.<ad>.error.network`).
|
|
1606
|
+
5. **Düğme kilidi:** yazan düğme istek süresince `isLoading` + `isDisabled`; her dalın sonunda açılır. Kilitsiz düğmede
|
|
1607
|
+
hızlı ikinci dokunuş yeni bir istek ve yeni bir `Idempotency-Key`'dir — sunucu ikisini de uygular (ölçüm: 1,6 sn'de
|
|
1608
|
+
üç dokunuş, üç kayıt).
|
|
1609
|
+
6. **Açılış ve yenileme (geçici çareler):** açılış sayfası korumasız giriş ekranıdır; kalıcı `state.app` oturum işareti
|
|
1610
|
+
(`storage: 'device'`) varsa mount akışı listeye `presentation: 'replace'` ile geçer, giriş yazar, çıkış siler —
|
|
1611
|
+
korumalı açılış sayfası ağsız ilk açılışta çizilemiyor (kök ADR 0024 taslak) ve cihazda kabuk bilgisi yokken
|
|
1612
|
+
middleware'in reddi girişe yönlenmiyor (zeyrek-frontend `docs/issues.md` ARC-342). Liste `scroll-view` `refreshable` +
|
|
1613
|
+
`refresh` olayı yükleme akışına bağlıdır — bağlantı dönünce açık ekranın mount akışı kendiliğinden koşmaz (kök ADR
|
|
1614
|
+
0025 taslak). İki karar kapanınca bu adım sadeleşir.
|
|
1615
|
+
|
|
1616
|
+
Fark yalnız üç yerde kalır: giriş (ağ ister), hiç açılmamış ekran (cihazda kopyası yok) ve bağlantı dönünce gönderilen
|
|
1617
|
+
kayıt — artık bekleyen değildir, önbellekteki eski listede de yoktur; liste aşağı çekilene kadar görünmez (ADR 0025). Önizleme ve
|
|
1618
|
+
`page_screenshot` önbellek ve kuyruk kullanmaz — davranış yalnız cihazda görülür. Tam gövde (iki ekran, beş akış, iki
|
|
1619
|
+
uç, ayar ve değişken): `ngapps://examples/mobile-offline-seamless`.
|
|
1620
|
+
|
|
1510
1621
|
## Kural 1h — Tasarım: `style` prop'u ve tema değişkenleri
|
|
1511
1622
|
|
|
1512
1623
|
Her komponentin `style` prop'u vardır ve emotion `css()` bloğudur: iç seçiciler, pseudo-class'lar
|
|
@@ -351,8 +351,8 @@ yazılır ama yanıt `applicationMismatch: true` ve not taşır.
|
|
|
351
351
|
`project_update` gerekmez; ama dil production'a da gider ve orada çeviriler deployment'la gelene
|
|
352
352
|
kadar runtime varsayılan dile düşer.
|
|
353
353
|
- Dosya platformda **saklanmaz**: ne dışa aktarma ne içe aktarma Sürücü'ye bir şey bırakır.
|
|
354
|
-
- Studio'nun çeviri panelindeki
|
|
355
|
-
|
|
354
|
+
- Studio'nun çeviri panelindeki "Excel'e aktar" / "Excel'den içe aktar" düğmeleri (2026-10-21) aynı
|
|
355
|
+
uçları kullanır; panelin eski JSON içe / dışa aktarması kaldırıldı.
|
|
356
356
|
- Sınırlar: `.xlsx` (`.xls`, csv, json reddedilir), 10 MB, 10.000 satır.
|
|
357
357
|
|
|
358
358
|
## Bilinen sınırlar
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"hash": "
|
|
3
|
-
"generatedAt": "2026-10-
|
|
2
|
+
"hash": "5e308466bfb365d77db8b3c0e40b90d21112d560b2b6eb23053200233734e904",
|
|
3
|
+
"generatedAt": "2026-10-22T18:49:12.637Z",
|
|
4
4
|
"types": 348,
|
|
5
5
|
"files": 173,
|
|
6
6
|
"note": "Şemaları üreten backend kaynaklarının parmak izi. Elle düzenlemeyin: 'npm run generate-schemas' yazar, 'npm run schema:check' denetler.",
|
|
@@ -147,7 +147,7 @@ export function registerAccessRuntimeTools(server, platform) {
|
|
|
147
147
|
entities: Array.isArray(data.entities) ? data.entities.length : 0
|
|
148
148
|
},
|
|
149
149
|
note: data.mode === 'off'
|
|
150
|
-
? "Zorlama KAPALI:
|
|
150
|
+
? "Zorlama KAPALI: karar motoru çalışmıyor, her şey açıktır. Kompleks projede listeler her şeyi sayar; basit projede listeler BOŞ döner (basit proje hep off'tur, kapsam için önce kompleks'e dönüşüm gerekir — access_model_preflight). Kompleks projede gerçek kapsamı görmek için environment'ı shadow/enforce'a alın (access_enforcement_mode_set)."
|
|
151
151
|
: "Harita bu kullanıcının o andaki yetkisidir; bir öğe eksikse nedenini access_preview söyler."
|
|
152
152
|
};
|
|
153
153
|
}));
|
|
@@ -3,6 +3,7 @@ import { handle } from '../platform/responses.js';
|
|
|
3
3
|
import { forgetApplication, readApplicationPlatform, resolveApplication } from '../knowledge/platform/resolve.js';
|
|
4
4
|
import { mobileTabsProblems, readMobileTabs } from '../knowledge/platform/mobileTabs.js';
|
|
5
5
|
import { mobileTransitionProblems } from '../knowledge/platform/pageTransition.js';
|
|
6
|
+
import { mobileOfflineProblems } from '../knowledge/platform/mobileOffline.js';
|
|
6
7
|
import { findingLine } from '../knowledge/platform/profile.js';
|
|
7
8
|
import { listComponents } from './components.js';
|
|
8
9
|
import { z } from 'zod';
|
|
@@ -51,6 +52,19 @@ export function mobileTransitionWarnings(properties) {
|
|
|
51
52
|
guide: "platform_guide('page') §Kural 1g-2"
|
|
52
53
|
}));
|
|
53
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* MOB-033 (çevrimdışı ayarı) — `properties.mobile.offline` yazan mobil uygulama çağrısının denetimi. Yazım platforma
|
|
57
|
+
* YİNE gider (backend `properties`'i doğrulamaz); cihaz okuyamadığı değeri sessizce varsayılana düşürdüğü için bulgunun
|
|
58
|
+
* söylendiği tek yer `platformWarnings`'tir.
|
|
59
|
+
*/
|
|
60
|
+
export function mobileOfflineWarnings(properties) {
|
|
61
|
+
return mobileOfflineProblems(properties).map(message => findingLine({
|
|
62
|
+
code: 'MOB-033',
|
|
63
|
+
severity: 'warn',
|
|
64
|
+
message,
|
|
65
|
+
guide: "platform_guide('page') §Kural 1g-4"
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
54
68
|
function withPlatformWarnings(response, warnings) {
|
|
55
69
|
if (warnings.length === 0 || !response || typeof response !== 'object' || Array.isArray(response))
|
|
56
70
|
return response;
|
|
@@ -91,7 +105,7 @@ export function registerApplicationTools(server, platform) {
|
|
|
91
105
|
annotations: writes
|
|
92
106
|
}, handle(config, async ({ projectId, ...body }) => {
|
|
93
107
|
const warnings = readApplicationPlatform(body.type) === 'mobile'
|
|
94
|
-
? [...await mobileTabsWarnings(platform, undefined, undefined, undefined, body.properties), ...mobileTransitionWarnings(body.properties)]
|
|
108
|
+
? [...await mobileTabsWarnings(platform, undefined, undefined, undefined, body.properties), ...mobileTransitionWarnings(body.properties), ...mobileOfflineWarnings(body.properties)]
|
|
95
109
|
: [];
|
|
96
110
|
const response = await platform.org('POST', `/applications/${projectId}`, { body });
|
|
97
111
|
forgetApplication(platform);
|
|
@@ -114,7 +128,7 @@ export function registerApplicationTools(server, platform) {
|
|
|
114
128
|
}, handle(config, async ({ id, ...body }) => {
|
|
115
129
|
const current = await resolveApplication(platform, id);
|
|
116
130
|
const warnings = current?.platform === 'mobile'
|
|
117
|
-
? [...await mobileTabsWarnings(platform, id, current.projectSlug, body.homepageId, body.properties), ...mobileTransitionWarnings(body.properties)]
|
|
131
|
+
? [...await mobileTabsWarnings(platform, id, current.projectSlug, body.homepageId, body.properties), ...mobileTransitionWarnings(body.properties), ...mobileOfflineWarnings(body.properties)]
|
|
118
132
|
: [];
|
|
119
133
|
const response = await platform.org('PUT', `/applications/${id}`, { body });
|
|
120
134
|
forgetApplication(platform, id);
|
package/dist/tools/flows.js
CHANGED
|
@@ -16,6 +16,8 @@ import { existingMatch, ifExistsParam, platformRename, withRename } from '../pla
|
|
|
16
16
|
import { randomUUID } from 'node:crypto';
|
|
17
17
|
import { flowProfileWarnings } from './profileWrite.js';
|
|
18
18
|
import { enforceTextHooks } from './textHookGuard.js';
|
|
19
|
+
import { readMobileOffline } from '../knowledge/platform/mobileOffline.js';
|
|
20
|
+
import { resolveProfile } from '../knowledge/platform/resolve.js';
|
|
19
21
|
import { jsonArray } from '../platform/jsonArray.js';
|
|
20
22
|
import { z } from 'zod';
|
|
21
23
|
/**
|
|
@@ -38,7 +40,7 @@ async function flowWriteDrops(platform, host, project, environment, applicationI
|
|
|
38
40
|
return emptyWriteDiff();
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
|
-
const stepsParam = jsonArray(z.array(z.record(z.unknown()))).describe("Adım listesi (StepManagementSchema: { stepId, name, type, kind, args, branches }). DİKKAT: branches[].nextStepId bir GUID değil, hedef adımın stepId STRING'idir; dal ADI motorun anahtarıdır ve start/setter/code/function adımlarında 'always' olmak zorundadır. Tam şablon: ngapps://examples/flow-load-table (ya da flow_get çıktısı); adım tipleri ve setter/parameters şekli platform_guide('page') Kural 1c. Kullanıcı fonksiyonu çağırmak için 'function' adımı: { type:'function', args:{ functionId:'<function_list id>', functionName:'<ad>', parameters:[{ name:'<bildirimdeki ad>', value:{ type:'static'|'property'|'storage'|'state'|'code', ref } }] } } → çıktı Steps.<adımAdı>.data (ngapps://examples/flow-call-function, platform_guide('functions')).");
|
|
43
|
+
const stepsParam = jsonArray(z.array(z.record(z.unknown()))).describe("Adım listesi (StepManagementSchema: { stepId, name, type, kind, args, branches }). DİKKAT: branches[].nextStepId bir GUID değil, hedef adımın stepId STRING'idir; dal ADI motorun anahtarıdır ve start/setter/code/function adımlarında 'always' olmak zorundadır. Tam şablon: ngapps://examples/flow-load-table (ya da flow_get çıktısı); adım tipleri ve setter/parameters şekli platform_guide('page') Kural 1c. Kullanıcı fonksiyonu çağırmak için 'function' adımı: { type:'function', args:{ functionId:'<function_list id>', functionName:'<ad>', parameters:[{ name:'<bildirimdeki ad>', value:{ type:'static'|'property'|'storage'|'state'|'code', ref } }] } } → çıktı Steps.<adımAdı>.data (ngapps://examples/flow-call-function, platform_guide('functions')). Mobilde çevrimdışı yazma: 'microservice' adımına 'queued' dalı, servis offlineWritable olmalı (platform_guide('page') Kural 1g-4).");
|
|
42
44
|
const policyOverrideParam = z.boolean().optional();
|
|
43
45
|
const patchOperationsParam = jsonArray(z.array(z.record(z.unknown())).min(1)).describe("RFC 6902 JSON Patch işlemleri; yolları flow_get çıktısıyla keşfedin. Dizi öğelerinde indeks yerine seçici kullanılabilir: '/steps[stepId=paint]/args/iteratees[element=tbl_recruiters]/mapping/source' — seçici gövde platforma gitmeden indekse çevrilir, çözülemezse istek hiç gönderilmez.");
|
|
44
46
|
const flowIdParam = guid.describe("Akış id'si; şemadaki events[].value bu id'dir");
|
|
@@ -323,6 +325,80 @@ async function functionWarnings(platform, host, project, environment, applicatio
|
|
|
323
325
|
}
|
|
324
326
|
return [...warnings];
|
|
325
327
|
}
|
|
328
|
+
/** Bir yazım boyunca servis tanımı okuyucusu: FLOW-043 ve FLOW-044 aynı servisi bir kez okur; okunamayan `undefined`. */
|
|
329
|
+
function serviceDefinitionReader(platform, project, environment, applicationId) {
|
|
330
|
+
const cache = new Map();
|
|
331
|
+
return microserviceId => {
|
|
332
|
+
if (!cache.has(microserviceId)) {
|
|
333
|
+
cache.set(microserviceId, platform.tenant('GET', project, `/microservices/${applicationId}/${microserviceId}`, { environment })
|
|
334
|
+
.then(payload => unwrap(payload))
|
|
335
|
+
.catch(() => undefined));
|
|
336
|
+
}
|
|
337
|
+
return cache.get(microserviceId);
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* FLOW-043 (kök ADR 0022, plans/mobil-cevrimdisi-calisma g-02). `microservice` adımının bağlı `queued` dalı yalnız
|
|
342
|
+
* mobil kabuklarda ve yalnız `offlineWritable` serviste koşar (ağ hatasında kayıt kuyruğa girer). İkisi tanımda yok:
|
|
343
|
+
* uygulama türü org'dan (`resolveProfile`), bildirim servis tanımından okunur. Okunamayan uygulama ya da servis
|
|
344
|
+
* uyarı üretmez — bilmediğimizi uyarı diye söylemeyiz.
|
|
345
|
+
*/
|
|
346
|
+
async function queuedBranchWarnings(platform, applicationId, steps, errorSteps, readService) {
|
|
347
|
+
const queuedSteps = [...(Array.isArray(steps) ? steps : []), ...(Array.isArray(errorSteps) ? errorSteps : [])].filter(isRecord)
|
|
348
|
+
.filter(step => String(step.type ?? '') === 'microservice')
|
|
349
|
+
.filter(step => (Array.isArray(step.branches) ? step.branches : []).filter(isRecord).some(branch => String(branch.name ?? '') === 'queued' && Boolean(branch.nextStepId)));
|
|
350
|
+
if (queuedSteps.length === 0)
|
|
351
|
+
return [];
|
|
352
|
+
const label = (step) => String(step.stepId ?? step.name ?? '?');
|
|
353
|
+
const resolved = await resolveProfile(platform, applicationId);
|
|
354
|
+
if (resolved.known && resolved.profile.platform !== 'mobile') {
|
|
355
|
+
return queuedSteps.map(step => `FLOW-043: '${label(step)}' adımının 'queued' dalı bu web uygulamasında hiç koşmaz — yazma kuyruğu yalnız mobil kabuklardadır; ağ hatası 'error' dalına gider.`);
|
|
356
|
+
}
|
|
357
|
+
const warnings = [];
|
|
358
|
+
for (const step of queuedSteps) {
|
|
359
|
+
const microserviceId = step.args?.microserviceId;
|
|
360
|
+
const definition = typeof microserviceId === 'string' ? await readService(microserviceId) : undefined;
|
|
361
|
+
// Alanı hiç taşımayan tanım (alan öncesi backend imajı) bilinmiyordur, "bildirimsiz" değil.
|
|
362
|
+
if (!definition || typeof definition.offlineWritable !== 'boolean' || definition.offlineWritable)
|
|
363
|
+
continue;
|
|
364
|
+
warnings.push(`FLOW-043: '${label(step)}' adımının 'queued' dalı bağlı ama '${String(definition.slug ?? microserviceId)}' servisi offlineWritable değil — 'queued' dalı bağlı yazmanın ilk isteği Idempotency-Key taşır, bildirimsiz servis onu 422 OfflineReplayNotAllowedException ile reddeder: adım çevrimiçiyken de HER ÇAĞRIDA 'error' dalına gider. Servis tekrarı kaldırıyorsa microservice_patch ile '/offlineWritable' true yapın; değilse 'queued' dalını kaldırın.`);
|
|
365
|
+
}
|
|
366
|
+
return warnings;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* FLOW-044 (plans/mobil-cevrimdisi-calisma g-03, telefon turu 2026-10-22). Veri önbelleği yalnız GET okumayı saklar
|
|
370
|
+
* (frontend `isCacheableMethod`): okuyan uca (görünüm kaynağı ya da tablo `get`/`count` — MS-025 ile aynı tanım) GET dışı
|
|
371
|
+
* yöntemle giden mobil adım ağsızken kayıttan dönemez, hata yoluna düşer. Yöntem servis tanımındandır: backend adımın
|
|
372
|
+
* `httpMethod`'unu her okumada servisten üretir (`StepManagementSchema`), adıma yazılan saklanmaz. Veri önbelleği kapalı
|
|
373
|
+
* uygulamada hiçbir okuma saklanmadığı için susar. İş akışı ve sorgu kaynaklı uç okuma mı yazma mı bilinmez (kök ADR 0022
|
|
374
|
+
* Y1) — susar; okunamayan uygulama ya da servis de uyarı üretmez.
|
|
375
|
+
*/
|
|
376
|
+
async function uncachedReadWarnings(platform, applicationId, steps, errorSteps, readService) {
|
|
377
|
+
const serviceSteps = [...(Array.isArray(steps) ? steps : []), ...(Array.isArray(errorSteps) ? errorSteps : [])].filter(isRecord)
|
|
378
|
+
.filter(step => String(step.type ?? '') === 'microservice')
|
|
379
|
+
.filter(step => typeof step.args?.microserviceId === 'string');
|
|
380
|
+
if (serviceSteps.length === 0)
|
|
381
|
+
return [];
|
|
382
|
+
const resolved = await resolveProfile(platform, applicationId);
|
|
383
|
+
if (!resolved.known || resolved.profile.platform !== 'mobile' || !readMobileOffline(resolved.application?.properties).data)
|
|
384
|
+
return [];
|
|
385
|
+
const warnings = [];
|
|
386
|
+
for (const step of serviceSteps) {
|
|
387
|
+
const args = step.args;
|
|
388
|
+
const definition = await readService(args.microserviceId);
|
|
389
|
+
if (!definition)
|
|
390
|
+
continue;
|
|
391
|
+
const source = String(definition.source ?? '').toLowerCase();
|
|
392
|
+
const operation = String(definition.sourceParameters?.operation ?? '').toLowerCase();
|
|
393
|
+
if (source !== 'view' && !(source === 'table' && (operation === 'get' || operation === 'count')))
|
|
394
|
+
continue;
|
|
395
|
+
const method = String(definition.httpMethod ?? 'get').toLowerCase();
|
|
396
|
+
if (method === 'get')
|
|
397
|
+
continue;
|
|
398
|
+
warnings.push(`FLOW-044: '${String(step.stepId ?? step.name ?? '?')}' adımı '${String(definition.slug ?? args.microserviceId)}' servisinden ${method.toUpperCase()} ile okuyor — veri önbelleği yalnız GET okumayı saklar: ağsızken bu adım kayıttan dönemez, hata yoluna düşer. Okuyan ucu GET yapın (microservice_patch '/httpMethod' 'get'; adımın yöntemi servisten gelir) ve gövdeden okunan parametreleri query-string'e taşıyın — uç filtrelerinin ve adım parametrelerinin source'u 'query-string' olmalı, GET'te gövde gitmez.`);
|
|
399
|
+
}
|
|
400
|
+
return warnings;
|
|
401
|
+
}
|
|
326
402
|
/**
|
|
327
403
|
* FLOW-038 (g-02, ADR 0004 — ZM-07). `microservice.ts` `.finally` üç yoldan birini dener: adımın
|
|
328
404
|
* kendi `error` dalı bağlıysa oradan sürer, yoksa flow `errorSteps`'i (`engine.onError`) devralır,
|
|
@@ -457,12 +533,15 @@ export function registerFlowTools(server, platform) {
|
|
|
457
533
|
hostTree: async () => hostNodes(hostRecord),
|
|
458
534
|
where: `akış '${name}'`
|
|
459
535
|
}, policyOverride);
|
|
536
|
+
const readService = serviceDefinitionReader(platform, project, environment, applicationId);
|
|
460
537
|
const parameterWarnings = [
|
|
461
538
|
...await requiredParameterWarnings(platform, project, environment, applicationId, steps),
|
|
462
539
|
...await functionWarnings(platform, host, project, environment, applicationId, hostId, steps),
|
|
463
540
|
...flowBodyWarnings(steps),
|
|
464
541
|
...unknownSetterTargetWarnings(steps, errorSteps ?? [], hostNodes(hostRecord)),
|
|
465
|
-
...microserviceAlwaysDataWarnings(steps, errorSteps ?? [])
|
|
542
|
+
...microserviceAlwaysDataWarnings(steps, errorSteps ?? []),
|
|
543
|
+
...await queuedBranchWarnings(platform, applicationId, steps, errorSteps ?? [], readService),
|
|
544
|
+
...await uncachedReadWarnings(platform, applicationId, steps, errorSteps ?? [], readService)
|
|
466
545
|
];
|
|
467
546
|
// Gövde yalnız akıştır (designer-partial-update K1): barındırıcı zarfı platformda hâlâ isteğe bağlı
|
|
468
547
|
// ama gönderilirse okunan tam kaydı yeniden yazar, açık Studio designer'ının kayıtlı tabanını
|
|
@@ -544,12 +623,15 @@ export function registerFlowTools(server, platform) {
|
|
|
544
623
|
where: `akış '${String(flow.name ?? flowId)}'`
|
|
545
624
|
}, policyOverride)
|
|
546
625
|
: [];
|
|
626
|
+
const readService = serviceDefinitionReader(platform, project, environment, applicationId);
|
|
547
627
|
const parameterWarnings = [
|
|
548
628
|
...await requiredParameterWarnings(platform, project, environment, applicationId, flow.steps),
|
|
549
629
|
...await functionWarnings(platform, host, project, environment, applicationId, hostId, flow.steps),
|
|
550
630
|
...flowBodyWarnings(flow.steps),
|
|
551
631
|
...unknownSetterTargetWarnings(flow.steps, flow.errorSteps, hostNodes(hostRecord)),
|
|
552
|
-
...microserviceAlwaysDataWarnings(flow.steps, flow.errorSteps)
|
|
632
|
+
...microserviceAlwaysDataWarnings(flow.steps, flow.errorSteps),
|
|
633
|
+
...await queuedBranchWarnings(platform, applicationId, flow.steps, flow.errorSteps, readService),
|
|
634
|
+
...await uncachedReadWarnings(platform, applicationId, flow.steps, flow.errorSteps, readService)
|
|
553
635
|
];
|
|
554
636
|
await platform.tenant('PUT', project, flowPath(host, applicationId, hostId, flowId), { environment, body: { flow } });
|
|
555
637
|
// Kısmi güncellemede yalnız GÖNDERİLEN alanlar karşılaştırılır; verilmeyen alan için
|
|
@@ -607,12 +689,15 @@ export function registerFlowTools(server, platform) {
|
|
|
607
689
|
where: `akış '${String(current.name ?? flowId)}'`
|
|
608
690
|
}, policyOverride)
|
|
609
691
|
];
|
|
692
|
+
const readService = serviceDefinitionReader(platform, project, environment, applicationId);
|
|
610
693
|
const parameterWarnings = [
|
|
611
694
|
...await requiredParameterWarnings(platform, project, environment, applicationId, flow.steps),
|
|
612
695
|
...await functionWarnings(platform, host, project, environment, applicationId, hostId, flow.steps),
|
|
613
696
|
...flowBodyWarnings(flow.steps),
|
|
614
697
|
...unknownSetterTargetWarnings(flow.steps, flow.errorSteps, hostNodes(hostRecord)),
|
|
615
|
-
...microserviceAlwaysDataWarnings(flow.steps, flow.errorSteps)
|
|
698
|
+
...microserviceAlwaysDataWarnings(flow.steps, flow.errorSteps),
|
|
699
|
+
...await queuedBranchWarnings(platform, applicationId, flow.steps, flow.errorSteps, readService),
|
|
700
|
+
...await uncachedReadWarnings(platform, applicationId, flow.steps, flow.errorSteps, readService)
|
|
616
701
|
];
|
|
617
702
|
// Gövde değil FARK gönderilir; platform PATCH ucu akışı tek başına yazar. Net diff okunan kayıt ile son hâl arasından hesaplanır.
|
|
618
703
|
const netOps = fastJsonPatch.compare(current, flow);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appaflytech/zeyrek-ai-mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.47",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Zeyrek (NgApps) platform APIs as MCP tools — data, logic and Studio design surface in one gateway",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -60,4 +60,4 @@
|
|
|
60
60
|
"typescript": "^5.7.2",
|
|
61
61
|
"vitest": "^3.0.0"
|
|
62
62
|
}
|
|
63
|
-
}
|
|
63
|
+
}
|