@appaflytech/zeyrek-ai-mcp 0.0.6 → 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.
Files changed (91) hide show
  1. package/.env.example +2 -2
  2. package/.env.production.example +8 -0
  3. package/README.md +9 -8
  4. package/dist/config.js +18 -3
  5. package/dist/knowledge/backendConstraints.js +85 -0
  6. package/dist/knowledge/componentCatalog.js +357 -54
  7. package/dist/knowledge/componentEvents.js +120 -25
  8. package/dist/knowledge/functionGuards.js +134 -0
  9. package/dist/knowledge/normalize.js +53 -2
  10. package/dist/knowledge/outlines.js +31 -0
  11. package/dist/knowledge/policy.js +14 -5
  12. package/dist/knowledge/rules.js +343 -1
  13. package/dist/platform/csv.js +123 -0
  14. package/dist/platform/errors.js +62 -3
  15. package/dist/platform/http.js +1 -0
  16. package/dist/platform/responses.js +16 -4
  17. package/dist/platform/screenshot.js +18 -1
  18. package/dist/resources/examples/flow-call-function.json +66 -0
  19. package/dist/resources/examples/function-total.json +70 -0
  20. package/dist/resources/examples/microfunction-node-sum.json +56 -0
  21. package/dist/resources/examples/page-dynamic-form.json +1 -1
  22. package/dist/resources/examples/page-sign-in.json +1 -1
  23. package/dist/resources/guides/component.md +13 -1
  24. package/dist/resources/guides/entity.md +321 -17
  25. package/dist/resources/guides/expressions.md +3 -0
  26. package/dist/resources/guides/functions.md +262 -0
  27. package/dist/resources/guides/getting-started.md +5 -0
  28. package/dist/resources/guides/merge.md +231 -0
  29. package/dist/resources/guides/microfunction.md +166 -0
  30. package/dist/resources/guides/microservice.md +61 -2
  31. package/dist/resources/guides/modify-existing.md +23 -0
  32. package/dist/resources/guides/page.md +20 -4
  33. package/dist/resources/guides/translation.md +24 -0
  34. package/dist/resources/guides/workflow.md +1 -1
  35. package/dist/resources/schema-fingerprint.json +4 -4
  36. package/dist/resources/schemas/AnalyzeImportQuery.json +51 -0
  37. package/dist/resources/schemas/ApplyMergePlanCommand.json +19 -0
  38. package/dist/resources/schemas/CreateBulkRowCommand.json +3 -0
  39. package/dist/resources/schemas/CreateEnvironmentCommand.json +31 -0
  40. package/dist/resources/schemas/CreateGlobalFunctionCommand.json +95 -0
  41. package/dist/resources/schemas/CreateImportPlanCommand.json +278 -0
  42. package/dist/resources/schemas/CreateMergePlanCommand.json +34 -0
  43. package/dist/resources/schemas/CreateMicrofunctionCommand.json +117 -0
  44. package/dist/resources/schemas/CreateMicrofunctionRuntimeCommand.json +51 -0
  45. package/dist/resources/schemas/CreateMicroserviceCommand.json +119 -1
  46. package/dist/resources/schemas/CreateWorkflowCommand.json +13 -2
  47. package/dist/resources/schemas/DataJobDto.json +267 -0
  48. package/dist/resources/schemas/ExportRowsCommand.json +172 -0
  49. package/dist/resources/schemas/Filter.json +3 -1
  50. package/dist/resources/schemas/GetRowsQuery.json +3 -1
  51. package/dist/resources/schemas/GlobalFunctionDto.json +89 -0
  52. package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +249 -0
  53. package/dist/resources/schemas/ImportAnalysisDto.json +401 -0
  54. package/dist/resources/schemas/ImportPlanDto.json +260 -0
  55. package/dist/resources/schemas/ImportSampleDto.json +90 -0
  56. package/dist/resources/schemas/InvokeMicrofunctionCommand.json +25 -0
  57. package/dist/resources/schemas/PreviewMicroserviceCommand.json +119 -1
  58. package/dist/resources/schemas/PreviewWorkflowCommand.json +13 -2
  59. package/dist/resources/schemas/ResolveMergeConflictsCommand.json +58 -0
  60. package/dist/resources/schemas/RevertMergePlanCommand.json +19 -0
  61. package/dist/resources/schemas/RunImportCommand.json +62 -0
  62. package/dist/resources/schemas/StepDto.json +13 -2
  63. package/dist/resources/schemas/UpdateBulkRowCommand.json +3 -0
  64. package/dist/resources/schemas/UpdateEntityCommand.json +3 -1
  65. package/dist/resources/schemas/UpdateGlobalFunctionCommand.json +66 -0
  66. package/dist/resources/schemas/UpdateMicrofunctionCommand.json +121 -0
  67. package/dist/resources/schemas/UpdateMicrofunctionRuntimeCommand.json +54 -0
  68. package/dist/resources/schemas/UpdateMicroserviceCommand.json +119 -1
  69. package/dist/resources/schemas/UpdateWorkflowCommand.json +13 -2
  70. package/dist/server.js +15 -3
  71. package/dist/tools/activities.js +40 -0
  72. package/dist/tools/automations.js +14 -5
  73. package/dist/tools/common.js +16 -0
  74. package/dist/tools/dependencies.js +1 -1
  75. package/dist/tools/environments.js +52 -0
  76. package/dist/tools/files.js +51 -50
  77. package/dist/tools/flows.js +95 -2
  78. package/dist/tools/functions.js +331 -0
  79. package/dist/tools/importSchemas.js +79 -0
  80. package/dist/tools/imports.js +241 -0
  81. package/dist/tools/merges.js +113 -0
  82. package/dist/tools/microfunctions.js +155 -0
  83. package/dist/tools/microservices.js +42 -3
  84. package/dist/tools/pages.js +62 -10
  85. package/dist/tools/platformInfo.js +4 -1
  86. package/dist/tools/revisions.js +94 -0
  87. package/dist/tools/rows.js +342 -22
  88. package/dist/tools/screenWrite.js +11 -2
  89. package/dist/tools/templates.js +32 -5
  90. package/dist/tools/workflows.js +24 -6
  91. package/package.json +3 -1
