@appaflytech/zeyrek-ai-mcp 0.0.5 → 0.0.7
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 +2 -2
- package/.env.production.example +9 -1
- package/README.md +14 -38
- package/dist/config.js +36 -3
- package/dist/knowledge/backendConstraints.js +982 -0
- package/dist/knowledge/componentCatalog.js +549 -92
- package/dist/knowledge/componentEvents.js +120 -25
- package/dist/knowledge/coverage.js +43 -0
- package/dist/knowledge/flowGuards.js +30 -0
- package/dist/knowledge/functionGuards.js +134 -0
- package/dist/knowledge/guideSections.js +49 -0
- package/dist/knowledge/hydrate.js +97 -0
- package/dist/knowledge/languageCodes.js +36 -0
- package/dist/knowledge/languages.js +105 -0
- package/dist/knowledge/layoutSummary.js +10 -0
- package/dist/knowledge/localization.js +51 -0
- package/dist/knowledge/normalize.js +500 -16
- package/dist/knowledge/outlines.js +167 -12
- package/dist/knowledge/policy.js +14 -5
- package/dist/knowledge/propTypes.js +80 -0
- package/dist/knowledge/rules.js +961 -44
- package/dist/knowledge/schemaGuard.js +199 -0
- package/dist/knowledge/styleResolve.js +63 -4
- package/dist/observability/trace.js +27 -3
- package/dist/platform/csv.js +123 -0
- package/dist/platform/errors.js +107 -6
- package/dist/platform/http.js +34 -4
- package/dist/platform/patch.js +27 -0
- package/dist/platform/refs.js +104 -0
- package/dist/platform/responses.js +25 -6
- package/dist/platform/screenshot.js +544 -16
- package/dist/platform/secrets.js +40 -0
- package/dist/platform/tokenVault.js +89 -0
- package/dist/platform/writeDiff.js +281 -0
- package/dist/resources/examples/flow-call-function.json +66 -0
- package/dist/resources/examples/function-total.json +70 -0
- package/dist/resources/examples/layout-app-shell.json +1 -1
- package/dist/resources/examples/microfunction-node-sum.json +56 -0
- package/dist/resources/examples/microservice-table-list.json +2 -4
- package/dist/resources/examples/page-dynamic-form.json +3 -3
- package/dist/resources/examples/page-flex-sections.json +99 -0
- package/dist/resources/examples/page-sign-in.json +4 -3
- package/dist/resources/guides/component.md +81 -8
- package/dist/resources/guides/entity.md +712 -20
- package/dist/resources/guides/expressions.md +47 -2
- package/dist/resources/guides/external-component.md +9 -0
- package/dist/resources/guides/functions.md +262 -0
- package/dist/resources/guides/getting-started.md +82 -7
- package/dist/resources/guides/layout.md +53 -10
- package/dist/resources/guides/merge.md +231 -0
- package/dist/resources/guides/microfunction.md +166 -0
- package/dist/resources/guides/microservice.md +287 -15
- package/dist/resources/guides/middleware.md +89 -1
- package/dist/resources/guides/modify-existing.md +23 -0
- package/dist/resources/guides/page.md +402 -49
- package/dist/resources/guides/translation.md +150 -8
- package/dist/resources/guides/view.md +16 -1
- package/dist/resources/guides/workflow.md +199 -28
- package/dist/resources/knowledge.js +5 -0
- package/dist/resources/rules.js +27 -0
- package/dist/resources/schema-fingerprint.json +8 -0
- package/dist/resources/schemas/AnalyzeImportQuery.json +51 -0
- package/dist/resources/schemas/ApplyMergePlanCommand.json +19 -0
- package/dist/resources/schemas/CreateBulkRowCommand.json +36 -0
- package/dist/resources/schemas/CreateDatasourceCommand.json +15 -6
- package/dist/resources/schemas/CreateDiscoveredEntitiesCommand.json +19 -8
- package/dist/resources/schemas/CreateEntityCommand.json +52 -12
- package/dist/resources/schemas/CreateEnvironmentCommand.json +31 -0
- package/dist/resources/schemas/CreateGlobalFunctionCommand.json +95 -0
- package/dist/resources/schemas/CreateImportPlanCommand.json +278 -0
- package/dist/resources/schemas/CreateMergePlanCommand.json +34 -0
- package/dist/resources/schemas/CreateMicrofunctionCommand.json +117 -0
- package/dist/resources/schemas/CreateMicrofunctionRuntimeCommand.json +51 -0
- package/dist/resources/schemas/CreateMicroserviceCommand.json +145 -3
- package/dist/resources/schemas/CreateQueryCommand.json +56 -3
- package/dist/resources/schemas/CreateRowCommand.json +38 -0
- package/dist/resources/schemas/CreateViewCommand.json +13 -10
- package/dist/resources/schemas/CreateWorkflowCommand.json +106 -14
- package/dist/resources/schemas/DataJobDto.json +267 -0
- package/dist/resources/schemas/ExportRowsCommand.json +172 -0
- package/dist/resources/schemas/Filter.json +3 -1
- package/dist/resources/schemas/GetRowsQuery.json +6 -1
- package/dist/resources/schemas/GlobalFunctionDto.json +89 -0
- package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +249 -0
- package/dist/resources/schemas/ImportAnalysisDto.json +401 -0
- package/dist/resources/schemas/ImportPlanDto.json +260 -0
- package/dist/resources/schemas/ImportSampleDto.json +90 -0
- package/dist/resources/schemas/InvokeMicrofunctionCommand.json +25 -0
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +135 -1
- package/dist/resources/schemas/PreviewQueryCommand.json +5 -2
- package/dist/resources/schemas/PreviewWorkflowCommand.json +45 -9
- package/dist/resources/schemas/ResolveMergeConflictsCommand.json +58 -0
- package/dist/resources/schemas/RevertMergePlanCommand.json +19 -0
- package/dist/resources/schemas/RunImportCommand.json +62 -0
- package/dist/resources/schemas/StepDto.json +34 -3
- package/dist/resources/schemas/UpdateBulkRowCommand.json +36 -0
- package/dist/resources/schemas/UpdateDatasourceCommand.json +15 -6
- package/dist/resources/schemas/UpdateEntityCommand.json +52 -11
- package/dist/resources/schemas/UpdateGlobalFunctionCommand.json +66 -0
- package/dist/resources/schemas/UpdateMicrofunctionCommand.json +121 -0
- package/dist/resources/schemas/UpdateMicrofunctionRuntimeCommand.json +54 -0
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +147 -4
- package/dist/resources/schemas/UpdateQueryCommand.json +13 -3
- package/dist/resources/schemas/UpdateRowCommand.json +40 -0
- package/dist/resources/schemas/UpdateViewCommand.json +15 -10
- package/dist/resources/schemas/UpdateWorkflowCommand.json +106 -14
- package/dist/server.js +17 -1
- package/dist/tools/access.js +3 -3
- package/dist/tools/activities.js +40 -0
- package/dist/tools/applications.js +1 -1
- package/dist/tools/automations.js +76 -34
- package/dist/tools/common.js +55 -0
- package/dist/tools/components.js +16 -7
- package/dist/tools/datasources.js +83 -21
- package/dist/tools/dependencies.js +1 -1
- package/dist/tools/deployments.js +34 -2
- package/dist/tools/dtos.js +25 -12
- package/dist/tools/entities.js +113 -28
- package/dist/tools/environments.js +52 -0
- package/dist/tools/externalComponents.js +9 -3
- package/dist/tools/files.js +57 -42
- package/dist/tools/flows.js +205 -13
- package/dist/tools/folders.js +7 -2
- package/dist/tools/functions.js +331 -0
- package/dist/tools/globalFunctions.js +63 -0
- package/dist/tools/importSchemas.js +79 -0
- package/dist/tools/imports.js +241 -0
- package/dist/tools/layouts.js +103 -29
- package/dist/tools/merges.js +113 -0
- package/dist/tools/microfunctions.js +155 -0
- package/dist/tools/microservices.js +270 -40
- package/dist/tools/organizations.js +5 -6
- package/dist/tools/pages.js +421 -104
- package/dist/tools/platformInfo.js +155 -11
- package/dist/tools/projects.js +183 -33
- package/dist/tools/queries.js +32 -10
- package/dist/tools/revisions.js +94 -0
- package/dist/tools/rows.js +484 -50
- package/dist/tools/screenWrite.js +68 -0
- package/dist/tools/screens.js +28 -0
- package/dist/tools/templates.js +32 -5
- package/dist/tools/translations.js +24 -8
- package/dist/tools/views.js +20 -10
- package/dist/tools/workflows.js +56 -21
- package/package.json +7 -2
|
@@ -78,9 +78,30 @@ mümkündür ama doğrulama duvarı ve canlı canvas yalnız `page_schema_patch`
|
|
|
78
78
|
her turda çözümlenmiş metinle EZER — anahtar yalnız `ref`'te yaşar, `data`'ya yazıp
|
|
79
79
|
güvenme (`code` prop'uyla aynı davranış). Tam şekil, fallback zinciri ve `translation_*`
|
|
80
80
|
tool'ları için `platform_guide('translation')`.
|
|
81
|
+
- **Kurulmuş bir düğümün prop TİPİNİ `set_prop_type` micro-op'u değiştirir.**
|
|
82
|
+
`{ op: 'set_prop_type', target: '<elementId>', prop: 'content', propType: 'translation', ref: 'dashboard.kpi.total' }`
|
|
83
|
+
bir `static` prop'u çeviriye, `propType: 'code'` + `ref: '<ifade>'` koda, `propType: 'static'` +
|
|
84
|
+
`data: <değer>` sabite bağlar. Bu bir **gateway emülasyonudur**: `replace_prop` gönderilen ham
|
|
85
|
+
değeri her zaman `static` Prop'una sarar ve sarmalanmış Prop nesnesini reddeder, yani prop tipini
|
|
86
|
+
yazamaz. Op olmadan tek yol düğümü `remove_component` + `add_component` ile yeniden kurmaktı;
|
|
87
|
+
2026-09-06 koşusunda on bir etiket bu yolla kuruldu ve onlara yazan **dokuz setter iteratee'si**
|
|
88
|
+
platform tarafından sessizce silindi (üç KPI kartı boş kaldı). Taşıyıcı alan tipe göre değişir —
|
|
89
|
+
`static` değeri `data`'da, `code` ve `translation` `ref`'te taşır; eksik taşıyıcı istek
|
|
90
|
+
gönderilmeden reddedilir ve `page_schema_validate` aynı kararı verir.
|
|
91
|
+
|
|
81
92
|
- **`blocks[].size`, komponentin `component_get`'teki `maxSize`'ını aşamaz.** Dikkat: katalog
|
|
82
93
|
varsayılanı aşabiliyor (`page-header` default `h:8`, `maxSize` `h:4`) — varsayılanı körü körüne
|
|
83
94
|
kopyalama, doğrulayıcı `"Height of 'page-header' must be between 1 and 4."` ile reddeder.
|
|
95
|
+
- **Kurulmuş bir düğümün boyutunu `resize_component` micro-op'u değiştirir.**
|
|
96
|
+
`{ op: 'resize_component', target: '<elementId>', size: { w, h } }` ızgara boyutunu,
|
|
97
|
+
`{ …, appearance: { heightType: 'fixed', heightString: '340px' } }` flex ölçüsünü yazar; ikisi
|
|
98
|
+
aynı op'ta verilebilir, `breakpoint` varsayılanı 1024'tür. Bu bir **gateway emülasyonudur**:
|
|
99
|
+
platformun micro-op sözlüğünde boyut yoktur ve `move_component` gövdesine konan `size` 200 dönüp
|
|
100
|
+
SESSİZCE düşer (bu yüzden gateway artık onu reddeder ve buraya yönlendirir). Op şemayı okuyup
|
|
101
|
+
sayfayı tam gövdeyle geri yazar. Ebeveynin düzeni yazdığın alanı etkisiz kılıyorsa (flex kabın
|
|
102
|
+
içine `size`, ızgaranın içine `appearance`) yanıt `PAGE-019` uyarısı taşır — istek yine geçer.
|
|
103
|
+
**Düğümü silip yeniden kurmayın:** o yol ona yazan akış setter'larını sessizce öldürür
|
|
104
|
+
(`FLOW-018`, aşağıda Kural 2).
|
|
84
105
|
- **Aynı ızgara hücrelerini iki komponente veremezsin.** Studio'da komponent tuvale bırakıldığında
|
|
85
106
|
çakışan kardeşleri aşağı itme işini studio-api'nin sayfa kurma servisi yapar
|
|
86
107
|
(`SchemaHelper.reorderComponents` → `draggableElement.moveItem`); komple şema yazan `page_create`
|
|
@@ -189,14 +210,15 @@ Adım gövdesi `StepManagementSchema`: `{ stepId, name, type, kind, args, branch
|
|
|
189
210
|
**`branches[].nextStepId` bir GUID değil, hedef adımın `stepId` STRING'idir**
|
|
190
211
|
(`allSteps.TryGetValue(b.NextStepId)`).
|
|
191
212
|
|
|
192
|
-
Bu adımda platformun sessizce yuttuğu
|
|
213
|
+
Bu adımda platformun sessizce yuttuğu altı tuzak var — hepsi isteği 200 döndürür, akış yine de
|
|
193
214
|
ölü ya da yarım çalışır. Gateway hepsini yakalar (FLOW-004…012), ama şekli baştan doğru yazın:
|
|
194
215
|
|
|
195
216
|
**1. Dal adı motorun anahtarıdır, etiket değil.** Runtime dal kimliğini `branch.name`'den üretir
|
|
196
217
|
(`Runtime.svelte:329`) ve her adım `engine.next('always')` çağırır. Ad `always` değilse motor
|
|
197
218
|
dalı bulamaz ve akışı **sessizce durdurur** (`flow-engine.ts:79`); Studio da zinciri
|
|
198
219
|
`sourceBranch === 'always'` ile çizdiği için panelde **Start kartından sonrası boş görünür**.
|
|
199
|
-
İstisnalar: `condition` → dal adı rule id'sidir
|
|
220
|
+
İstisnalar: `condition` → dal adı rule id'sidir (ve o id bir **GUID**'dir — aşağıdaki tuzak 6),
|
|
221
|
+
`confirm` → `yes|no|always`, `microservice` →
|
|
200
222
|
`always` (eski akışlarda `success` de çalışır).
|
|
201
223
|
|
|
202
224
|
**2. `iteratees[].type` yalnız `change` | `fill`.** `setter.ts` başka değerde hiçbir dala
|
|
@@ -226,6 +248,37 @@ key'ini düz anahtar ver, iç içe yolu `ref`'e yaz: `"parent_name": { "type": "
|
|
|
226
248
|
anahtar her satırda taşınır. `type` sözlüğü: `item` (kaynak alanı), `code` (satır başına JS,
|
|
227
249
|
satır `Row` değişkenindedir), diğerleri sabit.
|
|
228
250
|
|
|
251
|
+
**6. `condition` adımının gövdesi `args.rules`'tur — backend workflow'unun `rule.items` şekli
|
|
252
|
+
DEĞİL.** Sayfa akışını başka bir motor koşar (`ng-apps-flow/tasks/condition/condition.ts`) ve o
|
|
253
|
+
motor yalnız şu sözleşmeyi tanır. Workflow şekli yazılırsa istek 200 döner, adım kaydedilir,
|
|
254
|
+
Studio çizer ve **kural hiç değerlendirilmez** — akış dalsız kalır. Gateway `FLOW-020` ile
|
|
255
|
+
yakalar.
|
|
256
|
+
|
|
257
|
+
```jsonc
|
|
258
|
+
{ "stepId": "guard", "name": "Token var mı", "type": "condition", "kind": "normal",
|
|
259
|
+
"args": { "rules": [
|
|
260
|
+
{ "id": "0198e2a1-4c31-7a10-9b44-1f0c5d2e6a01", "expression": "!!Steps.signIn.data.token", "type": "if" },
|
|
261
|
+
{ "id": "0198e2a1-4c31-7a10-9b44-1f0c5d2e6a02", "expression": "", "type": "else" } ] },
|
|
262
|
+
"branches": [ { "id": "<GUID>", "name": "0198e2a1-4c31-7a10-9b44-1f0c5d2e6a01", "nextStepId": "go_home" },
|
|
263
|
+
{ "id": "<GUID>", "name": "0198e2a1-4c31-7a10-9b44-1f0c5d2e6a02", "nextStepId": "show_error" },
|
|
264
|
+
{ "id": "<GUID>", "name": "always", "nextStepId": "hide_spinner" } ] }
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
> Dal adları okunabilir değil, **kuralın GUID'inin kendisi** — `branches[].name === rules[].id`.
|
|
268
|
+
> Okunabilir ad iki uçta birden tutmaz (aşağıdaki tabloda ilk satır).
|
|
269
|
+
|
|
270
|
+
| Kural | Neden | Kaynak |
|
|
271
|
+
|---|---|---|
|
|
272
|
+
| **`rules[].id` GERÇEK bir GUID olmalı** | Backend alanı `Guid`'e çevirir; `"ok"` gibi okunabilir bir ad isteği `The JSON value could not be converted to System.Guid. Path: $.flow.steps[N].args.rules[0].id` ile reddeder. Dal adı da aynı GUID olduğu için iki yerde birden okunabilir ad kullanamazsınız | `StepManagementSchema.cs` `StepManagementRule.Id` |
|
|
273
|
+
| **`id`'yi hiç vermemek dalı sessizce ÖLDÜRÜR** | Alan boşsa backend `Guid.CreateVersion7()` ile kendi GUID'ini üretir; yazdığınız `branches[].name` ona asla eşleşmez, istek 200 döner ve dal hiç koşmaz. Her kural için taze GUID üretip iki yere de aynısını yazın | `StepManagementSchema.cs:549` varsayılan değer |
|
|
274
|
+
| **İlk kural `type:'if'` olmak ZORUNDA** | Motor zinciri yalnız `rules[0].type === 'if'` iken başlatır; değilse adım hiçbir dala girmez ve akış sessizce biter | `condition.ts` son blok |
|
|
275
|
+
| **Dal adı kuralın `id`'sidir** | `engine.next(rule.id)` → `Runtime.svelte:330` `branch.name`'i `branch.id`'ye çevirir → `flow-engine.ts:93` dalı adıyla arar. Her `rules[].id` için aynı adlı bir `branches[]` girdisi olmalı | `condition.ts` |
|
|
276
|
+
| **`else` yalnız `expression` BOŞKEN fallback'tir** | Koşul `!rule.expression && rule.type === 'else'`; dolu `else` normal karşılaştırmaya döner ve hiçbir kural tutmazsa akış dalsız biter | `condition.ts` |
|
|
277
|
+
| **Zincir dizi SIRASIYLA yürür** | Tutmayan kural `rules[index + 1]`'e geçer — `else-if` sırası diziden gelir, `order` alanından değil | `condition.ts` `process()` |
|
|
278
|
+
| `type` kümesi `if` · `else-if` · `else` | `ConditionArgumentRuleType` | `condition.types.ts` |
|
|
279
|
+
| **`always` YALNIZ bir dal eşleştiğinde koşar** | Motor `always`'i eşleşen dalın `completed`'ından çağırır (boş ifadeli `else` dalında ayrıca `stopped`'ta da). `rules` boşsa, `rules[0].type !== 'if'` ise ya da hiçbir ifade tutmayıp fallback `else` yoksa `engine.next('always')` **hiç çağrılmaz** — ayrıntı ve tuzağı için aşağıdaki §"Condition adımı `always` dalını…" | `condition.ts:55-61` |
|
|
280
|
+
| `branches` nesne biçimini de kabul eder | Dizi yerine `{ "<dal adı>": "<nextStepId>" }` yazılabilir; motor ikisini de aynı `{ id, nextStepId }` şekline eşler. Dizi biçimini tercih edin — `branches[].id` alanını orada verebiliyorsunuz | `Runtime.svelte` `mapStepBranches` |
|
|
281
|
+
|
|
229
282
|
```jsonc
|
|
230
283
|
// akışı başlatan adım — dal adı 'always' olmak zorunda
|
|
231
284
|
{ "stepId": "start", "name": "Start", "type": "start", "kind": "normal", "args": {},
|
|
@@ -259,6 +312,16 @@ satır `Row` değişkenindedir), diğerleri sabit.
|
|
|
259
312
|
> göndermeden reddeder. `element` değerini `page_schema_get` çıktısındaki `elementId` ile doğrula,
|
|
260
313
|
> uydurma.
|
|
261
314
|
|
|
315
|
+
> **DOLU ama var olmayan `element` FLOW-017'nin KAPSAMI DIŞINDADIR — onu FLOW-024 söyler.**
|
|
316
|
+
> FLOW-017 yalnız alanın boş olduğunu görür; henüz kurulmamış bir düğümün id'sini yazarsan alan
|
|
317
|
+
> dolu görünür, kural susar ve platform `element`i **null** kaydeder — sonuç aynıdır: adım koşar,
|
|
318
|
+
> hiçbir şey yazmaz (ölçüm: 2026-09-09 koşusu `S-14`, `search_hint` düğümü akıştan sonra
|
|
319
|
+
> kurulmuştu). Gateway `flow_create`/`flow_update`/`flow_patch` sırasında barındırıcının şemasını
|
|
320
|
+
> okuyup hedefi arar ve bulamazsa **FLOW-024 (uyarı)** düşürür; yazmayı durdurmaz, çünkü "önce
|
|
321
|
+
> akışı kur, sonra düğümü" meşru bir sıradır. Doğru sıra: düğümü `page_schema_patch add_component`
|
|
322
|
+
> ile kur, sonra akışı `flow_update` ile **aynı gövdeyle** yeniden kaydet — kaydedilen `element`
|
|
323
|
+
> null olduğu için `flow_patch`'in `[element=…]` seçicisi onu bulamaz.
|
|
324
|
+
|
|
262
325
|
Satır eşlemeli tablo yüklemesinin tam şekli (yükleniyor bayrağı → uç → satırlar + toplam kayıt)
|
|
263
326
|
`ngapps://examples/flow-load-table`'dadır; setter'ın kritik iki iteratee'si şöyle görünür:
|
|
264
327
|
|
|
@@ -279,7 +342,67 @@ Satır eşlemeli tablo yüklemesinin tam şekli (yükleniyor bayrağı → uç
|
|
|
279
342
|
|
|
280
343
|
`errorSteps` verirsen (start dışında en az bir adım) hata anında `engine.onError` true döner ve
|
|
281
344
|
**ana akışın kalan adımları hiç çalışmaz** — yükleniyor bayrağını kapatmak, hata mesajını
|
|
282
|
-
göstermek error flow'un işidir
|
|
345
|
+
göstermek error flow'un işidir.
|
|
346
|
+
|
|
347
|
+
> **4xx de hatadır ve `always` dalı seni KURTARMAZ.** `microservice.ts` `.catch` bloğu
|
|
348
|
+
> reddedilen her istekte koşar — 401/403/404/422 dâhil. Sonrası iki yoldan biridir ve ikisi de
|
|
349
|
+
> "ekranda hiçbir şey olmadı" ile biter:
|
|
350
|
+
>
|
|
351
|
+
> 1. **Hata yolu VARSA** `engine.onError` true döner ve `.finally` `return` eder —
|
|
352
|
+
> `engine.next('always')` **hiç çağrılmaz**. Yani `always` ile `errorSteps` birbirini dışlar;
|
|
353
|
+
> ikisini birden kuramazsın, hata yolu ana akışın devamını devralır.
|
|
354
|
+
> 2. **Hata yolu YOKSA** `always` koşar, ama storage artık `{ error, data }`'dır ve
|
|
355
|
+
> `Steps.<ad>.data` başarı gövdesi değil **hata gövdesidir**. Sıradaki `condition`
|
|
356
|
+
> `!!Steps.signIn.data.token` gibi bir ifadeyi `undefined` üzerinden değerlendirir, sessizce
|
|
357
|
+
> diğer dala düşer ve `else` dalı bağlı değilse akış orada biter.
|
|
358
|
+
>
|
|
359
|
+
> **`errorSteps` yalnız `start` taşıyorsa hata yolu YOKTUR:** `hasErrorFlow`
|
|
360
|
+
> `errorTasks.some(t => t.type !== 'start')` arar. Start'ın ardına en az bir adım bağla —
|
|
361
|
+
> gateway `FLOW-021` ile uyarır.
|
|
362
|
+
>
|
|
363
|
+
> **Mobilde `errorSteps` diye bir şey YOK.** `ScreenRuntime.tsx` `mapFlowsToMachine` yalnız
|
|
364
|
+
> `tasks` üretir (web `Runtime.svelte` ayrıca `errorTasks` verir), yani mobil uygulamada
|
|
365
|
+
> `hasErrorFlow` her zaman false: hata yolu hiç koşmaz ve akış yukarıdaki 2. yoldan —
|
|
366
|
+
> `always` + hata gövdeli storage — devam eder. Mobil sayfada hata yolunu `condition
|
|
367
|
+
> Steps.<adımAdı>.error` ile kur.
|
|
368
|
+
|
|
369
|
+
> **Hata metni ÜÇ ayrı yerde durur ve ikisi kullanıcıya gösterilecek metin DEĞİLDİR.**
|
|
370
|
+
> `onError` hata akışını koşturmadan önce `machine.setStorage('error', errorInfo)` yapar
|
|
371
|
+
> (`flow-engine.ts`), yani hata akışının adımları `Steps.error`'ı okuyabilir:
|
|
372
|
+
>
|
|
373
|
+
> | İfade | Ne taşır | Kaynak |
|
|
374
|
+
> |---|---|---|
|
|
375
|
+
> | **`Steps.error.message`** | **Ucun kendi mesajı** — `err.response.data.message`; boşsa HTTP durum metnine düşer. **Kullanıcıya gösterilecek metin budur.** Yanında `Steps.error.code` · `Steps.error.step.name` (patlayan adım) · `Steps.error.step.data` (ucun gövdesi) gelir | `microservice.ts` `err.reason \|\| HttpStatusText[err.code]` → `flow-engine.ts` `onError` |
|
|
376
|
+
> | `Steps.<adımAdı>.error` | Yalnız HTTP **durum metni** — 401 için `'Unauthorized'`. Hata OLDUĞUNU anlamaya yarar, göstermeye değil | `microservice.ts` `.catch` `HttpStatusText[err.code]` |
|
|
377
|
+
> | `Steps.<adımAdı>.data` | Ucun **hata gövdesi** (`err.response.data`) — başarı gövdesi değil. `.message` alanı burada da vardır | `microservice.ts` `.catch` |
|
|
378
|
+
>
|
|
379
|
+
> **`alert` adımının `message`'ı DÜZ METİNDİR — ifade yazarsan ekranda o ifade görünür.**
|
|
380
|
+
> `alert.ts` `task.argument.message`'ı doğrudan `toast.error()`'a geçirir ve `args` hiçbir yerde
|
|
381
|
+
> değerlendirilmez (`Runtime.svelte` `argument: step.args`): `{ "type": "alert", "args": {
|
|
382
|
+
> "message": "Steps.error.message", "alertType": "error" } }` kullanıcıya harfi harfine
|
|
383
|
+
> `Steps.error.message` gösterir. Sabit bir uyarı yetiyorsa `alert` en ucuz adımdır; **ucun ne
|
|
384
|
+
> dediğini göstereceksen bir `setter` (ya da `code`) adımı zorunludur** — `value.type: 'code'`
|
|
385
|
+
> ifadeyi orada gerçekten çalıştırır:
|
|
386
|
+
>
|
|
387
|
+
> ```jsonc
|
|
388
|
+
> // errorSteps: start → bu setter. Metni bir notification/text komponentine yazar.
|
|
389
|
+
> { "stepId": "show_error", "name": "Hatayı göster", "type": "setter", "kind": "normal",
|
|
390
|
+
> "args": { "iteratees": [
|
|
391
|
+
> { "type": "change", "element": "error_note", "property": "content", "source": "component",
|
|
392
|
+
> "mapping": { "source": "", "mappings": {} },
|
|
393
|
+
> "value": { "type": "code", "ref": "Steps.error?.message ?? 'İşlem başarısız'" } }] },
|
|
394
|
+
> "branches": [{ "id": "<GUID>", "name": "always", "nextStepId": null }] }
|
|
395
|
+
> ```
|
|
396
|
+
|
|
397
|
+
> **Hangi yolu seçeceksin — `errorSteps` mi, ana akışta `condition` mı?** İkisi birden
|
|
398
|
+
> kurulamaz (yukarıdaki 1. madde), yani bu bir tercih değil bir karar:
|
|
399
|
+
>
|
|
400
|
+
> | | `errorSteps` | ana akışta `condition Steps.<adımAdı>.error` |
|
|
401
|
+
> |---|---|---|
|
|
402
|
+
> | Ana akışın kalanı | **koşmaz** — hata akışı devralır | koşar, dalı sen seçersin |
|
|
403
|
+
> | Yükleniyor bayrağı · modal kapatma · tablo tazeleme | hata akışında **yeniden kurmak zorundasın**; kurmazsan bayrak açık kalır | zaten ana akışta duruyor |
|
|
404
|
+
> | Hata metni | `Steps.error.message` (yukarıdaki tablo) | `Steps.<adımAdı>.data.message`, hata olduğunu `Steps.<adımAdı>.error` söyler |
|
|
405
|
+
> | Ne zaman doğru | hata anında akış **tamamen başka bir yola** sapacaksa (başarısız giriş, yetkisiz sayfa) | kalan adımların çoğu hata hâlinde de koşacaksa — **form gönderimlerinin varsayılanı budur** (Kural 7) |
|
|
283
406
|
|
|
284
407
|
Zorunlu filtresi olan uçlarda (`patient-*`, `doctor-appointments` gibi `isRequired: true`
|
|
285
408
|
filtreli microservice'ler) parametreyi adımda ver, yoksa uç `MissingParameterException` atar:
|
|
@@ -319,15 +442,93 @@ Tarif: `platform_guide('middleware')`.
|
|
|
319
442
|
- Adım hedef akışı **bekler** (`await engine.run`), sonra `always` dalından devam eder.
|
|
320
443
|
- Gateway boş/yarım `args`'ı **FLOW-014** ile yakalar.
|
|
321
444
|
|
|
445
|
+
> **`code` adımının gövdesi `args.value` alanındadır — düz JS metni olarak.** Runtime onu
|
|
446
|
+
> `(async () => { <value> })()` içinde koşturur (`code.ts:18`), yani `await` serbesttir ve dönüş
|
|
447
|
+
> değeri akışa taşınmaz; etkiyi `Page`/`state`/komponent yazarak üretirsin. **Alan boşsa adım
|
|
448
|
+
> hata vermeden NO-OP olur** ve akış hiçbir şey yapmadan devam eder.
|
|
449
|
+
>
|
|
450
|
+
> ```jsonc
|
|
451
|
+
> { "stepId": "sync_filters", "name": "sync_filters", "type": "code", "kind": "normal",
|
|
452
|
+
> "args": { "value": "state.page.month = flt_month.value" },
|
|
453
|
+
> "branches": [{ "id": "<GUID>", "name": "always", "nextStepId": "reload" }] }
|
|
454
|
+
> ```
|
|
455
|
+
>
|
|
456
|
+
> `args.expression` / `args.script` gibi uydurma anahtarlar `StepManagementArgument` sözleşmesinde
|
|
457
|
+
> YOKTUR ve platform onları **sessizce düşürür**: 2026-09-05 koşusunda akış koştu, filtre hiçbir
|
|
458
|
+
> şey yapmadı ve teşhis ~10 dakika sürdü. Gateway artık ikisini birden yakalar — **FLOW-019**
|
|
459
|
+
> gövdesiz `code` adımını istek gitmeden reddeder, akış yazmasından sonra da gövdeyi geri okuyup
|
|
460
|
+
> farkı `silentlyDropped` ile bildirir.
|
|
461
|
+
>
|
|
462
|
+
> **Çoğu zaman `code` adımına hiç gerek yok:** filtre değerini sayfa değişkenine yazmak yerine
|
|
463
|
+
> değeri doğrudan komponent prop'undan okuyun (`value: { type: 'property', ref: { source:
|
|
464
|
+
> 'component', element: 'flt_month', property: 'value' } }`, ya da bir `code` ifadesinde
|
|
465
|
+
> `flt_month.value`) ve olayı doğrudan yükleme akışına bağlayın — ara adım kırılgan bir katman ekler.
|
|
466
|
+
|
|
467
|
+
> **Tek bir ifadeyi düzeltmek için tüm gövdeyi yeniden göndermeyin: `flow_patch` var.** Dizi
|
|
468
|
+
> öğelerinde indeks yerine seçici kullanın —
|
|
469
|
+
> `/steps[stepId=paint]/args/iteratees[element=tbl_funnel]/mapping/mappings/share/ref`. Adım ve
|
|
470
|
+
> iteratee sırası platformda değişebilir; indeksle yazılan patch yanlış öğeye dokunur.
|
|
471
|
+
|
|
472
|
+
> **`states` bir prop DEĞİL düğüm alanıdır** (`isWrapper`, `isScrollable`, `isSticky`,
|
|
473
|
+
> `isDroppable`, `isFloating`, `isQuickStack`): `replace_prop` onu yazamaz. Kurulmuş bir düğümde
|
|
474
|
+
> değiştirmek için `resize_component`'e `states` verin —
|
|
475
|
+
> `{ op: 'resize_component', target: 'row_kpi', states: { isWrapper: false } }`. Eskiden tek yol
|
|
476
|
+
> düğümü silip yeniden kurmaktı ve 09-05 koşusunda bunun bedeli 20 setter'ın kopmasıydı.
|
|
477
|
+
> **`isWrapper: true` olan her kapsayıcıya runtime `min-height: 80vh` veriyor** — dokuz düğüm
|
|
478
|
+
> sayfaya ~1600px ölü boşluk eklemişti; `style` ile ezilemez, gerekmiyorsa `false` bırakın.
|
|
479
|
+
|
|
322
480
|
**Sözlükler** (`StepType.cs`, `StepParameterValueType.cs` — hepsi küçük harf):
|
|
323
481
|
`start · microservice · setter · setcookie · validation · condition · redirect · alert ·
|
|
324
|
-
confirm · flow-trigger · storage · navigate · code · download · end`
|
|
482
|
+
confirm · flow-trigger · storage · navigate · code · download · function · end`
|
|
325
483
|
değer tipleri: `static · page · property · storage · variable · code · item · state`
|
|
326
484
|
|
|
485
|
+
> **Sözlükte olmak KOŞACAĞI anlamına gelmez — koşan tipler barındırıcıdan gelir.** Motor yedi
|
|
486
|
+
> tip register eder, gerisini uygulama ekler. Bir sayfa TEK bir uygulamaya aittir
|
|
487
|
+
> (`Page.ApplicationId`) ve uygulamanın tipi `web` ya da `mobile`'dır (`ApplicationType.cs`), yani
|
|
488
|
+
> sayfanın barındırıcısı bellidir — matris "hangi tip sende çalışır"ı söyler, iki barındırıcıda
|
|
489
|
+
> birden koşmayı değil (web `Runtime.svelte`, mobil `ScreenRuntime.tsx`):
|
|
490
|
+
>
|
|
491
|
+
> | Adım tipi | Web | Mobil | Nerede register ediliyor |
|
|
492
|
+
> |---|---|---|---|
|
|
493
|
+
> | `start` · `setter` · `code` · `condition` · `microservice` · `validation` · `flow-trigger` · `function` | ✅ | ✅ | `flow-engine.ts` — motorun kendisi (`function` mobilde kayıtlıdır ama mobil runtime `Functions`'ı boş kurar — K11, çağrı çalışmaz) |
|
|
494
|
+
> | `alert` · `redirect` · `setcookie` · `storage` | ✅ | ✅ | uygulama; mobilde `redirect` navigate, `setcookie` storage uygulamasına eşlenir |
|
|
495
|
+
> | `confirm` · `download` | ✅ | ❌ | yalnız `Runtime.svelte` |
|
|
496
|
+
> | `navigate` | ❌ | ✅ | yalnız `ScreenRuntime.tsx` — web'deki karşılığı `redirect` |
|
|
497
|
+
> | `end` · `query` | ❌ | ❌ | hiçbir yerde — üstelik `query` backend sözlüğünde de yok (`StepType.cs` onu saymaz), yalnız frontend enum'unda duruyor |
|
|
498
|
+
>
|
|
499
|
+
> **Register edilmemiş bir tipe gelen akış SESSİZCE durur.** `flow-engine.ts` `process()`
|
|
500
|
+
> callback bulamazsa hiçbir şey yapmaz: `next()` yok, `completed`/`stopped` yok, hata yok, log
|
|
501
|
+
> yok. Akışın kalanı ölür — üstelik `run()`'ın promise'i hiç çözülmediği için
|
|
502
|
+
> `flowRunFinished()` koşmaz: `__ngAppsFlowActivity.running` sıfıra inmez ve
|
|
503
|
+
> `page_screenshot`'ın hazır bekleyişi her eylemde bütçesini sonuna kadar yakar.
|
|
504
|
+
>
|
|
505
|
+
> Gateway iki hâli **kendisi düzeltir** ve `gatewayNormalized` ile söyler: `navigate` → `redirect`
|
|
506
|
+
> (argüman şekli aynı, `redirect` iki barındırıcıda da koşar) ve ölü `end` adımı gövdeden düşer
|
|
507
|
+
> (ona işaret eden dal `nextStepId: null` olur). `FLOW-023` bunların arkasındaki emniyet kemeridir:
|
|
508
|
+
> `end`/`query` kalırsa **bloklar**, iki barındırıcıya birden özel tip taşıyan gövdeyi uyarır. Tek
|
|
509
|
+
> barındırıcıya özel bir tipi (`confirm`/`download`) tek başına kullanmak kusur değildir — gateway
|
|
510
|
+
> sayfanın hangi uygulamada olduğunu bilmez, doğru tipi bu matristen SEN seçersin.
|
|
511
|
+
>
|
|
512
|
+
> **`end` adımı bir tuzaktır.** Studio kataloğunda bir tip olarak duruyor
|
|
513
|
+
> (`event-actions.constants.ts` `FlowTaskType.End`; ekleme menüsü onu eler) ve eski akışlar bu
|
|
514
|
+
> düğümü taşıyabiliyor (`event-actions.mappers.ts`) — ama Studio'nun varsayılan şeması End
|
|
515
|
+
> düğümü YARATMAZ (`DEFAULT_SCHEMA` `endId`'yi üretir ve kullanmaz) ve motor onu register etmez. Düğümün VARLIĞI zararsızdır; zararlı olan **bir dalın oraya işaret
|
|
516
|
+
> etmesidir** — akış o adıma girer ve çıkamaz. Akış, son adımın dalına `nextStepId: null`
|
|
517
|
+
> verilerek bitirilir. İronik olan şu: var olmayan bir `stepId`'ye işaret etmek daha güvenlidir,
|
|
518
|
+
> çünkü motor hedefi bulamayınca `completed`/`stopped`'ı düzgün çağırır.
|
|
519
|
+
|
|
327
520
|
> `code` adımının içinde ve `value.type:'code'` ifadelerinde kullanılabilen bağlam
|
|
328
521
|
> (`Page.*`, komponentlere adıyla erişim, `state.page/app`, `Steps`, `self`/`item`/`event`,
|
|
329
522
|
> `cookie.get/set`, `await`) ve `value.type` çözümleme tablosu için
|
|
330
523
|
> **`platform_guide('expressions')`** — uydurma erişim adı sessizce `undefined` üretir.
|
|
524
|
+
>
|
|
525
|
+
> **`function` adımı ("Call function")** bir kullanıcı fonksiyonunu çağırır: `args: { functionId, functionName,
|
|
526
|
+
> parameters: [{ name, value }] }` — `functionId` zorunlu ve gerçek (`function_list`; FLOW-024 block),
|
|
527
|
+
> `parameters[].name` fonksiyonun bildirimindeki adla eşleşir, `value` şekli `microservice` adımıyla
|
|
528
|
+
> aynıdır. Çıktı `Steps.<adımAdı>.data` (hata `.error.message`), dal `always`. Aynı fonksiyon `code`
|
|
529
|
+
> adımında ve `{{ }}` bağlamasında `Functions.<ad>(…)` ile de çağrılır; gateway bilinmeyen adı ve
|
|
530
|
+
> fazla argümanı FLOW-025 ile uyarır. Tam gövde `ngapps://examples/flow-call-function`, kurallar
|
|
531
|
+
> **`platform_guide('functions')`**.
|
|
331
532
|
|
|
332
533
|
> Bir microservice adımı kaydedildiğinde platform `args.microserviceSchema`'yı
|
|
333
534
|
> (parameterScheme + returnScheme + `isReturnArray`) kendisi doldurur — `flow_get` ile geri
|
|
@@ -355,6 +556,10 @@ Toplam kayıt sayısı `Total-Count` header'ından gelir (`TableMicroserviceExec
|
|
|
355
556
|
`isSingle: false` olduğu sürece) — `totalRows`'u yukarıdaki guard'lı ifadeyle yaz. Gateway
|
|
356
557
|
parametreleri geçmeyi unutursan `FLOW-013` ile uyarır.
|
|
357
558
|
|
|
559
|
+
Ucun gerçekten `Total-Count` döndüğünü sayfayı kurmadan **önce** doğrula:
|
|
560
|
+
`microservice_execute(...)` yanıtındaki `headers['total-count']` dolu olmalı; boşsa `sort`/`limit`
|
|
561
|
+
verilmemiş bir tablo kaynağı vardır ve sayfa göstergesi `NaN / N` olur (ölçüm: İK koşusu M-8/E-4).
|
|
562
|
+
|
|
358
563
|
> **`replace_prop` Prop sarmalı DEĞİL ham değer alır** — `PageSchemaMicroOpApplier.cs:77`
|
|
359
564
|
> `new Prop(PropValueType.Static) { Data = op.Value }` kurar. `{ "type": "static", "data": true }`
|
|
360
565
|
> gönderirsen sarmalın kendisi `Data`'ya yazılır ve platform onu `Dictionary<string, Prop>` diye
|
|
@@ -394,8 +599,9 @@ Türkçe başlık `props.title` / `props.text` / `props.label` / `props.pageTitl
|
|
|
394
599
|
> Aynı sebeple akış ifadelerinde komponente **`name` ile** erişilir (`tbl_mng.selectedRow`);
|
|
395
600
|
> `elementId` ile eşit tutmazsan `element:` alanı çalışır ama ifadedeki değişken `undefined` kalır.
|
|
396
601
|
>
|
|
397
|
-
> Gateway bunu **PAGE-009** ile
|
|
398
|
-
>
|
|
602
|
+
> Gateway bunu **PAGE-009** ile HER sayfa ve layout yazma yolunda istek gitmeden reddeder:
|
|
603
|
+
> `page_create`, `page_update(schema)`, `add_component`, `layout_create`, `layout_update(views)`
|
|
604
|
+
> ve `layout_patch`.
|
|
399
605
|
|
|
400
606
|
## Kural 1d — Sayfa iskeleti: `page_container` ve boyutlandırma
|
|
401
607
|
|
|
@@ -614,8 +820,9 @@ kullanır: `page.mappers.ts` `mapPageLayoutToPreview` — layout varsa çizilen
|
|
|
614
820
|
>
|
|
615
821
|
> Kural: **`isWrapper` yalnız gerçekten sayfa boyu kaplaması gereken kap içindir**
|
|
616
822
|
> (`page_container` böyledir ve öyle kalmalı). Sadece "başlık/çerçeve çizilmesin" diye wrapper
|
|
617
|
-
> yapma — o iş `container` için `style` ile (`background:'transparent'`,
|
|
618
|
-
> `form`
|
|
823
|
+
> yapma — o iş `container` için de `form` için de `style` ile yapılır (`background:'transparent'`,
|
|
824
|
+
> `border:'none'`, `padding:0`). `form`'un eski `hideBorders`/`hidePadding` prop'ları
|
|
825
|
+
> 2026-09-09'da şemadan kaldırıldı — bileşen onları hiçbir zaman okumuyordu, no-op'tu. **`states` için micro-op
|
|
619
826
|
> YOKTUR:** yanlış `isWrapper`'ı düzeltmenin tek yolu düğümü `remove_component` +
|
|
620
827
|
> `add_component` ile yeniden kurmaktır (sonrasında Kural 2'deki flow yeniden kaydetme adımı
|
|
621
828
|
> ZORUNLU olur).
|
|
@@ -633,13 +840,18 @@ aynı prop grubunu o da alır. Grup katalogda tanımlıdır, yani şemadan kurul
|
|
|
633
840
|
|
|
634
841
|
| Prop | Değerler (varsayılan **kalın**) | Ne yapar |
|
|
635
842
|
|---|---|---|
|
|
636
|
-
| `layout` | **`flex`** · `grid` | `flex`: akış düzeni. `grid`: 12 kolonluk ızgara (Kural 1f). |
|
|
843
|
+
| `layout` | **`flex`** · `grid` | `flex`: akış düzeni. `grid`: 12 kolonluk mutlak ızgara (Kural 1f). Grubu taşıyan kaplar: `container`/`page_container` · `form` (2026-09-01'den) · `box`/`aibox` · `layout` ve `widget-area` (2026-09-03) — hepsinde değer kümesi `flex·grid`; yalnız `box-section` tek değerlidir (`flex`). `box`/`aibox`'ın eski üçüncü değeri `cssgrid` (akan gerçek `display:grid`) 2026-09-02'de seçenek olmaktan çıktı: yeni yazımda `invalid-enum-value` verir, o değerle kayıtlı düğümler çizilmeye devam eder. |
|
|
637
844
|
| `direction` | **`row`** · `column` | `flex-direction`; hangi hizalamanın ANA eksen olduğunu belirler. |
|
|
638
845
|
| `horizontalAlign` | **`left`** · `center` · `right` · `stretch` | `row`'da ana eksen (`justify-content`), `column`'da çapraz eksen (`align-items`). |
|
|
639
846
|
| `verticalAlign` | **`top`** · `middle` · `bottom` · `stretch` | `row`'da çapraz eksen, `column`'da ana eksen (rolleri `horizontalAlign` ile takas). |
|
|
640
847
|
| `size` | **`shrink`** · `grow` | Çocuklara `flex: 0 1 auto` / `1 1 auto`. |
|
|
641
|
-
| `gap` | `none` · `small` · **`medium`** · `large` | 0 /
|
|
642
|
-
| `wrap` |
|
|
848
|
+
| `gap` | `none` · `small` · **`medium`** · `large` **ya da ham CSS** | Preset'ler tema değişkenidir: 0 / `var(--ng-spacing-sm)` / `--ng-spacing-md` / `--ng-spacing-lg` (varsayılan temada 8/16/32px). Alan `allowCustom`'dır: `"18px"` ya da `"var(--ng-spacing-xl)"` gibi ham değer de geçer. `box-section`/`aibox`'taki sayısal `gapCustom` doluysa preset'i ezer. |
|
|
849
|
+
| `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. |
|
|
850
|
+
|
|
851
|
+
**`form` da bu grubun tamamını taşır (2026-09-01):** varsayılanları container ile aynı
|
|
852
|
+
(`flex` · `row` · `left` · `top` · `shrink` · `medium` · `wrap` açık). "Form'a layout yazılmaz"
|
|
853
|
+
eski bilgidir. (Platform kataloğu güncel şemayı `component_get`'te göstermiyorsa kayıt
|
|
854
|
+
yenilenmemiştir — ARC-024.)
|
|
643
855
|
|
|
644
856
|
`stretch` iki eksende farklı anlama gelir: **ana** eksende `space-between` (çocukları uçlara
|
|
645
857
|
dağıtır), **çapraz** eksende gerçekten doldurur.
|
|
@@ -654,27 +866,37 @@ prop'una bakar (`isFlexLayout`). İki sonucu var:
|
|
|
654
866
|
ızgara alırsın — Studio'dan sürüklenen kardeş kapsayıcı flex gelirken seninki grid kalır.
|
|
655
867
|
|
|
656
868
|
Gateway'in kendi eklediği kök kapsayıcı (`page_create`'te şemada `page_container` yoksa) bu yüzden
|
|
657
|
-
seti açıkça taşır: `flex` · `row` · `left` · `top` · `shrink` · `medium
|
|
658
|
-
|
|
659
|
-
istiyorsan
|
|
869
|
+
seti açıkça taşır: `flex` · `row` · `left` · `top` · `shrink` · `medium` · `wrap` açık.
|
|
870
|
+
`row` + `wrap` açık + `w: 12` çocuklar alt satıra sararak dikey akar; net bir dikey akış
|
|
871
|
+
istiyorsan yine de `direction: 'column'` yazmak daha okunur (ya da `layout: 'grid'`e dön).
|
|
872
|
+
**`wrap`'i kapatırsan** alt alta düşünülmüş `w: 12` çocuklar TEK SATIRA sıkışır.
|
|
660
873
|
|
|
661
874
|
**Ne zaman flex?** Yan yana buton/aksiyon grubu, toolbar, rozet dizisi, ortalanmış giriş kartı,
|
|
662
875
|
"kalanı doldursun" yerleşimleri. Alt alta akan form alanları için ızgara da doğrudur — orada flex
|
|
663
876
|
istiyorsan `direction: 'column'` şart, `row` ile alanlar tek satıra sıkışır.
|
|
664
877
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
1.
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
878
|
+
Beş şeyi bilmeden flex kurma:
|
|
879
|
+
|
|
880
|
+
1. **Çocuğun genişliği `appearance.widthType`'tan gelir (2026-09-01); 12 kolon yalnız
|
|
881
|
+
FALLBACK'tir.** Dört cevap, öncelik sırasıyla:
|
|
882
|
+
- `widthType: 'fill'` — kabın tüm genişliği (satırda `flex:1 1 100%`, sütunda
|
|
883
|
+
`align-self:stretch`); string taşımaz, taşırsa bile ezer.
|
|
884
|
+
- `widthType: 'fixed'` + `widthString` — sabit ölçü, serbest CSS uzunluğu (`"240px"`,
|
|
885
|
+
`"50%"`, `"10vw"`, `calc(...)`). Geçersiz string sessizce düşer ve span'a dönülür.
|
|
886
|
+
- `widthType: 'auto'` — içerik kadar (`flex: 0 1 auto`).
|
|
887
|
+
- `widthType` YOK (eski kayıtlar) — `blocks[].size.w` payı: `row`'da `flex-basis: w/12`,
|
|
888
|
+
`column`'da `width: w/12` (`gap` payı düşülür; `column` + `horizontalAlign:'stretch'`
|
|
889
|
+
istisna — tam genişlik). Izgara ↔ flex geçişi bu fallback sayesinde kayıpsızdır.
|
|
890
|
+
Şemayı sen kuruyorsan çocuğa `widthType`'ı AÇIKÇA yaz. Studio'nun kendi bırakma kuralı:
|
|
891
|
+
kapsayıcı türü kaplar (`container`/`box`/`form`) `'fixed'` + `"50%"`, diğer her şey `'auto'`.
|
|
672
892
|
2. **`position.y` artık yalnız SIRADIR.** Flex çocuklar `y`, sonra `x` sırasına göre dizilir;
|
|
673
893
|
aradaki boşluklar çizilmez. Yine de bitişik ver (0,1,2…): kapsayıcı ileride `grid`'e
|
|
674
894
|
döndürülürse şema geçerli kalsın. Gateway bu yüzden **flex kapsayıcının İÇİNDE PAGE-010
|
|
675
895
|
boşluk uyarısı üretmez** (ızgarada üretmeye devam eder).
|
|
676
896
|
3. **Flex kapsayıcının yüksekliği içeriğine oturur.** `verticalAlign`'ın dağıtacak boşluğu
|
|
677
|
-
olması için `appearance.heightType: 'fixed'`
|
|
897
|
+
olması için `appearance.heightType: 'fixed'` vermelisin — ölçü `heightString`'den
|
|
898
|
+
(serbest CSS uzunluğu, ör. `"30vh"`), o yoksa `size.h × 10px`'ten gelir. `heightString`
|
|
899
|
+
yalnız `heightType:'fixed'` iken okunur; tek başına yazmak hiçbir şey yapmaz. **İstisna
|
|
678
900
|
`page_container`**: `states.isWrapper: true` olduğu için zaten `min-height: 80vh` alır
|
|
679
901
|
(Kural 1f), dolayısıyla dikey hizalama onda kutu boyu vermeden de çalışır. Üçüncü yol
|
|
680
902
|
`heightType: 'fill'` (2026-08-28): çocuk kabın bıraktığı yeri alır — sütunda `flex: 1 1 auto`,
|
|
@@ -684,6 +906,10 @@ Dört şeyi bilmeden flex kurma:
|
|
|
684
906
|
4. **`layout: 'grid'` iken diğer altı prop ÖLÜDÜR.** Katalogda tanımlı oldukları için
|
|
685
907
|
doğrulama duvarı susar, renderer da okumaz: ızgara kapsayıcıya `direction: 'column'` yazmak
|
|
686
908
|
sessizce hiçbir şey yapmaz. Gateway bunu **PAGE-015 (uyarı)** ile söyler.
|
|
909
|
+
5. **Flex düzeni kırılım BİLMEZ.** `direction`/`gap`/hizalama masaüstü ve mobilde AYNIDIR;
|
|
910
|
+
sıra ve span'lar Desktop (1024) bloğundandır — Studio, mobil kırılım düzenlenirken flex
|
|
911
|
+
bölgeyi salt-okunur kilitler. Kırılım bilen yalnız `blocks[]` ve `appearance.hideOn`'dur;
|
|
912
|
+
mobilde farklı davranış gereken satır için `layout: 'grid'` kullan (Kural 1f mobil notu).
|
|
687
913
|
|
|
688
914
|
```jsonc
|
|
689
915
|
// Ortalanmış giriş kartı — style ile CSS hack'i YOK, kabın kendi düzeni
|
|
@@ -701,6 +927,33 @@ Dört şeyi bilmeden flex kurma:
|
|
|
701
927
|
{ "op": "replace_prop", "target": "row_actions", "prop": "gap", "value": "small" }
|
|
702
928
|
```
|
|
703
929
|
|
|
930
|
+
**Mini tarif — sıkı dizilim (küçük bileşenleri dip dibe getirmek).** Buton/rozet/ikon dizisi
|
|
931
|
+
gibi bitişik duracak elemanlar için ÜÇ şart birden gerekir; biri eksikse arada boşluk kalır:
|
|
932
|
+
|
|
933
|
+
1. Her çocuğa **`appearance.widthType: 'auto'`** — içerik kadar yer kaplar (`flex: 0 1 auto`).
|
|
934
|
+
Yazılmazsa eski 12 kolon payı geçerlidir ve çocuk kolonunu doldurur, bitişemez.
|
|
935
|
+
2. Kaba **`gap: 'none'`** (ya da ham ince değer: `"2px"`, `"4px"` — alan `allowCustom`).
|
|
936
|
+
3. Her çocuğa **`appearance.marginType: 'none'`** — en çok atlanan şart: `marginType`
|
|
937
|
+
yazılmamış düğüm `normal` sayılır ve her kenara 4px basar (`spacing.ts`
|
|
938
|
+
`CANVAS_NORMAL_MARGIN`), yani `gap:'none'` olsa bile komşular arasında 8px kalır.
|
|
939
|
+
|
|
940
|
+
```jsonc
|
|
941
|
+
// Bitişik rozet dizisi: kap + iki çocuktan biri (diğeri aynı desen)
|
|
942
|
+
{ "elementId": "badge_row", "type": "container", "kind": "component",
|
|
943
|
+
"props": { "layout": { "type": "static", "data": "flex" },
|
|
944
|
+
"direction": { "type": "static", "data": "row" },
|
|
945
|
+
"gap": { "type": "static", "data": "none" } },
|
|
946
|
+
"children": [
|
|
947
|
+
{ "elementId": "badge_1", "type": "button", "kind": "component",
|
|
948
|
+
"appearance": { "widthType": "auto", "marginType": "none", "heightType": "auto" },
|
|
949
|
+
"blocks": [{ "breakpoint": 1024, "size": { "w": 2, "h": 4 }, "position": { "x": 0, "y": 0 } }] }
|
|
950
|
+
] }
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
"Şu ikisi bitişik, şu uzak" gibi eşit olmayan aralıklar için `gap` yetmez (kapta tekildir) —
|
|
954
|
+
bitişik elemanları `gap:'none'` bir İÇ kapsayıcıda gruplayıp grupları dış kapta normal
|
|
955
|
+
`gap` ile diz.
|
|
956
|
+
|
|
704
957
|
> Düzen işi `style` prop'una AİT DEĞİL. Kural 1h'deki `style` reçeteleri tema/görsellik içindir;
|
|
705
958
|
> `display:flex` gibi düzen kurallarını oraya yazmak kabın kendi düzeniyle çakışır (PAGE-014'teki
|
|
706
959
|
> ölçüm: string style ile kart 66px'e çöktü). Yerleşim bu prop grubuyla, tema `style` ile kurulur.
|
|
@@ -776,8 +1029,10 @@ UYGULAMAZ** — koordinatları aynen kaydeder (aşağı itme yalnız `page_creat
|
|
|
776
1029
|
> - Ekranda sürekli `Expression error: Cannot read properties of null (reading '0')` toast'ı çıkıyor
|
|
777
1030
|
> (iç repeater bir kez `item` olmadan da değerlendiriliyor).
|
|
778
1031
|
>
|
|
779
|
-
> **Gateway bunu `PAGE-013` ile istek gitmeden reddediyor**
|
|
780
|
-
> `
|
|
1032
|
+
> **Gateway bunu `PAGE-013` ile istek gitmeden reddediyor** — `page_create` / `page_update(schema)` /
|
|
1033
|
+
> `layout_create` / `layout_update(views)` / `layout_patch` gönderilen ağaca, `page_schema_patch` hem
|
|
1034
|
+
> eklenen alt ağaca hem op'lar UYGULANDIKTAN SONRAKİ ağaca bakarak. Layout'ta da geçerlidir: kırılma
|
|
1035
|
+
> `_repeaterValues` geri yazmasındadır, barındıranın sayfa mı layout mu olduğuna bakmaz.
|
|
781
1036
|
>
|
|
782
1037
|
> **Yapılacak:** satır içi listeyi tek bir `textarea`'da **satır başına bir öğe** olarak topla
|
|
783
1038
|
> (`options_text`), kaydederken `split('\n')`'le böl. Ölçülmüş çalışan sürüm: anket editörü
|
|
@@ -805,6 +1060,14 @@ yapmanın yolu budur — ölçülmüş kurallar (anket-doldur, 2026-08-19):
|
|
|
805
1060
|
> Bu kural TEMA/GÖRSELLİK içindir. Çocukların dizilimi (ortalama, yaslama, aralık, "kalanı
|
|
806
1061
|
> doldur") `style` ile değil kapsayıcının kendi `layout` prop grubuyla kurulur — Kural 1f-2.
|
|
807
1062
|
|
|
1063
|
+
> **Stil anahtarları camelCase'dir: `minHeight`, `fontSize`, `letterSpacing`.** Kebab-case anahtar
|
|
1064
|
+
> (`min-height`) platform tarafından KABUL EDİLİR, `page_schema_get` ile aynen geri okunur ve
|
|
1065
|
+
> runtime onu HİÇ UYGULAMAZ; tek işaret tarayıcı konsolundaki tek satırdır ve `page_screenshot`
|
|
1066
|
+
> konsolu döndürmez. 2026-09-05 koşusunun en pahalı yanlış teşhisi buydu (~15 dk) ve yanlış teşhis
|
|
1067
|
+
> düğümleri silip yeniden kurmaya, o da 20 setter'ın sessizce kopmasına yol açtı. Gateway artık
|
|
1068
|
+
> kebab-case anahtarı camelCase'e çevirir ve `gatewayNormalized` ile bildirir; seçici anahtarlara
|
|
1069
|
+
> (`&__body`, `:hover`, `--ng-*`) dokunmaz.
|
|
1070
|
+
|
|
808
1071
|
**1. Temayı tek yerden çevir: `page_container.style` içinde `--ng-*` değişkenlerini ez.**
|
|
809
1072
|
Runtime bütün renk/tipografi/form tokenlarını CSS değişkeni olarak basar
|
|
810
1073
|
(`Theme.svelte`: `--ng-accent-primary`, `--ng-accent-hover`, `--ng-background-surface`,
|
|
@@ -875,6 +1138,13 @@ yapmazsan ekran "platform mavisi" görünür; marka rengine çevirmek tek satır
|
|
|
875
1138
|
BÜTÜN girdileri yuvarlar; aynı şeyi komponent komponent `&__input { borderRadius }` yazarak
|
|
876
1139
|
yapmak hem uzun sürer hem de yeni komponent eklendiğinde tutarsızlık üretir.
|
|
877
1140
|
|
|
1141
|
+
**Koyu tema karesi için sayfada `theme-toggle` bulunması gerekmez.** Ziyaretçinin tema tercihi
|
|
1142
|
+
çerezde değil `localStorage`'da (`zeyrek-viewer-theme-mode`) yaşar ve tema store'u onu sayfa
|
|
1143
|
+
açılırken bir kez okur; `page_screenshot` `colorScheme: 'dark' | 'light'` parametresi tercihi
|
|
1144
|
+
sayfa script'lerinden ÖNCE eker. İki temayı da doğrulamak, tasarıma düğme eklemeden iki çağrıdır
|
|
1145
|
+
(aynı tool'un `language` parametresi ikinci dil için aynı işi yapar —
|
|
1146
|
+
`platform_guide('translation')`).
|
|
1147
|
+
|
|
878
1148
|
### 1h-3 — Ölçülmüş hazır bloklar (anket ekranından, olduğu gibi kullanılabilir)
|
|
879
1149
|
|
|
880
1150
|
```jsonc
|
|
@@ -991,7 +1261,7 @@ budur — bir preset ya da `componentStyles` sizin değerinizi eziyorsa `styleLa
|
|
|
991
1261
|
| Değişiklik | Tool | Neden |
|
|
992
1262
|
|---|---|---|
|
|
993
1263
|
| Komponent ekle/sil/taşı, prop, binding, event | `page_schema_patch` | Doğrulama duvarı + açık Studio canvas'ına SignalR canlı yayını + eşzamanlı yazar kilidi yalnız bu yolda çalışır |
|
|
994
|
-
| Ad, slug, browserTitle, layout, roller, middleware | `page_update` | Üstbilgi alanları micro-op sözlüğünde yok |
|
|
1264
|
+
| Ad, slug, browserTitle, `browserTitleKey`, layout, roller, middleware | `page_update` | Üstbilgi alanları micro-op sözlüğünde yok. `browserTitleKey` sekme başlığını çeviri anahtarına bağlar: verilirse başlık sözlükten çözülür, boşsa `browserTitle` kullanılır. Başlık sayfa yüklenirken çözülür ve canlı dil değişimini izlemez (`platform_guide('translation')`) |
|
|
995
1265
|
|
|
996
1266
|
Platformun `PUT /pages/...` ucu **replace**'tir: gönderilmeyen `schema`/`events`/`roleIds`
|
|
997
1267
|
alanları silinir. Gateway bu yüzden `page_update`'te sayfayı önce okur, yalnız verdiğin
|
|
@@ -1018,6 +1288,17 @@ Yanıt üç alan döner: `applied` (uygulanan op sayısı), **`appliedPatch`** (
|
|
|
1018
1288
|
olarak hangi JSON Pointer'a ne yaptığı — RFC 6902 biçiminde; "gerçekten yalnız o komponente mi
|
|
1019
1289
|
dokunuldu" sorusunun kanıtı) ve **`newVersion`** (`UpdatedAt.Ticks`).
|
|
1020
1290
|
|
|
1291
|
+
> **`appliedPatch` gövdesi VARSAYILAN OLARAK iskelettir.** Girdi `{ op, path }` döner; eklenen
|
|
1292
|
+
> düğüm `component` altında yalnız `id`/`elementId`/`name`/`type`/`children` taşır. Kanıt zaten
|
|
1293
|
+
> path'tedir — `value` senin aynı turda gönderdiğin gövdenin yankısıdır ve tek bir `set_event`
|
|
1294
|
+
> yaması bile düğümün bütün prop'larını geri getiriyordu. Aynı kural `page_create` yanıtındaki
|
|
1295
|
+
> `schema` için de geçerlidir (çözülmüş layout düğümleri dâhil). Tam gövde: `view: 'full'`.
|
|
1296
|
+
>
|
|
1297
|
+
> **"Kaydedildi mi" sorusunu `appliedPatch` zaten cevaplamıyor** (aşağıdaki `silentlyDropped`
|
|
1298
|
+
> bölümü): yama 200 döner ve pointer'ı gösterir, ama alanın kayda geçtiğini söylemez. Onu gateway
|
|
1299
|
+
> yamadan sonra şemayı okuyup gönderdiğinle karşılaştırarak söyler. Kırpma bu yüzden kanıt kaybı
|
|
1300
|
+
> değildir; `view: 'full'`e yalnız gerçekten platformun ham gövdesini incelerken düş.
|
|
1301
|
+
|
|
1021
1302
|
**Sürüm kontrolü platformda var ama gateway bugün KULLANMIYOR.** Platform gövdede `baseVersion`
|
|
1022
1303
|
(long tick) kabul eder ve tutmazsa 409 verir; `page_state.baseVersion` bu değeri döner.
|
|
1023
1304
|
`page_schema_patch` bu alanı geçirmez — bayat plan koruması gateway tarafında
|
|
@@ -1204,9 +1485,21 @@ altın örneklerde** — şemayı ve akışları oradan kopyalayıp uyarla:
|
|
|
1204
1485
|
| Detay / profil | `ngapps://examples/page-detail-profile` |
|
|
1205
1486
|
| Dinamik form (alanlar veriden) | `ngapps://examples/page-dynamic-form` (Kural 1g + 1h) |
|
|
1206
1487
|
|
|
1207
|
-
> Gateway
|
|
1488
|
+
> Gateway üç yarım kurulumu yakalar: **FORM-001** (`form` eklendi, `submit` bağlanmadı),
|
|
1208
1489
|
> **FORM-002** (akışta POST/PUT adımı var ama hiç `source:'body'` parametresi yok → gövde boş
|
|
1209
|
-
> gider)
|
|
1490
|
+
> gider) ve **FORM-003** (formun `submit`'i bağlı ama içindeki butonun `click`'i bağlı değil).
|
|
1491
|
+
>
|
|
1492
|
+
> **FORM-003 neden var:** `button` varsayılan olarak `type="button"` çizilir; form içinde bile
|
|
1493
|
+
> HTML form submit'i HİÇ doğmaz — butona tıklamak da alanda Enter da uca istek göndermez ve
|
|
1494
|
+
> **hiçbir hata çıkmaz**. `ngapps://examples/page-sign-in`'i harfiyen izleyen bir giriş sayfası bu
|
|
1495
|
+
> yüzden tıklanamaz kalıyordu (ölçüldü 2026-09-05); teşhis yalnız gerçek tıklamayla mümkün oldu
|
|
1496
|
+
> (`page_screenshot` `actions`). İki çözümden biri yeter:
|
|
1497
|
+
>
|
|
1498
|
+
> 1. Butona **`props.type = 'submit'`** ver — katalogdaki `type` prop'u bu değeri destekliyor ve
|
|
1499
|
+
> idiomatik yol budur.
|
|
1500
|
+
> 2. Ya da AYNI akışı butonun `click` olayına da bağla.
|
|
1501
|
+
>
|
|
1502
|
+
> `submit` olayını forma bağlamak tek başına yetmez; gateway ikisi de yoksa uyarır. `project_overview` ayrıca proje düzeyi boşlukları döndürür (`coverageGaps`): kimlik
|
|
1210
1503
|
> middleware'i var ama giriş sayfası yok, yazma ucu var ama sayfa yok.
|
|
1211
1504
|
|
|
1212
1505
|
**Adlandırma:** çoğul = liste sayfası, tekil = form sayfası (`Departmanlar` / `Departman`).
|
|
@@ -1235,6 +1528,17 @@ maxLength/pattern — sözlük `component_get`'te) orada listelenir.
|
|
|
1235
1528
|
] }
|
|
1236
1529
|
```
|
|
1237
1530
|
|
|
1531
|
+
**Mesajı çeviriye bağlamak: `t:` öneki.** `message` düz bir metindir ve translation prop'u ALMAZ;
|
|
1532
|
+
çeviri anahtarı mesajın kendisine önek olarak yazılır:
|
|
1533
|
+
|
|
1534
|
+
```jsonc
|
|
1535
|
+
{ "type": "required", "message": "t:form.emailRequired", "value": true, "isActive": true }
|
|
1536
|
+
```
|
|
1537
|
+
|
|
1538
|
+
Runtime `t:` ile başlayan mesajı anahtar sayar ve normal fallback zincirinden çözer (aktif dil →
|
|
1539
|
+
varsayılan dil → anahtarın kendisi); önek yoksa metin olduğu gibi gösterilir. Çözüm çalışma
|
|
1540
|
+
anında olduğu için şema varsayılanlarına dokunmak gerekmez.
|
|
1541
|
+
|
|
1238
1542
|
Geçerli `type` değerleri: `required` · `email` · `regex` · `max-length` · `min-length` ·
|
|
1239
1543
|
`max-value` · `min-value` · `value-options`. Üç tuzak ölçüldü (crm koşumu B-9):
|
|
1240
1544
|
|
|
@@ -1268,18 +1572,29 @@ start → [setter] page_container.isLoading = true
|
|
|
1268
1572
|
└─ else → [setter] CREATE etiketleri
|
|
1269
1573
|
```
|
|
1270
1574
|
|
|
1271
|
-
> **Condition adımı `always` dalını kural dallarıyla BİRLİKTE taşır
|
|
1272
|
-
>
|
|
1273
|
-
> göre. `rules`: `{ id, expression, type:'if' }` + `{ id, expression:'', type:'else' }`.
|
|
1575
|
+
> **Condition adımı `always` dalını kural dallarıyla BİRLİKTE taşır** — ama `always` her hâlükârda
|
|
1576
|
+
> KOŞMAZ. Motor onu yalnız **eşleşen dalın** bitişinden çağırır:
|
|
1274
1577
|
>
|
|
1275
|
-
>
|
|
1276
|
-
>
|
|
1277
|
-
>
|
|
1278
|
-
>
|
|
1578
|
+
> ```ts
|
|
1579
|
+
> // condition.ts — always'in TEK çıkışı eşleşen dalın callback'idir
|
|
1580
|
+
> engine.next(rule.id, { ...definition, completed: () => engine.next('always', definition) })
|
|
1581
|
+
> ```
|
|
1279
1582
|
>
|
|
1280
|
-
>
|
|
1281
|
-
>
|
|
1282
|
-
>
|
|
1583
|
+
> Yani şu üç hâlde `always` **hiç** koşmaz: `rules` boş · `rules[0].type !== 'if'` · hiçbir ifade
|
|
1584
|
+
> tutmuyor ve boş ifadeli bir `else` yok. **Yükleniyor bayrağını `always` ile kapatıyorsan
|
|
1585
|
+
> zinciri boş ifadeli `else` ile kapatmak ZORUNDASIN** — yukarıdaki iskelette `else` dalı tam da
|
|
1586
|
+
> bu yüzden var. `else`'siz bir zincirde ifade tutmazsa bayrak açık kalır ve sayfa sonsuza kadar
|
|
1587
|
+
> yükleniyor görünür. Gateway `FLOW-020` bunu uyarıyla söyler.
|
|
1588
|
+
>
|
|
1589
|
+
> Sözleşmenin tamamı (GUID id zorunluluğu, dal adı = rule id, `else` fallback kuralı, zincir
|
|
1590
|
+
> sırası) aşağıdaki tuzak 6'da.
|
|
1591
|
+
>
|
|
1592
|
+
> **Kural ifadesi patlarsa kural EŞLEŞMEMİŞ sayılır** — `runCode` `undefined` döner,
|
|
1593
|
+
> `Boolean(undefined)` false'tur — ve zincir bir sonraki kurala, oradan `else`'e geçer. Ama bu
|
|
1594
|
+
> tamamen sessiz değildir: hata işaretlenir ve sıradaki `engine.next` onu tüketip **hata yolu
|
|
1595
|
+
> varsa akışı oraya saptırır** (`flow-engine.ts` `consumeExpressionError`), yani beklediğin dal
|
|
1596
|
+
> yerine `errorSteps` koşar. Bu yüzden condition ifadeleri guard'lı yazılır — özellikle
|
|
1597
|
+
> `Page.user` okuyanlar (Kural 8).
|
|
1283
1598
|
|
|
1284
1599
|
**İki ayrı ucun sonucunu tek tabloya yazmak:** `mapping` tek kaynak alır, o yüzden birleştirmeyi
|
|
1285
1600
|
`value.type: 'code'` ile yap — ilgisiz kayıtları da orada süz:
|
|
@@ -1337,20 +1652,24 @@ start → [setter] btn_save.isLoading = true
|
|
|
1337
1652
|
|
|
1338
1653
|
- **Upsert deseni:** tek POST ucu hem create hem update yapar — `id` query-string'den, alanlar
|
|
1339
1654
|
`source:'body'`'den. Entity başına iki uç yazmaya gerek yok.
|
|
1340
|
-
- **
|
|
1341
|
-
ana akışın kalanını
|
|
1655
|
+
- **Form akışında hata yolunu `condition Steps.<adımAdı>.error` ile kur**, `errorSteps` ile
|
|
1656
|
+
değil: `errorSteps` ana akışın kalanını devralır, yani yükleniyor bayrağını kapatma · modal'ı
|
|
1657
|
+
kapatma · tabloyu tazeleme adımlarını hata akışında yeniden kurman gerekir — kurmazsan bayrak
|
|
1658
|
+
açık kalır. İki yolun karşılaştırması ve hata metninin nerede durduğu Kural 1c'nin §hata yolu
|
|
1659
|
+
bloğunda.
|
|
1342
1660
|
- Geri bildirim `notification` komponentiyle verilir (`kind` · `header` · `content` · `timeout` ·
|
|
1343
1661
|
`showCloseButton` · `style`), `alert` adımıyla değil.
|
|
1344
1662
|
|
|
1345
1663
|
> **`isHidden`: ŞEMAYA yazmak ile SETTER ile yazmak AYRI yollardır.** Runtime tarafı ortak:
|
|
1346
1664
|
> `RenderComponent` her düğümü `{#if !props.isHidden}` ile çizer, yani akıştaki setter
|
|
1347
|
-
> `isHidden` yazınca komponent katalogda o prop'u tanımlamasa bile gizlenir. **Şema yolu
|
|
1348
|
-
> katalogla sınırlıdır
|
|
1349
|
-
>
|
|
1350
|
-
>
|
|
1351
|
-
>
|
|
1352
|
-
> `
|
|
1353
|
-
>
|
|
1665
|
+
> `isHidden` yazınca komponent katalogda o prop'u tanımlamasa bile gizlenir. **Şema yolu
|
|
1666
|
+
> katalogla sınırlıdır** ama artık neredeyse her komponent tanımlıyor: **101 kaydın 99'u**
|
|
1667
|
+
> (ölçüm 2026-09-08; 2026-08-26'daki toplu ekleme öncesi 81'de 37 idi). Tanımlamayan yalnız
|
|
1668
|
+
> iki kap var: **`slot` · `widget-area`** — onların içindekini gizlemek için sarmalayıcı
|
|
1669
|
+
> kullan. Eskiden tanımlamayan `text` · `table` · `datatable` · `dropdown` · `multi-select` ·
|
|
1670
|
+
> `tag-input` · `tabs` · `notification` · `toast` · `datepicker` ailesi gibi komponentlere
|
|
1671
|
+
> artık doğrudan `props.isHidden` yazılabilir; sırf gizlemek için `container`'a sarmak
|
|
1672
|
+
> GEREKMEZ. Tek doğru kaynak `component_get` + `page_schema_validate` kuru koşusudur.
|
|
1354
1673
|
>
|
|
1355
1674
|
> **`appearance.isHidden` bir kaçış yolu DEĞİLDİR:** kaydedilir ama runtime hiçbir yerde okumaz
|
|
1356
1675
|
> (renderer yalnız `props.isHidden`'a bakar) — komponent görünmeye devam eder. Başlangıçta gizli
|
|
@@ -1540,6 +1859,21 @@ hiçbiri** bağlı değildi; üç portalın da rol menüsü boş çıkıyor, pan
|
|
|
1540
1859
|
> `Host: <org>.<suffix>` + `X-Environment` başlıklarıyla. Ham `curl` yerine tool'u kullanmak
|
|
1541
1860
|
> yeterlidir.
|
|
1542
1861
|
>
|
|
1862
|
+
> **Yerleşimi görüntüsüz ölçmek.** Taşma/çakışma şüphesinde `page_screenshot(layoutReport: true)`:
|
|
1863
|
+
> `layoutSummary.overflowing` boş değilse içeriğine sığmayan kutu, `outsideViewport` boş değilse
|
|
1864
|
+
> hiç görünmeyen düğüm var; `zeroSized` çizilmemiş komponenti gösterir. Runtime düğümleri
|
|
1865
|
+
> `data-element-id` basmıyorsa yanıt `layoutReportUnavailable` der — tool tahmin üretmez.
|
|
1866
|
+
>
|
|
1867
|
+
> **Üye kimliğiyle doğrulama (`asUser`).** Kapının kapalı olduğunu görmek yarısıdır; açık
|
|
1868
|
+
> olduğunu görmek diğer yarısı. `page_runtime_get` ve `page_screenshot` aynı `asUser` alanını
|
|
1869
|
+
> alır: uygulamanın kendi giriş ucundan (`microservice_execute`) aldığın üye jetonunu verirsin,
|
|
1870
|
+
> gateway o jetonu **hem `Authorization` başlığında hem `NG_AccessToken` çerezinde** taşır.
|
|
1871
|
+
> Çerez okuyan bir middleware ile başlık okuyan bir middleware aynı çağrıdan geçer — iki tool da
|
|
1872
|
+
> aynı kimlik kanalını kullanır. `page_screenshot` ayrıca `cookies: {ad: değer}` ile uygulamanın
|
|
1873
|
+
> kendi oturum çerezlerini enjekte eder. `asUser`/`cookies` ile `anonymous` birlikte verilemez;
|
|
1874
|
+
> gateway'in servis jetonu (varsayılan kimlik) uygulamanın `users` tablosuna çözülmeyebilir —
|
|
1875
|
+
> korumalı sayfada boş panel görüyorsan önce `identity` alanına bak, sonra `asUser` ile tekrarla.
|
|
1876
|
+
>
|
|
1543
1877
|
> `page.roleIds` bu dalla birlikte de kapı değildir: rol ayrımını sayfa değil **uç** yapar.
|
|
1544
1878
|
|
|
1545
1879
|
> **Rol okurken dizi bekleme.** `set-user` DTO'su `roles` dizisini çoğu kurulumda düşürür
|
|
@@ -1603,6 +1937,24 @@ micro-op hattına dönün.
|
|
|
1603
1937
|
> setter'ı sessizce hiçbir şey yazmadı — sayfa boş liste ile açıldı, konsolda hata yok.
|
|
1604
1938
|
> `flow_update` ile aynı gövdeyi yeniden kaydetmek düzeltti. Kural: **şemadan bir düğüm sildiysen,
|
|
1605
1939
|
> o düğümü hedefleyen her flow'u yeniden kaydet.**
|
|
1940
|
+
>
|
|
1941
|
+
> **Akış silen yama artık istek gönderilmeden REDDEDİLİR.** Platform referanssız kalan akışı
|
|
1942
|
+
> KALICI siler; uyarı yamadan sonra geldiğinde "önce yedekle" tavsiyesi uygulanamıyordu (09-05
|
|
1943
|
+
> koşusunda sekiz adımlı giriş akışı sıfırdan yeniden yazıldı). Aynı kontrol `set_event` ve
|
|
1944
|
+
> `remove_event` için de çalışır — bir olayın bağını değiştirmek de akış öldürür ve o yolda hiç
|
|
1945
|
+
> uyarı yoktu. Silinmesini bilerek istiyorsanız çağrıyı `allowFlowDeletion: true` ile tekrarlayın;
|
|
1946
|
+
> yanıt `deletedFlows` ile hangi akışların gittiğini listeler.
|
|
1947
|
+
>
|
|
1948
|
+
> **FLOW-018 artık silinen düğümün ALT AĞACINI da görüyor.** Eskiden yalnız op'un kendi
|
|
1949
|
+
> `target`'ına bakılıyordu: bir kapsayıcı silinince ÇOCUĞUNA yazan setter sessizce kopuyor ve
|
|
1950
|
+
> uyarı hiç çıkmıyordu (09-05, `sign_in_form` → `btn_sign_in`).
|
|
1951
|
+
>
|
|
1952
|
+
> **Gateway artık bunu söylüyor (FLOW-018).** `remove_component` içeren bir yamada gateway sayfanın
|
|
1953
|
+
> akışlarını okur ve silinen düğümü hedefleyen setter adımlarını uyarı olarak listeler: hangi akış,
|
|
1954
|
+
> hangi adım, hangi hedef. Uyarıyı gördüğünde yapılacak tek şey `flow_update` ile aynı gövdeyi
|
|
1955
|
+
> yeniden kaydetmektir. Ters yönü (`silinen düğümün referans verdiği` akışların platformca kalıcı
|
|
1956
|
+
> silinmesi) ayrı bir uyarı kapsar; ikisi birlikte çıkabilir. Ölçüm 2026-09-04 (benchmark 4. koşu):
|
|
1957
|
+
> uyarı yokken aynı tuzak ~8 dakika teşhis aldı ve yalnız ekran görüntüsüyle görüldü.
|
|
1606
1958
|
|
|
1607
1959
|
## Bilinen sınırlar
|
|
1608
1960
|
|
|
@@ -1667,10 +2019,11 @@ micro-op hattına dönün.
|
|
|
1667
2019
|
`isHidden` prop'u yok (Kural 1g'deki sarmalayıcı çözümü). Bir prop'u kullanmadan önce
|
|
1668
2020
|
`component_get`'e bak; eksikse ürün sahibine katalog güncellemesi olarak bildir.
|
|
1669
2021
|
|
|
1670
|
-
- **`container.title` `states.isWrapper: true` iken başlık ÇİZMEZ.**
|
|
2022
|
+
- **`container.title` varsayılanı boştur ve `states.isWrapper: true` iken başlık ÇİZMEZ.** Başlıksız
|
|
2023
|
+
normal container da `__header` bloğu üretmez; bant istiyorsan `title` değerini açıkça yaz.
|
|
2024
|
+
Wrapper kaplar salt düzen
|
|
1671
2025
|
elemanıdır; başlığı da `__header` bloğunu da render etmez (klinik ölçümü: `__header` sayısı 0).
|
|
1672
|
-
`isWrapper: false` olan kapta başlık normal çizilir
|
|
1673
|
-
varsayılan "Container title" göründü). Kart başlığını garantiye almak istiyorsan kabın
|
|
2026
|
+
`isWrapper: false` olan ve başlığı açıkça verilen kapta başlık normal çizilir. Kart başlığını garantiye almak istiyorsan kabın
|
|
1674
2027
|
`title`'ına güvenme, **içine bir `text` komponenti** koy.
|
|
1675
2028
|
- **Kod prop'unun ifadesi `ref`'te ve `{{ }}` sarılı olmalı.** `{type:'code', ref:"'' + Row.value"}`
|
|
1676
2029
|
(süssüz) ekrana ifadenin **kendisini** basar; ifade yalnız `data`'da olursa prop **boş**
|