@appaflytech/zeyrek-ai-mcp 0.0.32 → 0.0.33
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 +15 -0
- package/dist/config.js +11 -0
- package/dist/index.js +2 -0
- package/dist/knowledge/access.js +802 -0
- package/dist/knowledge/case.js +41 -0
- package/dist/knowledge/componentCatalog.js +82 -213
- package/dist/knowledge/componentEvents.js +21 -19
- package/dist/knowledge/connectDataBind.js +819 -0
- package/dist/knowledge/connectDataDefinition.js +341 -0
- package/dist/knowledge/connectDataExecute.js +93 -0
- package/dist/knowledge/connectDataRules.js +128 -0
- package/dist/knowledge/decision.js +121 -0
- package/dist/knowledge/expressionPrelude.js +59 -0
- package/dist/knowledge/layoutSummary.js +140 -2
- package/dist/knowledge/microserviceParameters.js +58 -0
- package/dist/knowledge/mining.js +94 -0
- package/dist/knowledge/mobileComponentCatalog.js +864 -0
- package/dist/knowledge/mobileComponentEvents.js +239 -0
- package/dist/knowledge/mobileStore.js +227 -0
- package/dist/knowledge/normalize.js +121 -35
- package/dist/knowledge/platform/lint.js +385 -0
- package/dist/knowledge/platform/mobile.js +142 -0
- package/dist/knowledge/platform/mobileLayoutLint.js +324 -0
- package/dist/knowledge/platform/mobileRules.js +231 -0
- package/dist/knowledge/platform/mobileSpacing.js +82 -0
- package/dist/knowledge/platform/mobileTabs.js +108 -0
- package/dist/knowledge/platform/nativeBoxModel.js +44 -0
- package/dist/knowledge/platform/profile.js +25 -0
- package/dist/knowledge/platform/resolve.js +122 -0
- package/dist/knowledge/platform/web.js +39 -0
- package/dist/knowledge/process.js +510 -0
- package/dist/knowledge/rowFilter.js +43 -0
- package/dist/knowledge/rules.js +291 -19
- package/dist/knowledge/styleResolve.js +55 -38
- package/dist/knowledge/styleResolveNative.js +527 -0
- package/dist/knowledge/themeResolve.js +3 -3
- package/dist/observability/trace.js +1 -1
- package/dist/platform/argumentAliases.js +128 -0
- package/dist/platform/bodyFile.js +103 -0
- package/dist/platform/capture/actions.js +333 -0
- package/dist/platform/capture/browser.js +1 -0
- package/dist/platform/{screenshot.js → capture/capture.js} +81 -519
- package/dist/platform/capture/console-log.js +122 -0
- package/dist/platform/capture/index.js +11 -0
- package/dist/platform/capture/readiness.js +103 -0
- package/dist/platform/capture/summary.js +77 -0
- package/dist/platform/capture/target.js +5 -0
- package/dist/platform/capture/targets/studio-mobile.js +15 -0
- package/dist/platform/capture/targets/studio-web.js +5 -0
- package/dist/platform/diagnostics.js +10 -4
- package/dist/platform/domSummary.js +1 -1
- package/dist/platform/http.js +23 -7
- package/dist/platform/impersonation.js +45 -0
- package/dist/platform/jsonArray.js +24 -0
- package/dist/platform/responses.js +6 -2
- package/dist/platform/schemaReadMemory.js +60 -0
- package/dist/platform/secrets.js +9 -0
- package/dist/platform/strictArguments.js +68 -12
- package/dist/platform/tokenVault.js +187 -4
- package/dist/resources/examples/bpm-gorev-kontrol.json +294 -0
- package/dist/resources/examples/bpm-iso-dokuman.json +228 -0
- package/dist/resources/examples/bpm-satinalma.json +376 -0
- package/dist/resources/examples/connect-data-convert-verify.json +107 -0
- package/dist/resources/examples/connect-data-dropdown-roles.json +66 -0
- package/dist/resources/examples/connect-data-edit-m2m.json +73 -0
- package/dist/resources/examples/connect-data-query-params.json +50 -0
- package/dist/resources/examples/connect-data-table-entity.json +147 -0
- package/dist/resources/examples/connect-data-workflow-microservice.json +65 -0
- package/dist/resources/examples/layout-app-shell.json +229 -707
- package/dist/resources/examples/mobile-app-shell-drawer.json +244 -0
- package/dist/resources/examples/mobile-app-shell-stack.json +157 -0
- package/dist/resources/examples/mobile-app-shell-tab.json +208 -0
- package/dist/resources/examples/mobile-form-screen.json +365 -0
- package/dist/resources/examples/mobile-list-detail-form.json +703 -0
- package/dist/resources/examples/page-flex-sections.json +1 -1
- package/dist/resources/guides/access.md +796 -0
- package/dist/resources/guides/bpm.md +686 -0
- package/dist/resources/guides/case.md +153 -0
- package/dist/resources/guides/component.md +10 -2
- package/dist/resources/guides/decision.md +185 -0
- package/dist/resources/guides/expressions.md +14 -5
- package/dist/resources/guides/functions.md +1 -1
- package/dist/resources/guides/layout.md +55 -58
- package/dist/resources/guides/microservice.md +9 -2
- package/dist/resources/guides/middleware.md +34 -2
- package/dist/resources/guides/mobile-layout.md +193 -0
- package/dist/resources/guides/mobile.md +578 -0
- package/dist/resources/guides/page.md +221 -92
- package/dist/resources/guides/theme.md +8 -2
- package/dist/resources/guides/translation.md +1 -1
- package/dist/resources/guides/workflow.md +7 -1
- package/dist/resources/read.js +41 -0
- package/dist/resources/schema-fingerprint.json +4 -4
- package/dist/resources/schemas/AccessExplanationDto.json +144 -0
- package/dist/resources/schemas/AccessMatrixDto.json +170 -0
- package/dist/resources/schemas/AccessPermissionDto.json +57 -0
- package/dist/resources/schemas/AccessPolicyDto.json +223 -0
- package/dist/resources/schemas/AccessResourceDto.json +86 -0
- package/dist/resources/schemas/AppSessionDto.json +53 -0
- package/dist/resources/schemas/ConnectDataDescribeDto.json +344 -0
- package/dist/resources/schemas/ConnectDataRequestModel.json +202 -0
- package/dist/resources/schemas/ConnectDataResultDto.json +421 -0
- package/dist/resources/schemas/ConnectorCredentialDto.json +70 -0
- package/dist/resources/schemas/ConvertConnectDataToMicroserviceCommand.json +37 -0
- package/dist/resources/schemas/CreateAccessPolicyCommand.json +209 -0
- package/dist/resources/schemas/CreateDecisionCommand.json +221 -0
- package/dist/resources/schemas/CreateProcessDefinitionCommand.json +1337 -0
- package/dist/resources/schemas/DecisionDto.json +302 -0
- package/dist/resources/schemas/DetachConnectDataMicroserviceCommand.json +28 -0
- package/dist/resources/schemas/ExplainAccessQuery.json +33 -0
- package/dist/resources/schemas/GenerateProcessDocumentCommand.json +116 -0
- package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +3 -1
- package/dist/resources/schemas/MicroserviceDto.json +2 -2
- package/dist/resources/schemas/OrganizationProjectDto.json +335 -0
- package/dist/resources/schemas/OrganizationSchemaDto.json +196 -0
- package/dist/resources/schemas/OrganizationSchemaVersionDto.json +207 -0
- package/dist/resources/schemas/PatchProcessDefinitionCommand.json +76 -0
- package/dist/resources/schemas/ProcessDefinitionDto.json +1480 -0
- package/dist/resources/schemas/ProcessSimulationDto.json +96 -0
- package/dist/resources/schemas/SaveConnectorCredentialCommand.json +90 -0
- package/dist/resources/schemas/SaveProcessEventSourceCommand.json +61 -0
- package/dist/resources/schemas/SaveProcessMailSourceCommand.json +89 -0
- package/dist/resources/schemas/SignProcessTaskCommand.json +73 -0
- package/dist/resources/schemas/SimulateProcessDefinitionQuery.json +92 -0
- package/dist/resources/schemas/StartMobileBuildCommand.json +54 -0
- package/dist/resources/schemas/UpdateAccessPolicyCommand.json +209 -0
- package/dist/resources/schemas/UpdateDecisionCommand.json +216 -0
- package/dist/resources/schemas/UpdateProcessDefinitionCommand.json +1357 -0
- package/dist/resources/schemas/UpsertMobileStoreSettingsCommand.json +259 -0
- package/dist/resources/schemas/ValidateProcessDefinitionQuery.json +1339 -0
- package/dist/server.js +7 -1
- package/dist/tools/accessOperations.js +135 -0
- package/dist/tools/accessPolicies.js +170 -0
- package/dist/tools/accessRuntime.js +203 -0
- package/dist/tools/applications.js +60 -3
- package/dist/tools/bpm.js +343 -0
- package/dist/tools/bpmGovernance.js +266 -0
- package/dist/tools/bpmOperations.js +230 -0
- package/dist/tools/bpmReporting.js +154 -0
- package/dist/tools/bpmRouting.js +150 -0
- package/dist/tools/bpmRuntime.js +396 -0
- package/dist/tools/case.js +178 -0
- package/dist/tools/caseRuntime.js +89 -0
- package/dist/tools/components.js +103 -12
- package/dist/tools/connectData.js +449 -0
- package/dist/tools/connectors.js +193 -0
- package/dist/tools/datasources.js +1 -1
- package/dist/tools/decisions.js +206 -0
- package/dist/tools/designSchemaPatch.js +22 -16
- package/dist/tools/externalComponents.js +25 -4
- package/dist/tools/flows.js +79 -6
- package/dist/tools/layouts.js +44 -12
- package/dist/tools/microservices.js +32 -10
- package/dist/tools/mobile.js +221 -0
- package/dist/tools/mobileStore.js +268 -0
- package/dist/tools/modules.js +48 -0
- package/dist/tools/organizationStructure.js +137 -0
- package/dist/tools/pages.js +391 -92
- package/dist/tools/platformInfo.js +7 -2
- package/dist/tools/profileWrite.js +92 -0
- package/dist/tools/rows.js +7 -1
- package/dist/tools/schemaOps.js +33 -1
- package/dist/tools/screenWrite.js +15 -7
- package/dist/tools/screens.js +90 -3
- package/dist/tools/variables.js +11 -5
- package/package.json +2 -2
- package/dist/knowledge/boxSections.js +0 -184
|
@@ -4,6 +4,10 @@ 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
|
+
|
|
7
11
|
## Kuruluş sırası
|
|
8
12
|
|
|
9
13
|
```
|
|
@@ -222,7 +226,7 @@ döndürür; hata yok, sayfalama yok. (Bağımsız `pagination` komponenti bu tu
|
|
|
222
226
|
| `dropdown.search` · `multi-select.search` | `{ searchText }` | `self.searchText` |
|
|
223
227
|
| `tabs.tab` | `{ selected }` | `self.selected` ya da `event.data.selected` |
|
|
224
228
|
| `chart.dataPointClick` | `{ name, seriesName, value, dataIndex, row }` | `self.row` (kaynak satırın tamamı) |
|
|
225
|
-
| `repeater.change` · `repeater.select` | `{ selectedIndex }` | `self.selectedIndex` · `self.selectedItem` (akış satır bağlamında koşmaz, `item`/`Row` boş) |
|
|
229
|
+
| `repeater.change` · `repeater.select` | `{ selectedIndex }` | `self.selectedIndex` · `self.selectedItem` (akış satır bağlamında koşmaz, `item`/`Row` boş); satırdaki bir düğmenin akışında setter'ın yazım kapsamı OLAYIN kaynağı değil HEDEFİN ağaçtaki yeriyle belirlenir — satırın şablonu içindeki bir hedefe satır bazlı (`_repeaterValues`), dışındaki bir hedefe (modal, sayfa düzeyi metin) sayfa kapsamında yazılır (ZM-08, 2026-09-26); iç içe repeater zaten `PAGE-013` ile reddedilir, ama bir DIŞ repeater'ın şablonuna İÇ satırdan yazan bir akış varsa yazım dış satırın değil İÇ satırın kimliğiyle anahtarlanır — bilinen açık, PAGE-013 riski düşük tutar |
|
|
226
230
|
| `html` aksiyonu (`fireEvent`) | ikinci argüman | **`event.data`** |
|
|
227
231
|
| `kanban.cardMove` | `{ id, row, from, to }` | **`event.data`** (self'e yazılmaz) |
|
|
228
232
|
| `kanban.cardAdd` · `kanban.cardRemove` | `{ column }` · `{ id, row, column }` | **`event.data`** (self'e yazılmaz; kart eklenmez/gizlenmez, akış yazıp `rows`'u tazeler) |
|
|
@@ -245,7 +249,8 @@ dalı bulamaz ve akışı **sessizce durdurur** (`flow-engine.ts:79`); Studio da
|
|
|
245
249
|
`sourceBranch === 'always'` ile çizdiği için panelde **Start kartından sonrası boş görünür**.
|
|
246
250
|
İstisnalar: `condition` → dal adı rule id'sidir (ve o id bir **GUID**'dir — aşağıdaki tuzak 6),
|
|
247
251
|
`confirm` → `yes|no|always`, `microservice` →
|
|
248
|
-
`always` (eski akışlarda `success` de çalışır)
|
|
252
|
+
`always` (eski akışlarda `success` de çalışır) **+ `error`** — bağlarsan hata anında `always`
|
|
253
|
+
yerine ondan sürer (2026-09-26, ADR 0004; ayrıntı aşağıdaki §"4xx de hatadır").
|
|
249
254
|
|
|
250
255
|
**2. `iteratees[].type` yalnız `change` | `fill`.** `setter.ts` başka değerde hiçbir dala
|
|
251
256
|
girmez — adım çalışır, hiçbir şey yapmaz. `change` tek prop'a değer yazar, `fill` diziyi
|
|
@@ -371,36 +376,42 @@ Satır eşlemeli tablo yüklemesinin tam şekli (yükleniyor bayrağı → uç
|
|
|
371
376
|
göstermek error flow'un işidir.
|
|
372
377
|
|
|
373
378
|
> **4xx de hatadır ve `always` dalı seni KURTARMAZ.** `microservice.ts` `.catch` bloğu
|
|
374
|
-
> reddedilen her istekte koşar — 401/403/404/422 dâhil
|
|
375
|
-
>
|
|
379
|
+
> reddedilen her istekte koşar — 401/403/404/422 dâhil — ve storage'a HER ZAMAN
|
|
380
|
+
> `{ data: null, headers: null, error: { status, message, body } }` yazar (ADR 0004,
|
|
381
|
+
> 2026-09-26 — eskiden hata gövdesi `data`'ya yazılıyordu). `.finally` sonra ÜÇ yoldan birini
|
|
382
|
+
> dener, SIRAYLA:
|
|
376
383
|
>
|
|
377
|
-
> 1. **
|
|
378
|
-
> `
|
|
379
|
-
>
|
|
380
|
-
>
|
|
381
|
-
>
|
|
382
|
-
> `!!Steps.signIn.data.token` gibi bir
|
|
383
|
-
>
|
|
384
|
+
> 1. **Adımın kendi `error` dalı BAĞLIYSA** akış oradan sürer — `always` **hiç koşmaz**
|
|
385
|
+
> (`hasBranch('error')`). Bu dal `Steps.<ad>.error` okuyabilir; ana akışın kalanı hiç çalışmaz.
|
|
386
|
+
> 2. **`error` dalı yoksa, `errorSteps` VARSA** `engine.onError` true döner ve `.finally` `return`
|
|
387
|
+
> eder — yine `always` koşmaz, flow'un hata akışı devralır (aşağıdaki karşılaştırma tablosu).
|
|
388
|
+
> 3. **İkisi de yoksa** `always` koşar, ama `Steps.<ad>.data` artık **NULL**dır — başarı gövdesi
|
|
389
|
+
> değil, hiç gövde değil. Sıradaki bir `condition` `!!Steps.signIn.data.token` gibi bir
|
|
390
|
+
> ifadeyi `null.token` üzerinden dener; `runCode` hatayı yutar (K2), ifade `undefined` döner ve
|
|
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.
|
|
384
395
|
>
|
|
385
396
|
> **`errorSteps` yalnız `start` taşıyorsa hata yolu YOKTUR:** `hasErrorFlow`
|
|
386
397
|
> `errorTasks.some(t => t.type !== 'start')` arar. Start'ın ardına en az bir adım bağla —
|
|
387
398
|
> gateway `FLOW-021` ile uyarır.
|
|
388
399
|
>
|
|
389
|
-
> **
|
|
390
|
-
> `
|
|
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.
|
|
400
|
+
> **Mobil uygulama:** mobil runtime (`@ng-apps/ui-native` `NativeRuntime`) `errorSteps`'i web gibi
|
|
401
|
+
> `errorTasks`'a eşler — hata yolu iki platformda aynı koşar.
|
|
394
402
|
|
|
395
|
-
> **Hata metni
|
|
403
|
+
> **Hata metni birden çok yerde durur, hepsi aynı şey değildir (2026-09-26 itibarıyla, ADR 0004).**
|
|
396
404
|
> `onError` hata akışını koşturmadan önce `machine.setStorage('error', errorInfo)` yapar
|
|
397
|
-
> (`flow-engine.ts`), yani hata akışının adımları `Steps.error`'ı okuyabilir
|
|
405
|
+
> (`flow-engine.ts`), yani hata akışının adımları `Steps.error`'ı okuyabilir; patlayan adımın
|
|
406
|
+
> KENDİ storage'ı ise (bağlı `error` dalı da `always` da) `Steps.<adımAdı>.error` nesnesini taşır:
|
|
398
407
|
>
|
|
399
408
|
> | İfade | Ne taşır | Kaynak |
|
|
400
409
|
> |---|---|---|
|
|
401
|
-
> | **`Steps.error.message`** | **
|
|
402
|
-
> | `Steps.<adımAdı>.error` |
|
|
403
|
-
> | `Steps.<adımAdı>.
|
|
410
|
+
> | **`Steps.error.message`** | **Yalnız `errorSteps` içinde** — ucun kendi mesajı, `err.reason` → HTTP durum metni → `'Service request failed'`. Yanında `Steps.error.code` · `Steps.error.step.name` (patlayan adım) · `Steps.error.step.data` (ucun hata gövdesi; parametre ifadesi patladıysa `null`) gelir | `microservice.ts` `err.reason \|\| HttpStatusText[err.code]` → `flow-engine.ts` `onError` |
|
|
411
|
+
> | `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` |
|
|
412
|
+
> | `Steps.<adımAdı>.error.status` | HTTP durum KODU (sayı) — parametre ifadesi patladıysa `null` | `microservice.ts` `.catch` |
|
|
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` |
|
|
404
415
|
>
|
|
405
416
|
> **`alert` adımının `message`'ı DÜZ METİNDİR — ifade yazarsan ekranda o ifade görünür.**
|
|
406
417
|
> `alert.ts` `task.argument.message`'ı doğrudan `toast.error()`'a geçirir ve `args` hiçbir yerde
|
|
@@ -428,15 +439,24 @@ göstermek error flow'un işidir.
|
|
|
428
439
|
> `{ "type": "confirm", "args": { "message": "Bu risk ve 4 aksiyonu silinecek.", "title": "Riski sil",
|
|
429
440
|
> "confirmText": "Sil", "cancelText": "Vazgeç" } }`.
|
|
430
441
|
|
|
431
|
-
> **Hangi yolu seçeceksin — `errorSteps` mi, ana akışta
|
|
432
|
-
>
|
|
442
|
+
> **Hangi yolu seçeceksin — adımın kendi `error` dalı mı, `errorSteps` mi, ana akışta
|
|
443
|
+
> `condition` mı?** Bir hatada sırayla denenir (yukarıdaki 4xx bölümü) — üçü birden TANIMLI
|
|
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`:
|
|
433
446
|
>
|
|
434
|
-
> | | `errorSteps` | ana akışta `condition Steps.<adımAdı>.error` |
|
|
435
|
-
>
|
|
436
|
-
> |
|
|
437
|
-
> |
|
|
438
|
-
> |
|
|
439
|
-
> |
|
|
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) |
|
|
454
|
+
>
|
|
455
|
+
> **"Ana akışta condition" sütunu `.error`'u okumalı, `.data`'yı değil.** `Steps.<adımAdı>.data`'nın
|
|
456
|
+
> DOLU/BOŞ olmasına bakarak başarı/hata ayırmak (`data.token` gibi bir alanın varlığını yoklamak)
|
|
457
|
+
> artık yanıltıcıdır — `data` hata anında zaten `null`'dur (yukarıdaki §"4xx de hatadır"). Böyle bir
|
|
458
|
+
> `condition`'ı gateway **FLOW-028** ile uyarır; adıma ayrıca bir `error` dalı bağlayın (aşağıdaki
|
|
459
|
+
> 7c örneği) — `error` dalı bağlıysa uyarı düşer, çünkü hata artık `always`'e hiç uğramaz.
|
|
440
460
|
|
|
441
461
|
Zorunlu filtresi olan uçlarda (`patient-*`, `doctor-appointments` gibi `isRequired: true`
|
|
442
462
|
filtreli microservice'ler) parametreyi adımda ver, yoksa uç `MissingParameterException` atar:
|
|
@@ -513,21 +533,21 @@ Tarif: `platform_guide('middleware')`.
|
|
|
513
533
|
|
|
514
534
|
**Sözlükler** (`StepType.cs`, `StepParameterValueType.cs` — hepsi küçük harf):
|
|
515
535
|
`start · microservice · setter · setcookie · validation · condition · redirect · alert ·
|
|
516
|
-
confirm · flow-trigger · storage · navigate · code · download · function · end`
|
|
536
|
+
confirm · flow-trigger · storage · navigate · code · download · function · share · end`
|
|
517
537
|
değer tipleri: `static · page · property · storage · variable · code · item · state`
|
|
518
538
|
|
|
519
539
|
> **Sözlükte olmak KOŞACAĞI anlamına gelmez — koşan tipler barındırıcıdan gelir.** Motor yedi
|
|
520
540
|
> tip register eder, gerisini uygulama ekler. Bir sayfa TEK bir uygulamaya aittir
|
|
521
541
|
> (`Page.ApplicationId`) ve uygulamanın tipi `web` ya da `mobile`'dır (`ApplicationType.cs`), yani
|
|
522
542
|
> sayfanın barındırıcısı bellidir — matris "hangi tip sende çalışır"ı söyler, iki barındırıcıda
|
|
523
|
-
> birden koşmayı değil (web `Runtime.svelte`, mobil `
|
|
543
|
+
> birden koşmayı değil (web `Runtime.svelte`, mobil uygulama `@ng-apps/ui-native` `NativeRuntime`):
|
|
524
544
|
>
|
|
525
|
-
> | Adım tipi | Web | Mobil | Nerede register ediliyor |
|
|
545
|
+
> | Adım tipi | Web | Mobil uygulama | Nerede register ediliyor |
|
|
526
546
|
> |---|---|---|---|
|
|
527
|
-
> | `start` · `setter` · `code` · `condition` · `microservice` · `validation` · `flow-trigger` · `function` | ✅ | ✅ | `flow-engine.ts` — motorun kendisi
|
|
528
|
-
> | `alert` · `redirect` · `setcookie` · `storage` | ✅ | ✅ |
|
|
529
|
-
> | `confirm` · `download` | ✅ |
|
|
530
|
-
> | `navigate` | ❌ | ✅
|
|
547
|
+
> | `start` · `setter` · `code` · `condition` · `microservice` · `validation` · `flow-trigger` · `function` | ✅ | ✅ | `flow-engine.ts` — motorun kendisi |
|
|
548
|
+
> | `alert` · `redirect` · `setcookie` · `storage` | ✅ | ✅ | barındırıcı; mobilde `setcookie` cihaz deposuna yazar (`MOB-005`) |
|
|
549
|
+
> | `confirm` · `download` · `share` | ✅ | ✅ | `Runtime.svelte` · `runtime-tasks.ts` (`download` mobilde açma/paylaşım — `MOB-005`; `share` aşağıda) |
|
|
550
|
+
> | `navigate` | ❌ | ✅ (`redirect` takma adı) | web'deki karşılığı `redirect`; gateway `redirect`'e çevirir |
|
|
531
551
|
> | `end` · `query` | ❌ | ❌ | hiçbir yerde — üstelik `query` backend sözlüğünde de yok (`StepType.cs` onu saymaz), yalnız frontend enum'unda duruyor |
|
|
532
552
|
>
|
|
533
553
|
> **Register edilmemiş bir tipe gelen akış SESSİZCE durur.** `flow-engine.ts` `process()`
|
|
@@ -563,6 +583,19 @@ değer tipleri: `static · page · property · storage · variable · code · it
|
|
|
563
583
|
> adımında ve `{{ }}` bağlamasında `Functions.<ad>(…)` ile de çağrılır; gateway bilinmeyen adı ve
|
|
564
584
|
> fazla argümanı FLOW-025 ile uyarır. Tam gövde `ngapps://examples/flow-call-function`, kurallar
|
|
565
585
|
> **`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.
|
|
566
599
|
|
|
567
600
|
> Bir microservice adımı kaydedildiğinde platform `args.microserviceSchema`'yı
|
|
568
601
|
> (parameterScheme + returnScheme + `isReturnArray`) kendisi doldurur — `flow_get` ile geri
|
|
@@ -861,7 +894,7 @@ kullanır: `page.mappers.ts` `mapPageLayoutToPreview` — layout varsa çizilen
|
|
|
861
894
|
> `add_component` ile yeniden kurmaktır (sonrasında Kural 2'deki flow yeniden kaydetme adımı
|
|
862
895
|
> ZORUNLU olur).
|
|
863
896
|
|
|
864
|
-
|
|
897
|
+
Dar ekran notu: <768px'te ızgara tek kolona düşer (`RenderComponent` media query'si) — y sırası
|
|
865
898
|
dikey sıraya dönüşür, x/w yok sayılır. Yerleşimi masaüstü (breakpoint 1024) bloğuyla kur.
|
|
866
899
|
|
|
867
900
|
## Kural 1f-2 — Kapsayıcı düzeni: `flex` (varsayılan) ↔ `grid`
|
|
@@ -879,7 +912,7 @@ aynı prop grubunu o da alır. Grup katalogda tanımlıdır, yani şemadan kurul
|
|
|
879
912
|
| `horizontalAlign` | **`left`** · `center` · `right` · `stretch` | `row`'da ana eksen (`justify-content`), `column`'da çapraz eksen (`align-items`). |
|
|
880
913
|
| `verticalAlign` | **`top`** · `middle` · `bottom` · `stretch` | `row`'da çapraz eksen, `column`'da ana eksen (rolleri `horizontalAlign` ile takas). |
|
|
881
914
|
| `size` | **`shrink`** · `grow` | Çocuklara `flex: 0 1 auto` / `1 1 auto`. |
|
|
882
|
-
| `gap` | `none` · `small` · **`medium`** · `large`
|
|
915
|
+
| `gap` | `none` · `small` · **`medium`** · `large` | Preset'ler tema değişkenidir: 0 / `var(--ng-spacing-sm)` / `--ng-spacing-md` / `--ng-spacing-lg` (varsayılan temada 8/16/32px). Yalnız bu dört preset geçer: `"18px"` gibi ham değer platform doğrulamasında `invalid-enum-value` ile reddedilir. `box-section`/`aibox`'taki sayısal `gapCustom` doluysa preset'i ezer. |
|
|
883
916
|
| `wrap` | kapalı · **açık** | `flex-wrap`. **Varsayılan 2026-09-01'de açık oldu:** `row` + `w:12` çocuklar artık alt satıra sararak dikey akar. Kapatırsan taşan çocuklar tek satıra sıkışır. |
|
|
884
917
|
|
|
885
918
|
**`form` da bu grubun tamamını taşır (2026-09-01):** varsayılanları container ile aynı
|
|
@@ -950,10 +983,10 @@ Beş şeyi bilmeden flex kurma:
|
|
|
950
983
|
4. **`layout: 'grid'` iken diğer altı prop ÖLÜDÜR.** Katalogda tanımlı oldukları için
|
|
951
984
|
doğrulama duvarı susar, renderer da okumaz: ızgara kapsayıcıya `direction: 'column'` yazmak
|
|
952
985
|
sessizce hiçbir şey yapmaz. Gateway bunu **PAGE-015 (uyarı)** ile söyler.
|
|
953
|
-
5. **Flex düzeni kırılım BİLMEZ.** `direction`/`gap`/hizalama masaüstü ve
|
|
954
|
-
sıra ve span'lar Desktop (1024) bloğundandır — Studio,
|
|
986
|
+
5. **Flex düzeni kırılım BİLMEZ.** `direction`/`gap`/hizalama masaüstü ve dar ekranda AYNIDIR;
|
|
987
|
+
sıra ve span'lar Desktop (1024) bloğundandır — Studio, dar ekran kırılımı düzenlenirken flex
|
|
955
988
|
bölgeyi salt-okunur kilitler. Kırılım bilen yalnız `blocks[]` ve `appearance.hideOn`'dur;
|
|
956
|
-
|
|
989
|
+
dar ekranda farklı davranış gereken satır için `layout: 'grid'` kullan (Kural 1f dar ekran notu).
|
|
957
990
|
|
|
958
991
|
```jsonc
|
|
959
992
|
// Ortalanmış giriş kartı — style ile CSS hack'i YOK, kabın kendi düzeni
|
|
@@ -976,7 +1009,7 @@ gibi bitişik duracak elemanlar için ÜÇ şart birden gerekir; biri eksikse ar
|
|
|
976
1009
|
|
|
977
1010
|
1. Her çocuğa **`appearance.widthType: 'auto'`** — içerik kadar yer kaplar (`flex: 0 1 auto`).
|
|
978
1011
|
Yazılmazsa eski 12 kolon payı geçerlidir ve çocuk kolonunu doldurur, bitişemez.
|
|
979
|
-
2. Kaba **`gap: 'none'`** (
|
|
1012
|
+
2. Kaba **`gap: 'none'`** (ham ince değer yazılamaz — `"2px"` platformda 422; ince aralık gerekiyorsa çocuğa `appearance.marginType: 'custom'`).
|
|
980
1013
|
3. Her çocuğa **`appearance.marginType: 'none'`** — en çok atlanan şart: `marginType`
|
|
981
1014
|
yazılmamış düğüm `normal` sayılır ve her kenara 4px basar (`spacing.ts`
|
|
982
1015
|
`CANVAS_NORMAL_MARGIN`), yani `gap:'none'` olsa bile komşular arasında 8px kalır.
|
|
@@ -1080,15 +1113,22 @@ UYGULAMAZ** — koordinatları aynen kaydeder (aşağı itme yalnız `page_creat
|
|
|
1080
1113
|
> SONRAKİ ağaca bakarak. Layout'ta da geçerlidir: kırılma
|
|
1081
1114
|
> `_repeaterValues` geri yazmasındadır, barındıranın sayfa mı layout mu olduğuna bakmaz.
|
|
1082
1115
|
>
|
|
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
|
+
>
|
|
1083
1120
|
> **Yapılacak:** satır içi listeyi tek bir `textarea`'da **satır başına bir öğe** olarak topla
|
|
1084
1121
|
> (`options_text`), kaydederken `split('\n')`'le böl. Ölçülmüş çalışan sürüm: anket editörü
|
|
1085
1122
|
> (`anket-admin/anket-duzenle`). Gerçekten satır satır düzenleme gerekiyorsa iç listeyi AYRI bir
|
|
1086
1123
|
> sayfada/modalda yönet — iç içe repeater bunu karşılamıyor.
|
|
1087
1124
|
|
|
1088
1125
|
> **Repeater satırını akıştan silmek/eklemek:** repeater ÇOCUĞUNDAKİ bir butonun click akışında
|
|
1089
|
-
>
|
|
1090
|
-
> (`isRepeaterSelf` dalı
|
|
1091
|
-
>
|
|
1126
|
+
> tıklanan satır olay makineye gitmeden SEÇİLİR, yani `q_list.selectedIndex` o satırdır — her runtime
|
|
1127
|
+
> sürümünde. Hedef repeater'ın KENDİSİ olduğu için `rows`'a yazmak serbesttir (`isRepeaterSelf` dalı
|
|
1128
|
+
> satır-değeri yoluna girmez). Desen:
|
|
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ı.
|
|
1092
1132
|
> Ekleme aynı şekilde `.slice()` + `push` ile yapılır; satır numarasını ekledikten sonra yeniden ata.
|
|
1093
1133
|
|
|
1094
1134
|
**Gönderimi saklamak:** satır başına normalize kayıt yerine tek `TEXT` kolonda anlık görüntü
|
|
@@ -1097,6 +1137,45 @@ kendisi nesneye çevirir; Studio tablosunda `[object Object]` görünmesi normal
|
|
|
1097
1137
|
(`platform_guide('entity')` → "TEXT kolonunda JSON"). Ekranın görsel tarafı için **Kural 1h**:
|
|
1098
1138
|
tema `--ng-*` değişkenleriyle tek yerden çevrilir, `html` kaçış kapısına gerek kalmaz.
|
|
1099
1139
|
|
|
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
|
+
|
|
1100
1179
|
## Kural 1h — Tasarım: `style` prop'u ve tema değişkenleri
|
|
1101
1180
|
|
|
1102
1181
|
Her komponentin `style` prop'u vardır ve emotion `css()` bloğudur: iç seçiciler, pseudo-class'lar
|
|
@@ -1304,20 +1383,6 @@ bağlamında `page_runtime_get` → `theme.presets`; `componentStyles[type]` ref
|
|
|
1304
1383
|
Preset'in kendisini yazmak/silmek `theme_update` işidir — `platform_guide('theme')`. Bir alanı temaya bırakmak = o alanı hiç yazmamak;
|
|
1305
1384
|
studio'da bunun adı "Temaya dön"dür. Tema değerini gruba kopyalama — bağ kopar, tema değişince izlemez.
|
|
1306
1385
|
|
|
1307
|
-
**Yatay denge MÜREKKEPLE ölçülür, kutuyla değil (2026-09-29).** "Soldan sağdan eşit" bir
|
|
1308
|
-
düğme/çip/hap için iki kenardaki boşluk, elemanların kutusundan değil GÖRÜNEN çizgiden ölçülür:
|
|
1309
|
-
Material glifinin kendi yan boşluğu (~0.2em) vardır ve kutular eşitken ikon tarafı 3px daha
|
|
1310
|
-
geniş görünür. Rexora'da "Export Report" ve "Save Order" kutu ölçüsüyle 12/12 "eşit" raporlandı,
|
|
1311
|
-
kullanıcı iki kez "yazı sağa yapışmış" dedi. Kurallar:
|
|
1312
|
-
- `button` ikon + metinde dengeyi KENDİSİ kurar (ikon tarafını ~0.2em daraltır). Dolguyu
|
|
1313
|
-
değiştirmek için `style.padding` YAZMA — `!important` ile bu dengeyi ezer; `style:
|
|
1314
|
-
{ '--ng-btn-pad-x': '18px' }` yaz, iki taraf ondan türetilir.
|
|
1315
|
-
- Yuvarlak (pill) düğmede yatay dolgu yüksekliğin ~%35-40'ı olmalı; 44px'lik hapta 12px dar
|
|
1316
|
-
görünür (16-18px).
|
|
1317
|
-
- Kendi kurduğun çipte (container/html) ikon tarafını glif yan boşluğu kadar dar tut ya da
|
|
1318
|
-
simetrik bir öğeyle (avatar, nokta) başla. Doğrulama: `page_screenshot` + ölçü betiğinde
|
|
1319
|
-
glifin `measureText().actualBoundingBox*` değerleriyle mürekkep kenarı.
|
|
1320
|
-
|
|
1321
1386
|
**Efektif stili okumak:** `page_runtime_get(resolveStyles: true)` her düğüme `resolvedStyle`
|
|
1322
1387
|
(kaskad çözülmüş birleşik stil) ve `styleLayers` (`{ typedGroups, componentStyle, preset, own }`)
|
|
1323
1388
|
ekler. "Bu kutu neden böyle görünüyor / benim yazdığım stil neden görünmüyor" sorusunun cevabı
|
|
@@ -1337,6 +1402,16 @@ alanları silinir. Gateway bu yüzden `page_update`'te sayfayı önce okur, yaln
|
|
|
1337
1402
|
alanları değiştirip tam gövdeyi geri yazar (`layout_update` ve `component_update` de aynı).
|
|
1338
1403
|
Yine de `schema` parametresini elle doldurursan okuduğun hâli değil, **verdiğin liste** yazılır.
|
|
1339
1404
|
|
|
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
|
+
|
|
1340
1415
|
### Atomiklik: 500 KB'lık şemada tek komponente dokunmak
|
|
1341
1416
|
|
|
1342
1417
|
`page_schema_patch` şemanın tamamını göndermez — yalnız op'ları gönderir. Tam gövde ne LLM
|
|
@@ -1346,7 +1421,8 @@ ve geri yazar. Sözleşme (`PatchPageSchemaCommandHandler`):
|
|
|
1346
1421
|
| Aşama | Ne yapar |
|
|
1347
1422
|
|---|---|
|
|
1348
1423
|
| Kilit | Sayfa başına 60 sn'lik dağıtık kilit; başka bir aktör yazıyorsa istek `PageSchemaLockedException` ile döner (409) |
|
|
1349
|
-
| Sürüm | `baseVersion` verdiysen `UpdatedAt.Ticks` ile karşılaştırılır; tutmazsa `PageSchemaVersionConflictException` (409) ve **hiçbir op uygulanmaz** |
|
|
1424
|
+
| Sürüm | `baseVersion` verdiysen `UpdatedAt.Ticks` ile karşılaştırılır; tutmazsa `PageSchemaVersionConflictException` (409) ve **hiçbir op uygulanmaz** — bütün op'lar etkisizse hariç (aşağıdaki "Tekrar" satırı) |
|
|
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 |
|
|
1350
1426
|
| 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 |
|
|
1351
1427
|
| 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 |
|
|
1352
1428
|
| Doğrulama | Tam şema `PageSchemaValidator`'dan geçer (422 + alan bazlı `errors`) |
|
|
@@ -1355,7 +1431,18 @@ ve geri yazar. Sözleşme (`PatchPageSchemaCommandHandler`):
|
|
|
1355
1431
|
|
|
1356
1432
|
Yanıt üç alan döner: `applied` (uygulanan op sayısı), **`appliedPatch`** (her op'un şemada tam
|
|
1357
1433
|
olarak hangi JSON Pointer'a ne yaptığı — RFC 6902 biçiminde; "gerçekten yalnız o komponente mi
|
|
1358
|
-
dokunuldu" sorusunun kanıtı) ve **`newVersion`** (`UpdatedAt.Ticks`).
|
|
1434
|
+
dokunuldu" sorusunun kanıtı) ve **`newVersion`** (`UpdatedAt.Ticks`). Etkisiz op varsa `unchanged`
|
|
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.
|
|
1359
1446
|
|
|
1360
1447
|
> **`appliedPatch` gövdesi VARSAYILAN OLARAK iskelettir.** Girdi `{ op, path }` döner; eklenen
|
|
1361
1448
|
> düğüm `component` altında yalnız `id`/`elementId`/`name`/`type`/`children` taşır. Kanıt zaten
|
|
@@ -1375,12 +1462,29 @@ yamanın `baseVersion`'ıdır. Kontrol platformda atomiktir (satır kilidi + sü
|
|
|
1375
1462
|
`UPDATE`'te), yani iki çağrı arasına giren yazarı da yakalar. `baseVersion` vermezsen gateway yalnız
|
|
1376
1463
|
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
|
|
1377
1464
|
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.
|
|
1378
1471
|
Yanıttaki `touched`, kaydı değişen elementId'leri listeler (eklenen alt ağaç dâhil).
|
|
1379
1472
|
|
|
1380
1473
|
> **Büyük şemada çalışma sırası:** `mode:'summary'` ile ağacı çıkar (props yok, 500 KB'lık sayfada
|
|
1381
1474
|
> bile küçük) → hedefin `elementId`'sini al → gerekiyorsa `mode:'subtree'` ile yalnız o dalı oku →
|
|
1382
1475
|
> op'ları `page_schema_validate` ile kuru koştur → `page_schema_patch`. `mode:'full'` yalnız
|
|
1383
1476
|
> 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.
|
|
1384
1488
|
|
|
1385
1489
|
> **`remove_component`'in yan etkisi — tek istisna.** Sayfa kaydedilirken artık hiçbir komponent
|
|
1386
1490
|
> olayının, prop'unun ya da sayfa olayının referans vermediği akışlar platformca **kalıcı olarak
|
|
@@ -1491,7 +1595,9 @@ isimlerine bağlanır.
|
|
|
1491
1595
|
|
|
1492
1596
|
**Platform değişkenleri tek tek değil SET olarak tutar:** uygulama başına bir kayıt, sayfa başına
|
|
1493
1597
|
bir kayıt (`variable_create` `pageId` verirsen sayfa, vermezsen uygulama düzeyi). Kayıt zaten varsa
|
|
1494
|
-
create update'e döner. Şekil `[{ key, value }]`; `value` **herhangi bir JSON** olabilir
|
|
1598
|
+
create update'e döner. Şekil `[{ key, value, storage? }]`; `value` **herhangi bir JSON** olabilir.
|
|
1599
|
+
State **bellektedir** — sayfa her açıldığında `value`'dan başlar; `storage: 'device' | 'secure'` yalnız
|
|
1600
|
+
mobil uygulamada değeri cihazda saklar (`platform_guide('mobile')` §Kalıcı state, `MOB-014`):
|
|
1495
1601
|
|
|
1496
1602
|
```jsonc
|
|
1497
1603
|
variable_create({ applicationId, pageId, variables: [
|
|
@@ -1503,7 +1609,7 @@ variable_create({ applicationId, pageId, variables: [
|
|
|
1503
1609
|
- Uç seti **komple değiştirir**; gateway mevcut seti okuyup anahtar bazında birleştirir. Kasten
|
|
1504
1610
|
silmek için `replace: true`. `variable_delete` **setin tamamını** siler.
|
|
1505
1611
|
- Platform `data`'yı JSON **string** olarak saklar (`"[{\"key\":…}]"`); gateway çeviriyi iki yönde
|
|
1506
|
-
de yapar — `variable_list` sana `[{key, value}]` döndürür. Ham HTTP kullanıyorsan string
|
|
1612
|
+
de yapar — `variable_list` sana `[{key, value, storage?}]` döndürür. Ham HTTP kullanıyorsan string
|
|
1507
1613
|
zorunludur: gövdede yalnız `data` alanı okunur, `name`/`type`/`defaultValue` gibi alanlar
|
|
1508
1614
|
**sessizce yok sayılır** ve kayıt boş yazılır (istek yine 200 döner).
|
|
1509
1615
|
|
|
@@ -1529,25 +1635,6 @@ Tercih kuralı: *"bu değer başka bir değerden TÜRETİLİYORSA"* `set_binding
|
|
|
1529
1635
|
*"bir OLAY sonucunda bir kez yazılacaksa"* (uçtan veri çekme gibi) flow + setter kullan.
|
|
1530
1636
|
İkisini aynı prop'ta karıştırma — setter'ın yazdığı değeri canlı bağ bir sonraki tetikte ezer.
|
|
1531
1637
|
|
|
1532
|
-
**Designer'da da görünsün: varsayılan değer kur (2026-09-29).** Studio kanvası akış
|
|
1533
|
-
koşturmaz; `type:'code'` prop'larını tasarım anında `state.page.*` / `state.app.*`
|
|
1534
|
-
değişkenlerinin **varsayılan değerleriyle** çözer (Rexora dashboard: KPI'lar, grafikler ve
|
|
1535
|
-
metinler önce `{{ state.page… }}` ham metni olarak görünüyordu). Kural: tasarımcıya boş kutu
|
|
1536
|
-
bırakma, kanvasta da view'daki içeriğin aynısı görünsün.
|
|
1537
|
-
- Veriyi akışla (microservice → setter) yüklesen bile, bağlanan şeklin **gerçekçi bir
|
|
1538
|
-
örneğini** `variable_create` ile sayfa değişkeni olarak kur ve prop'u ona bağla — view'da akış
|
|
1539
|
-
değeri ezer, kanvasta örnek görünür.
|
|
1540
|
-
- Kanvasta çözülmeyen ifadeler: `item.*` (repeater satırı), `Functions.*`, komponent adları ve
|
|
1541
|
-
`Steps.*`. Bunları taşıyan prop'a `data` alanında tasarım değeri ver (metin olmayan prop'larda
|
|
1542
|
-
kanvas `data`'yı çizer); metin prop'u çözülmeyen ifadeyi ipucu olarak gösterir, bu yüzden
|
|
1543
|
-
metni mümkünse `state.page` üzerinden besle (`{{ state.page.summary.totalText }}`).
|
|
1544
|
-
- `repeater`'ın `rows`'u statik ya da `state.page`'e bağlı olsun; kanvas tek satırı şablon
|
|
1545
|
-
olarak çizer.
|
|
1546
|
-
- Yer tutucu boşluk için BOŞ `container` kurma, `spacer` kullan. Boş kap kanvasta bırakma
|
|
1547
|
-
alanı olarak ~130px yükseklik alır ve bulunduğu satırı şişirir (Rexora New Order: tablo
|
|
1548
|
-
başlık satırı designer'da 148px, view'da 38px). Satırda yatay boşluk: `spacer` +
|
|
1549
|
-
`mode:'fixed'` + `size: 0` + `appearance.widthType:'fixed'` / `widthString:'32px'`.
|
|
1550
|
-
|
|
1551
1638
|
**`stateBindings[]` (şema düğümündeki dizi)** Studio'nun state-bağımlılık özelliğidir:
|
|
1552
1639
|
`[{ name, expression, targets: [{ elementId, elementProperty }] }]` — bir ifade değişince
|
|
1553
1640
|
listedeki hedef prop'lara yazılır. Micro-op sözlüğünde karşılığı YOKTUR; yalnız
|
|
@@ -1824,15 +1911,24 @@ page_container
|
|
|
1824
1911
|
```
|
|
1825
1912
|
start → [setter] btn.isLoading = true, btn.isDisabled = true, notification gizle
|
|
1826
1913
|
→ [microservice] sign-in (POST; email + password body'den)
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1914
|
+
├─ error → [setter] btn.isLoading=false, btn.isDisabled=false,
|
|
1915
|
+
│ notification.content =
|
|
1916
|
+
│ { type:'code', ref:'Steps.signIn.error?.message ?? "Giriş başarısız"' }
|
|
1917
|
+
└─ always → [condition] !!Steps.signIn.data.token
|
|
1918
|
+
├─ always → [setter] buton durumunu sıfırla
|
|
1919
|
+
├─ if → [setcookie] { name:'APP_Token', value:'Steps.signIn.data.token',
|
|
1920
|
+
│ expiresInHours: 240 }
|
|
1921
|
+
│ → [redirect] hedef sayfaya
|
|
1922
|
+
└─ else → [setter] notification.content =
|
|
1923
|
+
{ type:'code', ref:'Steps.signIn.error?.message ?? "Giriş başarısız"' }
|
|
1834
1924
|
```
|
|
1835
1925
|
|
|
1926
|
+
- **`sign-in` adımının `error` dalı burada ZORUNLUDUR, süs değil.** Dal bağlı değilken bu şablonun
|
|
1927
|
+
`condition`'ı `Steps.signIn.data.token`'ı okur ve gateway'i **FLOW-028** ile uyarır (yukarıdaki
|
|
1928
|
+
"Hangi yolu seçeceksin" notu): hata anında `data` `null`'dur, token okuması sessizce `undefined`
|
|
1929
|
+
döner. Dal bağlanınca hata onun üzerinden sürer — `always`/`condition` yalnız BAŞARIDA çalışır,
|
|
1930
|
+
yani `data.token` orada gerçek bir iş kuralıdır (uç 200 dönüp token'sız yanıt verirse), hata
|
|
1931
|
+
algılama YÖNTEMİ değil.
|
|
1836
1932
|
- **Cookie adı middleware'in okuduğu adla birebir aynı olmalı** (`cookie.APP_Token` —
|
|
1837
1933
|
`platform_guide('middleware')` Tarif 1). Uyuşmazlık sessizce "hep 401" demektir.
|
|
1838
1934
|
- `redirect` adımı `isRaw: true` iken `path` **çok satırlı JS bloğudur** (son ifade değeri döner) —
|
|
@@ -2022,9 +2118,14 @@ hiçbiri** bağlı değildi; üç portalın da rol menüsü boş çıkıyor, pan
|
|
|
2022
2118
|
> (`dto_get` ile bak: genelde `role`, `role_name`, `roles_csv` vardır). Sayfa tarafında CSV
|
|
2023
2119
|
> kullan — ayrıntı ve şablon `platform_guide('expressions')` §2.
|
|
2024
2120
|
>
|
|
2025
|
-
> **Uç hata dönerse `.data`
|
|
2026
|
-
>
|
|
2027
|
-
> `(items ?? []).map is not a function
|
|
2121
|
+
> **Uç hata dönerse `.data` NULL'dur, hata gövdesi değil (ADR 0004, 2026-09-26).** 2026-09-26'ya
|
|
2122
|
+
> kadar `Steps.x.data` 401/404 sonrası hata gövdesiydi ve `rows || []` bunu yakalamıyordu (nesne
|
|
2123
|
+
> truthy) → `rows.filter is not a function` / `(items ?? []).map is not a function`; artık uç hata
|
|
2124
|
+
> dönünce `data` **null**'dur ve bu adım boş veriyle koşar — `rows` gibi bir listeye bağlarsan
|
|
2125
|
+
> bileşen `null`'ı boş liste sayar, `Array.isArray(...) ? ... : []` sarmalamaya artık gerek yok.
|
|
2126
|
+
> Hata OLDUĞUNU fark etmeden geçmemek için `error` dalı bağlayın (yukarıdaki §"4xx de hatadır",
|
|
2127
|
+
> gateway bunu bağlı değilken **FLOW-028** ile uyarır); hata gövdesini görmek istiyorsan
|
|
2128
|
+
> `Steps.x.error.body`'yi okuyun.
|
|
2028
2129
|
|
|
2029
2130
|
## ⚠️ `page_schema_patch` `html` komponentini reddediyor — katalogda mükerrer kayıt (2026-08-19)
|
|
2030
2131
|
|
|
@@ -2087,6 +2188,31 @@ micro-op hattına dönün.
|
|
|
2087
2188
|
> uyarı yoktu. Silinmesini bilerek istiyorsanız çağrıyı `allowFlowDeletion: true` ile tekrarlayın;
|
|
2088
2189
|
> yanıt `deletedFlows` ile hangi akışların gittiğini listeler.
|
|
2089
2190
|
>
|
|
2191
|
+
> **Silinen akış geri kurulabilir (2026-09-26, ZM-27).** Sayfa kaydının sildiği akış artık revizyon
|
|
2192
|
+
> defterine `operation: delete` satırı olarak düşer (kaynağı `studio` ya da `mcp`). `flow_restore`
|
|
2193
|
+
> akışı son revizyonundaki ad, slug ve adımlarla AYNI id ile yeniden kurar; olaya bağlamaz —
|
|
2194
|
+
> geri geldikten sonra `set_event`. İki sınır: revizyon saklama süresi (budanan akış 404) ve
|
|
2195
|
+
> adımların hedeflediği komponentler — akış bir komponenti tetikleyen/parametre olarak
|
|
2196
|
+
> gösteriyorsa o komponent şemada durmalıdır (canlı ölçüldü: `flow_restore` "Trigger Element Id"
|
|
2197
|
+
> dış anahtarına çarpar).
|
|
2198
|
+
>
|
|
2199
|
+
> **Boşalan sayfa: `page_restore` (2026-09-26).** Sayfayı ve akışlarını birlikte geri kurar:
|
|
2200
|
+
> `revision_list(module: 'page', recordId: <pageId>)` → boşalmadan önceki revizyonu bul (`source` ve
|
|
2201
|
+
> `correlationId` yardım eder; `revision_get` ile içeriğine bak) → `page_restore({ revisionNo })`.
|
|
2202
|
+
> Platform önce eksik akışları adımsız kurar, sonra şemayı eski komponent id'leriyle yazar, sonra
|
|
2203
|
+
> adımları yazar — akış→komponent ve olay→akış dış anahtarları bu sırayla tek transaction'da çözülür.
|
|
2204
|
+
> Yanıt `restoredFlows` ve `deletedFlows` (N'den sonra bağlanmış, şimdi yetim kalan) döner.
|
|
2205
|
+
> Revizyonu kalmamış bir akış varsa 409 ve hiçbir şey yazılmaz.
|
|
2206
|
+
>
|
|
2207
|
+
> **Doğru revizyonu seç.** Şemayı yüklemeyen komutların (`UpdateProjectCommand`,
|
|
2208
|
+
> `UpdateApplicationCommand`…) yazdığı sayfa revizyonları komponent taşımaz; komponenti olan sayfayı
|
|
2209
|
+
> böyle bir revizyona döndürmek 409 `PageRevisionEmptyException` ile reddedilir (bilerek boşaltmak için
|
|
2210
|
+
> `allowEmpty: true`). `correlationId`'si `PatchPageSchemaCommand` ya da `UpdatePageCommand` olan
|
|
2211
|
+
> revizyonu seç. İki sınır daha: N'den beri silinen layout/rol/middleware/özel komponent ya da başka
|
|
2212
|
+
> sayfanın aldığı slug geri yüklemeyi dış anahtar/benzersizlik hatasıyla düşürür (transaction geri
|
|
2213
|
+
> 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
|
|
2214
|
+
> geri kurulmaz — onlar için `flow_restore`.
|
|
2215
|
+
>
|
|
2090
2216
|
> **FLOW-018 artık silinen düğümün ALT AĞACINI da görüyor.** Eskiden yalnız op'un kendi
|
|
2091
2217
|
> `target`'ına bakılıyordu: bir kapsayıcı silinince ÇOCUĞUNA yazan setter sessizce kopuyor ve
|
|
2092
2218
|
> uyarı hiç çıkmıyordu (09-05, `sign_in_form` → `btn_sign_in`).
|
|
@@ -2130,6 +2256,9 @@ micro-op hattına dönün.
|
|
|
2130
2256
|
style + Kural 1h deseniyle yeniden kurulunca kart 400px'e ve ortaya oturdu. Gateway bunu **PAGE-014 (uyarı)** ile
|
|
2131
2257
|
yanıtın `layoutWarnings` alanında bildirir. **Düzeni `style` ile kurmaya hiç kalkışma:**
|
|
2132
2258
|
ortalama/yaslama/aralık işi kapsayıcının kendi `layout: 'flex'` prop grubuna aittir (Kural 1f-2).
|
|
2259
|
+
**İstisna `html`:** onun `style`'ı yazarın işaretlemesine kapsamlı giren CSS metnidir (web'de iç
|
|
2260
|
+
seçicili sınıf, mobilde belgenin stil bloğu) — string asıl biçimdir ve PAGE-014 onda susar. Mobilde
|
|
2261
|
+
`html`'e nesne `style` verme: çizilmez (MOB-002).
|
|
2133
2262
|
- **Menüde "bulunduğun sayfa" vurgusu: `sidebar`/`layout`'ta `activeHref`, `header`'da
|
|
2134
2263
|
`activeNavHref`.** `sidebar` ve `layout` menü ağacını ortak renderer'la çizer: `activeHref` boşken
|
|
2135
2264
|
tarayıcıdaki adrese uyan satırı kendileri vurgular, prop yazılırsa o satır vurgulanır (akıştan
|
|
@@ -47,7 +47,10 @@ Değişkenlerin tam listesi ve o projedeki değerleri: `theme_get(view:'resolved
|
|
|
47
47
|
sırası bellidir: projenin tamamı için tema token'ı (`theme_update`), tekrar eden bir kalıp için
|
|
48
48
|
adlı preset (`presets` + `style.$preset`), yalnız o düğüme özgü karar için düğümün kendi
|
|
49
49
|
`style`'ı. Sabit hex yazmak yerine `var(--ng-accent-primary)` yazmak, düğümü temaya BAĞLI
|
|
50
|
-
tutar.
|
|
50
|
+
tutar. **Adı uydurmayın:** geçerli adlar temanın yaydığı değişkenlerdir (`theme_get({ view: 'resolved' })`'in `cssVars`'ı;
|
|
51
|
+
yüzeyler `--ng-background-surface`, `--ng-background-surface-alt`, `--ng-background-canvas`). Mobil
|
|
52
|
+
çizici yalnız bunları çözer; `var(--ng-surface)` gibi tanımsız bir ad cihazda saydam kalır ve iOS
|
|
53
|
+
gölgesi içeriğe düşer (THEME-012 uyarısı).
|
|
51
54
|
|
|
52
55
|
**2. Marka rengi tek çağrıdır.** `theme_update({ palette: { accent: { primary, hover } } })`
|
|
53
56
|
sayfadaki her butonu, odak halkasını, seçili satırı ve grafik serisini birden çevirir. Komponent
|
|
@@ -98,7 +101,10 @@ theme_update({ theme: {
|
|
|
98
101
|
```
|
|
99
102
|
|
|
100
103
|
**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).
|
|
104
|
+
fontu ADIYLA Google'dan çeker, tanınmayan ad sessizce sans-serif'e düşer (THEME-008). Mobilde de
|
|
105
|
+
aynı kural geçerlidir: cihaz aynı adı Google Fonts'tan TTF olarak indirip `expo-font` ile yükler
|
|
106
|
+
(400 ve 700 kalınlık) — Android'de kalın yüz SENTETİKTİR (iOS gerçek kalın dosyayı çizer,
|
|
107
|
+
ZM-10, 2026-09-26).
|
|
102
108
|
|
|
103
109
|
```jsonc
|
|
104
110
|
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 runtime (
|
|
211
|
+
- Mobil uygulama runtime'ı (`@ng-apps/ui-native`, Expo) web ile aynı sözlüğü ve motoru kullanır (2026-09-25, plans/mobil-coklu-dil): `language-selector` mobil katalogda, cihazda dil sırası uygulama içi seçim → kayıtlı seçim → cihaz dili → varsayılan (`?lang` yalnız `/preview`'da), seçim uygulama çapında ve kalıcı, sekme etiketi `t:<anahtar>`, `X-Data-Language` sonraki isteklerle gider. Ayrıntı `platform_guide('mobile')` §Çok dil.
|
|
212
212
|
|
|
213
213
|
## Backend doğrulama sınırları (TR-001)
|
|
214
214
|
|
|
@@ -651,9 +651,15 @@ Tam örnek, ölçülen çıktı şekli ve `code` çocuğu tuzağının çıkış
|
|
|
651
651
|
|
|
652
652
|
```js
|
|
653
653
|
// dizi (isSingle:false) · nesne (isSingle:true) · düz değer (yalnız pk dönen yazma)
|
|
654
|
-
(
|
|
654
|
+
(x.data && typeof x.data !== 'string' && typeof x.data.length === 'number' ? (x.data[0] && x.data[0].id) : (x.data && x.data.id !== undefined ? x.data.id : x.data))
|
|
655
655
|
```
|
|
656
656
|
|
|
657
|
+
Diziyi `Array.isArray` ile değil `.length` ile tanıyın: 2026-09-27'den önceki backend'de tablo
|
|
658
|
+
adımının listesi Jint'e sarılı bir CLR nesnesi olarak iniyordu ve `Array.isArray(x.data)` `false`
|
|
659
|
+
dönüyordu — koşuda (2026-09-24) giriş akışı bu yüzden her kullanıcıyı 401 ile reddetti
|
|
660
|
+
(`zeyrek-backend/docs/incident-log.md` #89). `.length`, `.map`, `.filter` o sürümde de çalışıyordu;
|
|
661
|
+
düzeltilmiş backend'de `Array.isArray` de doğrudur.
|
|
662
|
+
|
|
657
663
|
Şekli bilmiyorsan bu yazımı kullan; `workflow_preview` çıktısında `steps[].output`'a bakarak
|
|
658
664
|
hangi vakada olduğunu da görebilirsin.
|
|
659
665
|
|