@@ -0,0 +1,166 @@
1
+ # Microfunction Rehberi
2
+
3
+ Microfunction, kullanıcının yazdığı **tek bir fonksiyonun** platformun dışında, kendi
4
+ runtime'ında koşmasıdır: Node ya da Python kodu kaydedilir, yayınlanır, workflow adımı onu
5
+ çağırır ve çıktısı sonraki adımlara akar. Platformun JavaScript ifade motoru (global function'lar,
6
+ code step) sürecin İÇİNDE koşar; microfunction ise ayrı bir runtime'dadır — bu yüzden ağır iş,
7
+ üçüncü parti kütüphane ve zaman aşımı riski taşıyan işler oraya taşınır.
8
+
9
+ Kayıtlar **proje + environment** kapsamlıdır (`development` ile `production` ayrı kayıtlardır);
10
+ `microfunction_list` bir uygulamaya değil projeye bakar. Süzme ve sayfalama uçta yapılır:
11
+ `searchTerm` ad, slug ve açıklamada arar, `status` durum süzgecidir, `pageIndex`/`pageLength` sayfa
12
+ verir (gateway kendi çağrısında 200 gönderir; platform varsayılanı 10'dur).
13
+
14
+ ## Ne zaman microfunction, ne zaman code step
15
+
16
+ | İhtiyaç | Doğru yer |
17
+ |---|---|
18
+ | Birkaç satır dönüşüm, alan eşleme, koşul | `code` step / ifade (aynı süreç, en ucuz) |
19
+ | İfadelerde çıplak adla çağrılacak yardımcı | global function (`global_function_create`, JS) |
20
+ | Kütüphane gerektiren iş (kriptografi, PDF, görüntü, parse) | microfunction (zip kaynak) |
21
+ | Python gereken iş | microfunction — platformun ifade motoru YALNIZ JavaScript'tir |
22
+ | Uzun süren/CPU yiyen iş | microfunction (kendi bütçesi, API sürecini bloke etmez) |
23
+
24
+ Global function'lar JS'tir ve Python fonksiyonlarına bağlanmaz; microfunction çağrısı yalnız
25
+ workflow adımından (ve test için `microfunction_invoke`'tan) yapılır.
26
+
27
+ ## Çalışma zamanı sözleşmesi (protocol 1)
28
+
29
+ Kullanıcı kodu **tek bir handler** dışa aktarır. Inline kaynakta dosya adı SABİTTİR: Node'da
30
+ `function.js`, Python'da `function.py`; entrypoint `function.handler`'dır ve gönderilmez.
31
+
32
+ ```js
33
+ // node — function.js
34
+ exports.handler = async (args, context) => {
35
+ return { total: args.a + args.b, environment: context.environment }
36
+ }
37
+ ```
38
+
39
+ ```python
40
+ # python — function.py
41
+ def handler(args, context):
42
+ return {"total": args["a"] + args["b"], "environment": context["environment"]}
43
+ ```
44
+
45
+ - `args` — adımın `rule.expression`'ından üretilen argüman nesnesi. Fonksiyonun
46
+ `parameterDtoId`'si yoksa `{}` gelir.
47
+ - `context` — **salt okunur anlık görüntü**. İçine yazmak hiçbir şeyi değiştirmez; akışa dönen
48
+ tek kanal fonksiyonun DÖNÜŞ DEĞERİdir.
49
+
50
+ `context` şekli (ölçüldü, `MicrofunctionStep.BuildContext`):
51
+
52
+ ```jsonc
53
+ {
54
+ "input": {}, // akışın parameterDto girdisi
55
+ "variables": {}, // workflow değişkenleri (middleware'in kurduğu 'user' dahil)
56
+ "steps": { "<adım adı>": { "data": {}, "error": { "code": null, "message": null, "type": null } } },
57
+ "user": { "id": "…", "email": "…", "roles": [] },
58
+ "request": { "headers": {}, "queryString": {} },
59
+ "triggerSource": {},
60
+ "language": "tr",
61
+ "project": "<proje slug'ı>",
62
+ "environment": "development"
63
+ }
64
+ ```
65
+
66
+ **`request` yalnız `headers` + `queryString` taşır** ve `authorization` · `cookie` ·
67
+ `x-impersonated-user-id` başlıkları AYIKLANIR (ölçüldü 2026-09-10) — token'ı fonksiyona taşımaya
68
+ çalışmayın, taşınmaz. Çerez okuma yolu yoktur.
69
+
70
+ Yanıt zarfını shim üretir; `microfunction_invoke` bunu olduğu gibi döner:
71
+
72
+ ```jsonc
73
+ { "protocol": 1, "ok": true, "output": { "total": 3 }, "error": null, "logs": [], "durationMs": 12 }
74
+ ```
75
+
76
+ - `ok: false` ⇒ `error: { type, message, stack }` ve adım **fail dalına** düşer.
77
+ - `logs` yalnız `preview: true` çağrılarında dolar (`console.log` / `print` yakalanır). Normal
78
+ koşumda log toplanmaz — hata ayıklarken `microfunction_invoke(preview: true)` kullanın.
79
+ - İstek gövdesi (args + context) 5 MB'ı aşarsa adım `MicrofunctionPayloadTooLargeException` ile
80
+ fail dalına düşer: bütün tabloyu fonksiyona geçirmeyin, işi fonksiyona taşıyacak kadarını geçirin.
81
+
82
+ ## Yaşam döngüsü: kayıt yayınlanmadan ÇALIŞMAZ
83
+
84
+ ```
85
+ draft ──publish──▶ publishing ──▶ published ──update──▶ published + hasUnpublishedChanges
86
+ └────────▶ publish-failed (publishError)
87
+ ```
88
+
89
+ 1. `microfunction_create` kaydı **draft** açar. `publish: true` verirseniz aynı çağrıda yayın istenir.
90
+ 2. Yayın **asenkrondur**: çağrı `publishing` döner, kuyruk paketi runtime'a kurar ve bir `probe`
91
+ çağrısıyla duman testi yapar. Sözdizimi/import hatası **yayın anında** `publish-failed` olur —
92
+ koşumda değil. Durumu `microfunction_get` ile birkaç saniye arayla okuyun.
93
+ 3. Yayındaki kaydı `microfunction_update` ile değiştirirseniz runtime **ESKİ sürümü koşmaya
94
+ devam eder**: `hasUnpublishedChanges: true` olur (`revision` ≠ `publishedRevision`). Yeni kodu
95
+ canlıya almak için `microfunction_publish`.
96
+ 4. `microfunction_delete` runtime'daki fonksiyonu da kaldırır; bir workflow adımı kaydı
97
+ kullanıyorsa 400 ile reddedilir.
98
+
99
+ ## Workflow adımı (WF-MF-001)
100
+
101
+ Adım tipi `microfunction`; `workflow`, `automation` ve `middleware` akışlarının hepsinde
102
+ kullanılabilir. Kuralı iki alan taşır:
103
+
104
+ ```jsonc
105
+ {
106
+ "id": "<GUID>",
107
+ "name": "toplam",
108
+ "type": "microfunction",
109
+ "description": "İki sayıyı microfunction'da toplar.",
110
+ "rule": {
111
+ "microfunctionId": "<published kaydın id'si>",
112
+ "expression": "({ a: input.a, b: input.b })"
113
+ },
114
+ "branches": [
115
+ { "id": "<GUID>", "name": "success", "type": "success", "nextStepId": "<sonraki adım>" },
116
+ { "id": "<GUID>", "name": "fail", "type": "fail", "nextStepId": "<hata adımı>" }
117
+ ]
118
+ }
119
+ ```
120
+
121
+ - `microfunctionId` **zorunludur** ve gateway kaydı çağrıdan önce okur: durum `published` değilse
122
+ (ya da kayıt o ortamda yoksa) istek platforma GÖNDERİLMEZ. Adım taslak bir fonksiyona bağlıysa
123
+ akış kaydedilir, koşar ve sessizce fail dalına düşer (`MicrofunctionNotPublishedException`) —
124
+ ön-denetimin varlık sebebi budur.
125
+ - `expression` argüman nesnesini üreten JavaScript ifadesidir; şemayı `microfunction_get`
126
+ çıktısındaki `parameterScheme` verir. Fonksiyonun parametre DTO'su varken ifade boşsa gateway
127
+ uyarır (fonksiyon `args` içinde hiçbir alan göremez).
128
+ - Çıktı sonraki adımlara `Steps.<adım adı>.data` ile akar; şemasını `returnDtoId` belirler.
129
+ - Adım **senkrondur**: akış fonksiyon dönene kadar bekler. Zaman aşımı fonksiyonun
130
+ `timeoutSeconds` bütçesidir, aşılırsa fail dalı.
131
+ - `workflow_preview` adımı GERÇEK runtime'da koşturur; preview'ın rollback garantisi fonksiyonun
132
+ dış dünyada yaptığı işi geri ALMAZ.
133
+
134
+ Tam gövde örneği: `ngapps://examples/microfunction-node-sum`.
135
+
136
+ ## Built-In ve AWS Lambda farkı
137
+
138
+ | | `built-in` | `aws-lambda` |
139
+ |---|---|---|
140
+ | Nerede koşar | Platformun kendi Fission kümesi | Müşterinin AWS hesabı |
141
+ | Runtime kaydı | YOK — `runtimeId` verilmez | `microfunction_runtime_create` ile zorunlu |
142
+ | Zaman aşımı tavanı | 300 s | 900 s |
143
+ | `memoryMb` | kaydedilir, küme limiti geçerlidir | gerçekten uygulanır |
144
+ | Ölçüm alanları | `billedDurationMs`/`memoryUsedMb` boş | Lambda raporundan dolar |
145
+
146
+ `azure-functions` enum'da tanımlıdır ama v1'de reddedilir (Faz 2). Lambda hesabı kimlik
147
+ bilgilerini düz metin tutar (Datasource emsali) ve DTO'da maskeli döner — dar yetkili bir IAM
148
+ kullanıcısı verin, `roleArn` fonksiyonun koşacağı execution rolüdür ve **zorunludur** —
149
+ deseni tutmayan hesap gateway'de durur (MFR-001, block). Kaydettikten sonra
150
+ `microfunction_runtime_test_connection` ile doğrulayın.
151
+
152
+ ## Sınırlar (v1)
153
+
154
+ - **Bağımlılık build'i yok:** inline kod yalnız standart kütüphanedir; bağımlılık zip içinde gelir.
155
+ - **MCP'den zip yükleme ve indirme yok** (`sourceKind: 'archive'` kaydı açılabilir, dosya
156
+ Studio'dan yüklenir) — Faz 2. Yüklenmiş zip platform ucunda okunabilir durumdadır
157
+ (`GET /{proje}/microfunctions/{id}/archive`, `application/zip`) ve Studio inspector'ında bir
158
+ indirme düğmesi taşır.
159
+ - `timeoutSeconds` ve `memoryMb` komutta non-nullable int'tir: **göndermezseniz 0 gider ve platform
160
+ 422 döner.** Gateway değer uydurmaz, eksikliği çağrıdan önce söyler (MF-001, block; ürün
161
+ varsayılanları 30 / 256). Aynı kural provider ↔ `runtimeId` eşleşmesini, inline kaynakta `code`
162
+ zorunluluğunu ve env anahtarlarını da çağrıdan önce denetler.
163
+ - Env değişkenleri düz metin saklanır; anahtar `^[A-Z_][A-Z0-9_]*$`, toplam ≤ 4 KB. Sır yönetimi
164
+ için kullanmayın.
165
+ - Asenkron (fire-and-forget) çağrı, preview ekranı, microservice'in doğrudan microfunction kaynağı
166
+ olması ve metering Faz 2'dedir.
@@ -188,9 +188,12 @@ DTO'dan süzülmez (WF-026 — `platform_guide('workflow')` §Hata yolu). Sözle
188
188
  `ArgumentNullException(key)`, farklı alias verilirse "missing FROM-clause entry" gelir.
189
189
  - `sort` ve `limit` **her zaman** verilir (MS-008, block) — aşağıya bak.
190
190
  - Filtrelerde `value` bir **JavaScript ifadesidir** — sabit metin tırnak içinde
191
- (`"'ACTIVE'"`), dinamik değer ifade olarak (`"input.status"`).
191
+ (`"'ACTIVE'"`), dinamik değer ifade olarak (`"input.status"`). **İki operatör bunun dışındadır:**
192
+ `isnull` ve `isnotnull` değer taşımaz — `value` verilmez, `source` da zorunlu değildir; verirsen
193
+ platform yok sayar, doğrulama da değer beklemez.
192
194
  - **Operatör sözlüğü kapalıdır:** `eq · neq · lt · lte · gt · gte · contains · icontains ·
193
- in · notin · startswith · endswith · istartswith · iendswith`. **`like` YOKTUR** — metin
195
+ in · notin · startswith · endswith · istartswith · iendswith · isnull · isnotnull`.
196
+ **`like` YOKTUR** — metin
194
197
  araması `contains`/`icontains` iledir. Kritik tuzak: platform bilinmeyen operatörü 400 ile
195
198
  reddetmez, **sessizce `eq`'e düşürür** (enum çözümlemesi unknown'da default'a düşer) — uç
196
199
  testten geçer ama arama hiçbir şey döndürmez. Gateway MS-012/WF-015 bunu istek gitmeden keser.
@@ -531,6 +534,62 @@ kabul etti. Ayrıntı ve doğru rol kapısı tarifi: `platform_guide('middleware
531
534
  > rota `/{project}/m/{application}/{microservice SLUG'ı}`'dır ( `url` alanı rotaya GİRMEZ) ve
532
535
  > `Host: <org>.<suffix>` + `X-Environment` başlıkları zorunludur.
533
536
 
537
+ ## Alias nerede geçerli
538
+
539
+ Alias bir **SQL tablo takma adıdır**: yalnız okunan tarafta anlamı vardır. Sözleşme iki ayrı
540
+ tiple modellenmiştir ve ikisi karıştırılırsa alan sessizce düşer.
541
+
542
+ | Yer | Tip | Alanlar |
543
+ |---|---|---|
544
+ | `selectFields[]` · `returnFields[]` | `TableSelect` | `alias` · `fieldId` · `path` · `fieldSlug` |
545
+ | `filters[]` · `joins[]` | filtre/join | `alias` (+ kendi alanları) |
546
+ | `sourceParameters.alias` | kök alias | join varken ZORUNLU, kök entity'nin slug'ı |
547
+ | **`fields[]` (yazılacak alanlar)** | `TableField` | `fieldId` · `source` · `value` · `folderId` · `order` · `writeOn` — **`alias` YOK** |
548
+
549
+ `fields[]` yalnız `create` / `update` / `upsert` operasyonlarında bulunur ve WHERE değil SET
550
+ üretir: hangi tabloya yazılacağı zaten `entityId` ile bellidir, takma ada ihtiyaç yoktur. Aynı
551
+ `TableField` tipi workflow table adımlarının `rule.fields[]` listesinde de kullanılır.
552
+
553
+ Yazma alanına `alias` koyarsan istek **hata vermez**, alan model bağlamada düşer. Gateway bunu
554
+ istek gitmeden gövdeden çıkarır ve `gatewayNormalized` ile bildirir — böylece `silentlyDropped`
555
+ listesi yalnız gerçek kayıpları gösterir.
556
+
557
+ ## Zamanlanmış iş (`type: 'schedule-job'`) — `typeParameters.schedule`
558
+
559
+ Zamanlama tek bir tanımdır; `cronExpression` tek başına verilirse **UTC cron** sayılır (eski gövde).
560
+ Yeni işte tanımı `typeParameters.schedule` ile yazın ve kaydetmeden önce
561
+ `microservice_schedule_forecast` ile sıradaki koşuları görün.
562
+
563
+ | Alan | Değer |
564
+ |---|---|
565
+ | `mode` | `once` · `interval` · `cron` |
566
+ | `timeZoneId` | IANA (`Europe/Istanbul`); yoksa `UTC`. Saatler BU dilimde yorumlanır |
567
+ | `startAt` | yerel tarih-saat, dilimsiz (`2026-09-14T09:00:00`); once/interval için, cron'da `end.type:'after'` ile zorunlu |
568
+ | `every` · `unit` | 1–1000 · `minute` `hour` `day` `week` `month` |
569
+ | `timeOfDay` | `HH:mm` — `day`/`week`/`month` için zorunlu |
570
+ | `daysOfWeek` | `monday`…`sunday` — `week` için en az bir |
571
+ | `daysOfMonth` | 1–31, `-1` = ayın son günü — `month` için en az bir |
572
+ | `cronExpression` | Quartz cron (6–7 alan, `?` zorunlu) — yalnız `cron` modu |
573
+ | `end` | `{type:'never'}` · `{type:'on', at}` · `{type:'after', count}` (1–10000) |
574
+
575
+ ```json
576
+ { "mode": "interval", "timeZoneId": "Europe/Istanbul", "startAt": "2026-09-14T00:00:00",
577
+ "every": 2, "unit": "week", "daysOfWeek": ["tuesday", "thursday"], "timeOfDay": "09:00",
578
+ "end": { "type": "after", "count": 30 } }
579
+ ```
580
+
581
+ - Aralık başlangıçtan sayılır: "7 dakikada bir" saat başında sıfırlanmaz, "3 günde bir" ay sonunda
582
+ başa sarmaz, "2 haftada bir" gerçekten iki haftada birdir. Cron'da bunlar DOĞRU İFADE EDİLEMEZ
583
+ (`MON/2` = haftada 3 gün) — bu ihtiyaçlar için `interval` kullanın.
584
+ - `after N` başlangıçtan hesaplanan N'inci koşuda biter; `microservice_schedule_control trigger`
585
+ sayılmaz. Biten iş `microservice_schedule_get`'te `state: 'ended'` görünür.
586
+ - Geçersiz tanım `422` + alan adıyla lokalize mesaj döner (bozuk cron artık `500` değil). `after` ile
587
+ toplam süre sınırlıdır (gün × sayı ≤ 36500, hafta ≤ 5200, ay ≤ 1200).
588
+ - **`schedule` ile `cronExpression` çelişemez.** `microservice_get` ikisini de döndürür; güncellemede
589
+ yalnız `typeParameters.schedule`'ı değiştirin (cron modunda `schedule.cronExpression`). Yalnız
590
+ `cronExpression`'ı değiştiren PUT/PATCH `422 ScheduleCronConflict` alır — sessizce eski cron
591
+ kalmaz. `typeParameters: null` işi zamanlayıcıdan siler.
592
+
534
593
  ## Sık hatalar
535
594
 
536
595
  - `description` boş (MS-014, block — uç listesinde ne işe yaradığı okunamaz)
@@ -25,6 +25,29 @@ yeniden yazımlarda.
25
25
  `view:'part'` ile doğrulayarak yaz.
26
26
  - Silme yerine `replace` tercih et; `remove` kullanacaksan önce o path'i `part` ile görüntüle.
27
27
  - Yanıttaki outline özeti değişikliğin uygulandığı hâli gösterir — teyit için oku.
28
+ - **Kullanıcı fonksiyonunda patch aracı yok:** `function_update` tam gövde yazar ama vermediğin
29
+ alanları mevcut kayıttan doldurur — yalnız `body` göndermen yeter (fonksiyonun tek büyük alanı
30
+ gövdedir). Adı değiştirmeden önce `dependency_graph` (`module:'ui-function'`) ile çağıranları
31
+ bul: `{{ }}`/`code` ifadelerindeki `Functions.<eskiAd>(` çağrıları metinseldir ve kırılır.
32
+
33
+ ## Değiştirmeden önce geçmişe bak
34
+
35
+ Platform her tanım yazmasını append-only bir deftere düşürür. Bir kaydı değiştirmeden önce son
36
+ revizyonunu okumak, başka birinin işinin üstüne yazmayı önler:
37
+
38
+ ```
39
+ revision_list {projectId, module:'page', recordId, pageLength: 3}
40
+ → son satırda revisionNo, operation, actor ve source
41
+ revision_diff {projectId, module:'page', recordId}
42
+ → son iki sürüm arasındaki alan bazlı fark + summaryText
43
+ ```
44
+
45
+ `source` işin nereden geldiğini söyler: `mcp` bu gateway'in kendi izidir, `studio` bir insanın
46
+ Studio'da yaptığıdır, `merge` / `deployment` / `template` / `revert` ise taşıma yollarıdır.
47
+ Son revizyon `studio` ise ve dakikalar önceyse, üstüne yazmadan önce kullanıcıya sor.
48
+
49
+ Gövdenin tamamı gerekirse `revision_get {projectId, id}` — ama büyük sayfalarda MB'lar tutar ve
50
+ yanıt kırpılabilir; ne değiştiğini anlamak için `revision_diff` yeter.
28
51
 
29
52
  ## Uyum kuralları
30
53
 
@@ -479,7 +479,7 @@ Tarif: `platform_guide('middleware')`.
479
479
 
480
480
  **Sözlükler** (`StepType.cs`, `StepParameterValueType.cs` — hepsi küçük harf):
481
481
  `start · microservice · setter · setcookie · validation · condition · redirect · alert ·
482
- confirm · flow-trigger · storage · navigate · code · download · end`
482
+ confirm · flow-trigger · storage · navigate · code · download · function · end`
483
483
  değer tipleri: `static · page · property · storage · variable · code · item · state`
484
484
 
485
485
  > **Sözlükte olmak KOŞACAĞI anlamına gelmez — koşan tipler barındırıcıdan gelir.** Motor yedi
@@ -490,7 +490,7 @@ değer tipleri: `static · page · property · storage · variable · code · it
490
490
  >
491
491
  > | Adım tipi | Web | Mobil | Nerede register ediliyor |
492
492
  > |---|---|---|---|
493
- > | `start` · `setter` · `code` · `condition` · `microservice` · `validation` · `flow-trigger` | ✅ | ✅ | `flow-engine.ts` — motorun kendisi |
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
494
  > | `alert` · `redirect` · `setcookie` · `storage` | ✅ | ✅ | uygulama; mobilde `redirect` navigate, `setcookie` storage uygulamasına eşlenir |
495
495
  > | `confirm` · `download` | ✅ | ❌ | yalnız `Runtime.svelte` |
496
496
  > | `navigate` | ❌ | ✅ | yalnız `ScreenRuntime.tsx` — web'deki karşılığı `redirect` |
@@ -521,6 +521,14 @@ değer tipleri: `static · page · property · storage · variable · code · it
521
521
  > (`Page.*`, komponentlere adıyla erişim, `state.page/app`, `Steps`, `self`/`item`/`event`,
522
522
  > `cookie.get/set`, `await`) ve `value.type` çözümleme tablosu için
523
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')`**.
524
532
 
525
533
  > Bir microservice adımı kaydedildiğinde platform `args.microserviceSchema`'yı
526
534
  > (parameterScheme + returnScheme + `isReturnArray`) kendisi doldurur — `flow_get` ile geri
@@ -812,8 +820,9 @@ kullanır: `page.mappers.ts` `mapPageLayoutToPreview` — layout varsa çizilen
812
820
  >
813
821
  > Kural: **`isWrapper` yalnız gerçekten sayfa boyu kaplaması gereken kap içindir**
814
822
  > (`page_container` böyledir ve öyle kalmalı). Sadece "başlık/çerçeve çizilmesin" diye wrapper
815
- > yapma — o iş `container` için `style` ile (`background:'transparent'`, `border:'none'`),
816
- > `form` için `hideBorders`/`hidePadding` prop'larıyla yapılır. **`states` için micro-op
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
817
826
  > YOKTUR:** yanlış `isWrapper`'ı düzeltmenin tek yolu düğümü `remove_component` +
818
827
  > `add_component` ile yeniden kurmaktır (sonrasında Kural 2'deki flow yeniden kaydetme adımı
819
828
  > ZORUNLU olur).
@@ -1129,6 +1138,13 @@ yapmazsan ekran "platform mavisi" görünür; marka rengine çevirmek tek satır
1129
1138
  BÜTÜN girdileri yuvarlar; aynı şeyi komponent komponent `&__input { borderRadius }` yazarak
1130
1139
  yapmak hem uzun sürer hem de yeni komponent eklendiğinde tutarsızlık üretir.
1131
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
+
1132
1148
  ### 1h-3 — Ölçülmüş hazır bloklar (anket ekranından, olduğu gibi kullanılabilir)
1133
1149
 
1134
1150
  ```jsonc
@@ -123,6 +123,30 @@ Son kullanıcı dili `language-selector` komponentiyle değiştirir (`platform_g
123
123
  prop'lar sayfa yenilenmeden yeniden çözülür — ayrı bir akış kurmana gerek yok, komponenti sayfaya
124
124
  eklemen yeterli. Projede dil tanımlı değilse (`languages` boşsa) liste boş çizilir.
125
125
 
126
+ ## Kareyi ikinci dilde almak: `page_screenshot(language:)`
127
+
128
+ Dil değiştirici **kanıt için gerekli değildir.** Runtime boot dilini şu sırayla seçer:
129
+ `?lang=<kod>` → tarayıcıda kayıtlı seçim → tarayıcı dilleri → projenin varsayılanı
130
+ (`resolveRuntimeLanguage`). `page_screenshot` `language` parametresi adrese o sorgu değerini
131
+ ekler; seçim hem çeviriye bağlı prop'ları hem **çok dilli alanların satır değerlerini** kapsar,
132
+ çünkü aynı değer veri diline de geçirilir.
133
+
134
+ ```jsonc
135
+ { "applicationSlug": "app", "pageSlug": "dashboard", "language": "en" }
136
+ { "applicationSlug": "app", "pageSlug": "dashboard", "language": "tr" } // aynı sayfa, ikinci dil
137
+ ```
138
+
139
+ Bunun pratik sonucu: **referans tasarımına dil değiştirici eklemek zorunda değilsin.** Görsel
140
+ repro'su olan bir ekranı bozmadan iki dilin karesini alabilirsin; `language-selector` yalnız son
141
+ kullanıcı gerçekten dil değiştirecekse gerekir.
142
+
143
+ - Kod projenin `languages` listesinde değilse çağrı **reddedilir**. Runtime tanımadığı kodu yok
144
+ sayıp kareyi varsayılan dilde çizerdi ve "çevrildi" sanılan yanlış bir kare rapora girerdi.
145
+ - Bölgeli kod (`tr-TR`) indirgenir ve indirgeme yanıtta `languageNote` ile bildirilir.
146
+ - Aynı tool'un `colorScheme` parametresi ziyaretçinin tema tercihini sayfa açılmadan eker
147
+ (`localStorage`'daki `zeyrek-viewer-theme-mode`), yani koyu tema karesi için sayfada
148
+ `theme-toggle` bulunması da gerekmez.
149
+
126
150
  ## İstek dili: nereden gelir, hangi ifadede ne denir
127
151
 
128
152
  Her istekte dil şu sırayla çözülür: **`X-Data-Language` başlığı → `Accept-Language` → projenin
@@ -537,7 +537,7 @@ yolunu değiştirir: kapalı yolu deneyip raporuna "kanıtlayamadım" yazma, kan
537
537
  - Join'li table step'inde kök `rule.alias` boş (WF-019, block — Postgres 42601'in sebebi)
538
538
  - Akışta hiç okunmayan `selectFields` alanı (WF-023, warn — gereksiz taşınan sütun)
539
539
  - Adımda ya da akışta `description` yok (WF-024, block — Studio'da adım okunamaz kalır)
540
- - İlişki alanının içini okuyan ifade (WF-020, warn — join yoksa alan düz FK'dır)
540
+ - İlişki alanının içini okuyan ifade (WF-020, warn — join yoksa alan düz FK'dır); `Functions.<ad>()` çağrısı SUNUCUDA GEÇERSİZDİR (`WF-030` block, 2026-09-10) — `function_create source:'workflow'` ile tanımla, çıplak adla çağır
541
541
  - `set-user` adımı olmadan `user` okuyan middleware (MW-003, warn)
542
542
  - Backend zorunlulukları (WF-026, block — istek gitmeden): `name`/`slug`; `returnDtoId` varsa
543
543
  `returnBehavior`, `parameterDtoId` varsa `parameterBehavior` (`primitive` | `object` | `array`),
@@ -1,8 +1,8 @@
1
1
  {
2
- "hash": "0e6bb2b45f8c545b50dc6d6169e7d816d9cb9532ecbaed894307995d537ff3b6",
3
- "generatedAt": "2026-09-09T09:49:52.511Z",
4
- "types": 103,
5
- "files": 73,
2
+ "hash": "7702a2d5d690f0d9b1aeab42e9253096f68dfaca040952b07d6c2911f1a37a7f",
3
+ "generatedAt": "2026-09-14T09:08:38.743Z",
4
+ "types": 185,
5
+ "files": 107,
6
6
  "note": "Şemaları üreten backend kaynaklarının parmak izi. Elle düzenlemeyin: 'npm run generate-schemas' yazar, 'npm run schema:check' denetler.",
7
7
  "missing": []
8
8
  }
@@ -0,0 +1,51 @@
1
+ {
2
+ "schema": {
3
+ "required": [
4
+ "fileId"
5
+ ],
6
+ "type": "object",
7
+ "properties": {
8
+ "datasourceId": {
9
+ "type": "string",
10
+ "format": "uuid"
11
+ },
12
+ "fileId": {
13
+ "minLength": 1,
14
+ "type": "string",
15
+ "format": "uuid"
16
+ },
17
+ "locale": {
18
+ "type": "string",
19
+ "nullable": true
20
+ },
21
+ "headerRow": {
22
+ "minimum": 0,
23
+ "type": "integer",
24
+ "format": "int32",
25
+ "nullable": true
26
+ },
27
+ "csv": {
28
+ "$ref": "#/components/schemas/NgApps.Application.Contexts.Datastore.Imports.ImportCsvOptionsDto"
29
+ }
30
+ },
31
+ "additionalProperties": false
32
+ },
33
+ "components": {
34
+ "schemas": {
35
+ "NgApps.Application.Contexts.Datastore.Imports.ImportCsvOptionsDto": {
36
+ "type": "object",
37
+ "properties": {
38
+ "delimiter": {
39
+ "type": "string",
40
+ "nullable": true
41
+ },
42
+ "encoding": {
43
+ "type": "string",
44
+ "nullable": true
45
+ }
46
+ },
47
+ "additionalProperties": false
48
+ }
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "schema": {
3
+ "type": "object",
4
+ "properties": {
5
+ "projectId": {
6
+ "type": "string",
7
+ "format": "uuid"
8
+ },
9
+ "planId": {
10
+ "type": "string",
11
+ "format": "uuid"
12
+ }
13
+ },
14
+ "additionalProperties": false
15
+ },
16
+ "components": {
17
+ "schemas": {}
18
+ }
19
+ }
@@ -23,6 +23,9 @@
23
23
  "nullable": true
24
24
  },
25
25
  "nullable": true
26
+ },
27
+ "relationsByName": {
28
+ "type": "boolean"
26
29
  }
27
30
  },
28
31
  "additionalProperties": false
@@ -0,0 +1,31 @@
1
+ {
2
+ "schema": {
3
+ "required": [
4
+ "name"
5
+ ],
6
+ "type": "object",
7
+ "properties": {
8
+ "projectId": {
9
+ "type": "string",
10
+ "format": "uuid"
11
+ },
12
+ "name": {
13
+ "minLength": 1,
14
+ "pattern": "\\A(?=.{3,31}\\z)[a-z][a-z0-9_-]*(/[a-z0-9][a-z0-9_-]*)*\\z",
15
+ "type": "string"
16
+ },
17
+ "parentEnvironmentId": {
18
+ "type": "string",
19
+ "format": "uuid",
20
+ "nullable": true
21
+ },
22
+ "includeRecords": {
23
+ "type": "boolean"
24
+ }
25
+ },
26
+ "additionalProperties": false
27
+ },
28
+ "components": {
29
+ "schemas": {}
30
+ }
31
+ }
@@ -0,0 +1,95 @@
1
+ {
2
+ "schema": {
3
+ "required": [
4
+ "body",
5
+ "name",
6
+ "source"
7
+ ],
8
+ "type": "object",
9
+ "properties": {
10
+ "source": {
11
+ "$ref": "#/components/schemas/NgApps.Domain.Contexts.Studio.GlobalFunctions.GlobalFunctionSource"
12
+ },
13
+ "applicationId": {
14
+ "type": "string",
15
+ "format": "uuid",
16
+ "nullable": true
17
+ },
18
+ "pageId": {
19
+ "type": "string",
20
+ "format": "uuid",
21
+ "nullable": true
22
+ },
23
+ "scope": {
24
+ "$ref": "#/components/schemas/NgApps.Domain.Contexts.Studio.GlobalFunctions.GlobalFunctionScope"
25
+ },
26
+ "name": {
27
+ "minLength": 1,
28
+ "type": "string"
29
+ },
30
+ "description": {
31
+ "type": "string",
32
+ "nullable": true
33
+ },
34
+ "isAsync": {
35
+ "type": "boolean"
36
+ },
37
+ "parameters": {
38
+ "type": "array",
39
+ "items": {
40
+ "$ref": "#/components/schemas/NgApps.Application.Contexts.Studio.GlobalFunctions.GlobalFunctionParameterDto"
41
+ },
42
+ "nullable": true
43
+ },
44
+ "body": {
45
+ "minLength": 1,
46
+ "type": "string"
47
+ }
48
+ },
49
+ "additionalProperties": false
50
+ },
51
+ "components": {
52
+ "schemas": {
53
+ "NgApps.Domain.Contexts.Studio.GlobalFunctions.GlobalFunctionSource": {
54
+ "enum": [
55
+ "workflow",
56
+ "studio"
57
+ ],
58
+ "type": "string",
59
+ "format": ""
60
+ },
61
+ "NgApps.Domain.Contexts.Studio.GlobalFunctions.GlobalFunctionScope": {
62
+ "enum": [
63
+ "application",
64
+ "page"
65
+ ],
66
+ "type": "string",
67
+ "format": ""
68
+ },
69
+ "NgApps.Application.Contexts.Studio.GlobalFunctions.GlobalFunctionParameterDto": {
70
+ "type": "object",
71
+ "properties": {
72
+ "name": {
73
+ "type": "string",
74
+ "nullable": true
75
+ },
76
+ "type": {
77
+ "type": "string",
78
+ "nullable": true
79
+ },
80
+ "required": {
81
+ "type": "boolean"
82
+ },
83
+ "defaultValue": {
84
+ "nullable": true
85
+ },
86
+ "description": {
87
+ "type": "string",
88
+ "nullable": true
89
+ }
90
+ },
91
+ "additionalProperties": false
92
+ }
93
+ }
94
+ }
95
+ }