@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,262 @@
1
+ # Fonksiyonlar — iki kaynak, tek biçim
2
+
3
+ Studio kullanıcısı (ya da ajan) **parametreli JavaScript fonksiyonları** tanımlar. Backend tek
4
+ aggregate tutar (`GlobalFunction`, `/global-functions`), ajan sözlüğü `function_*` araçlarıdır; ayrım
5
+ **`source`** bayrağıdır ve kaydedildikten sonra değişmez — tarayıcıda `Functions.<ad>()`, sunucuda `<ad>()`:
6
+
7
+ | `source` | Nerede çalışır | Nasıl çağrılır | Kapsam |
8
+ |---|---|---|---|
9
+ | `workflow` | **Sunucu** (Jint): workflow / middleware / automation ifadeleri | çıplak ad `toplamHesapla(10, 3)` | tenant geneli; `applicationId`/`scope`/`pageId` verilmez, `isAsync` olamaz |
10
+ | `studio` | **Tarayıcı**: `{{ }}` prop bağlamaları, UI flow `code` / `function` adımı | `Functions.toplamHesapla(10, 3)` | uygulamaya ait; `applicationId` + `scope` (`application` \| `page`) zorunlu |
11
+
12
+ Kod ve parametre biçimi ikisinde **aynıdır**: gövde düz deyimler (`return fiyat * adet;`),
13
+ parametreler tipli ve sıralı bir liste, `defaultValue`/`required` zinciri aynı. Aynı ad iki kaynakta
14
+ yan yana yaşayabilir — ad alanları farklıdır (`ad()` vs `Functions.ad()`), ikisi ayrı kayıttır.
15
+
16
+ > **`source:'studio'` YALNIZ TARAYICIDA çalışır (2026-09-10).** Sunucu `Functions` diye bir ad
17
+ > alanı tanımaz — sunucu ifadesindeki `Functions.<ad>(…)` çağrısı `Functions is not defined` ile
18
+ > düşer ve gateway ifadeyi `WF-030` ile **istek gitmeden bloklar**. Sunucu için `source:'workflow'`
19
+ > tanımla. Mikroservis ifadeleri hiçbir kaynağı yüklemez.
20
+
21
+ Araçlar: `function_list` · `function_get` · `function_create` · `function_update` · `function_delete`
22
+ (modül `function`; `core` ve `studio` kümelerinde). Örnekler: `ngapps://examples/function-total`
23
+ (iki kaynak), `ngapps://examples/flow-call-function`.
24
+
25
+ ## Ne zaman fonksiyon, ne zaman değil
26
+
27
+ Fonksiyon **şu iki durumda** yazılır:
28
+
29
+ 1. Aynı ifade üç ya da daha çok yerde kopyalanıyor (her `code` adımına, her prop bağlamasına aynı
30
+ hesap) — tek tanım, tek düzeltme noktası.
31
+ 2. Parametreli bir hesap gerekiyor: `toplamHesapla(fiyat, adet)`, `kdvEkle(tutar, oran = 0.2)`.
32
+
33
+ Bir iş kuralı **hem tarayıcıda hem sunucuda** geçerliyse iki kayıt gerekir: `source:'studio'` ve
34
+ `source:'workflow'`, aynı gövdeyle. Kopyayı gizleme — kapatamıyorsan `platform_gap_report` ile bildir.
35
+
36
+ Fonksiyon **yazılmaz**: tek yerde kullanılan ifade için (doğrudan yaz); veri çekmek için
37
+ (uç çağrısı `microservice` adımının işidir, fonksiyon HTTP yapmaz); `system.*` / `file.*` /
38
+ `crypto.*` zaten yapıyorsa (`platform_guide('expressions')`).
39
+
40
+ ## Kaynak ve kapsam seçimi
41
+
42
+ | Seçim | Nerede görünür | Alanlar | Ne zaman |
43
+ |---|---|---|---|
44
+ | `source:'workflow'` | Tenant'ın **her** workflow / middleware / automation ifadesinde | yalnız `name`, `parameters`, `body`, `description` | Sunucu tarafı iş kuralı, hesap, biçimlendirme |
45
+ | `source:'studio'`, `scope:'application'` | Uygulamanın **her sayfasında** (tarayıcı) | `applicationId` | Varsayılan tarayıcı seçimi |
46
+ | `source:'studio'`, `scope:'page'` | **Yalnız o sayfanın** tarayıcı bağlamında | `applicationId` + `pageId` | Gövde sayfaya özgü komponent adlarını / `state.page`'i kullanıyor |
47
+
48
+ Tekillik: workflow adı tenant içinde, studio adı uygulama içinde **kapsamlar arası benzersizdir**
49
+ (K3) — `homepage`'de `hesapla` varsa başka bir sayfada da uygulama düzeyinde de `hesapla` açılamaz;
50
+ platform `422 GlobalFunctionNameAlreadyExists` döner ve mesaj çakışan kapsamı/sayfayı söyler.
51
+ Gölgeleme yoktur. Kaynak/kapsam tutarsızlığını gateway `FN-005` ile istek gitmeden yakalar
52
+ (workflow'a `applicationId`, studio'ya `applicationId`sız, `page` kapsamına `pageId`sız).
53
+
54
+ ## Hangi bağlam nerede çalışır (K4, K7)
55
+
56
+ Fonksiyonun **hedefi yoktur**: gövde nerede çağrılırsa o bağlamda çalışır ve çağıranın tüm
57
+ globallerini kapanış olarak görür. Yanlış bağlamda çağrı çalışma anında `X is not defined` verir;
58
+ lint bunu yakalayamaz, tablo sana kalır:
59
+
60
+ | Gövdede kullanılan ad | `studio` sayfa fonksiyonu | `studio` uygulama fonksiyonu | `workflow` fonksiyonu |
61
+ |---|:-:|:-:|:-:|
62
+ | parametreler (`fiyat`, `adet`) | ✓ | ✓ | ✓ |
63
+ | `state.app.<key>` | ✓ | ✓ | — |
64
+ | `state.page.<key>`, komponent adları, `Page.components` / `Page.properties` / `Page.queryParams` | ✓ | ✓ (**çağrıldığı sayfada varsa** — statik olarak bilinemez) | — |
65
+ | `Page.user`, `Page.authorized(roles)`, `Page.variables` | ✓ | ✓ | — |
66
+ | `Steps`, `self`, `item`, `event` | çağıran akışın bağlamından | çağıran akışın bağlamından | — |
67
+ | `input`, middleware değişkenleri, adım çıktıları (`<adım>.data`), `row` (automation) | — | — | çağıran ifadenin bağlamından |
68
+ | `system.*`, `file.*`, `crypto.*`, `convert.*`, `Now()`, `UtcNow()` | — | — | ✓ |
69
+ | `cookie` | `get/set/remove` | `get/set/remove` | okunur (`cookie.<ad>`) |
70
+ | `await` | `isAsync:true` ise | `isAsync:true` ise | **yok** (FN-004 block) |
71
+ | başka bir fonksiyon | `Functions.b()` ✓ (K15) | `Functions.b()` ✓ | çıplak `b()` ✓ (aynı kaynaktan) |
72
+
73
+ Kural: uygulama fonksiyonunda **sayfaya özgü ad kullanma**; workflow fonksiyonunda **adım adına
74
+ bağlanma** — dinamik veriyi parametre olarak geçir (`Functions.hesapla(state.page.sayac)`,
75
+ `hesapla(input.tutar)`), gerekiyorsa gövdeyi guard'la (`typeof state !== 'undefined'`).
76
+
77
+ ## İmza: parametreler, varsayılan, `required` (K5)
78
+
79
+ Parametreler **bildirimlidir ve sıralıdır**; çağrı **konumsaldır**: `f(a, b)` bildirimin birinci ve
80
+ ikinci parametresine bağlanır, ad eşlemesi yoktur. İki runtime da her fonksiyonu aynı şekilde kurar
81
+ (tek fark ad alanı ve hata öneki):
82
+
83
+ ```js
84
+ globalThis["toplamHesapla"] = function (fiyat, adet) { // studio: Functions.toplamHesapla = function (…)
85
+ if (adet === undefined) adet = 1; // defaultValue ÖNCE
86
+ if (fiyat === undefined) throw new Error('toplamHesapla: "fiyat" is required'); // required SONRA
87
+ try { return fiyat * adet } // gövde
88
+ catch (e) { throw new Error('toplamHesapla: ' + e.message) }
89
+ };
90
+ ```
91
+
92
+ - `defaultValue` yalnız argüman `undefined` kalınca uygulanır; `null` geçmek varsayılanı **tetiklemez**.
93
+ - `required:true` parametreye `defaultValue` da verilirse varsayılan kazanır, hata hiç fırlamaz.
94
+ - `type` (`text` · `number` · `boolean` · `date` · `object` · `array` · `any`) yalnız Studio
95
+ imzası ve autocomplete içindir; çalışma zamanı tip denetlemez, `"10"` string olarak gelir.
96
+ - Fazla argüman yok sayılır; eksik argüman `undefined` → varsayılan → `required` hatası zinciri.
97
+ - İmza gösterimi (yanıtlardaki `signature`): studio `Functions.toplamHesapla(fiyat, adet = 1)`,
98
+ workflow `toplamHesapla(fiyat, adet = 1)`; zorunlu olmayan ve varsayılansız parametre `ad?` yazılır.
99
+
100
+ ## Tanımlama: `function_create`
101
+
102
+ ```jsonc
103
+ // sunucu
104
+ { "source": "workflow",
105
+ "name": "toplamHesapla", "description": "fiyat × adet; adet verilmezse 1",
106
+ "parameters": [ { "name": "fiyat", "type": "number", "required": true },
107
+ { "name": "adet", "type": "number", "defaultValue": 1 } ],
108
+ "body": "return fiyat * adet;" }
109
+
110
+ // tarayıcı
111
+ { "source": "studio", "applicationId": "<app id>", "scope": "application",
112
+ "name": "toplamHesapla", "description": "fiyat × adet; adet verilmezse 1",
113
+ "isAsync": false,
114
+ "parameters": [ … aynı liste … ],
115
+ "body": "return fiyat * adet;" }
116
+ ```
117
+
118
+ Gövde **düz deyimlerdir** — `function (…) { }` sarmalı ya da arrow yazılmaz; `return` serbesttir,
119
+ dönüşsüz gövde `undefined` döner. Platform gövdeyi kaydetmeden **ayrıştırır** (yürütmez):
120
+ sözdizimi hatası `422 GlobalFunctionBodyInvalid` ile ve ayrıştırıcı mesajıyla döner. Yanıt
121
+ `signature` ve `hint` (çağrı biçimleri) taşır. İstek gitmeden denetlenenler:
122
+
123
+ | Kural | Ne | Sonuç |
124
+ |---|---|---|
125
+ | FN-001 | Ad JS tanımlayıcısı değil ya da ayrılmış sözcük; studio'da `Functions`, workflow'da motor global adı (`system`, `input`, `Now`…); parametre adı geçersiz | **block** — platform da 422 verirdi |
126
+ | FN-002 | Aynı parametre adı iki kez | **block** — 422 `GlobalFunctionParameterNameDuplicate` |
127
+ | FN-003 | Gövde kendini çağırıyor (`Functions.<ad>(` / çıplak `<ad>(`) | warn — durma koşulu yoksa sonsuz özyineleme |
128
+ | FN-004 | `source:'workflow'` + `isAsync:true` | **block** — motor senkron, 422 `GlobalFunctionAsyncNotAllowed` |
129
+ | FN-004 | studio: `isAsync:true` ama `await` yok · `isAsync:false` ama `await` var | warn — ilki gereksiz async (inline `[object Promise]`), ikincisi **derlenmeyen gövde**: fonksiyon atlanır |
130
+ | FN-005 | Kaynak/kapsam tutarsız: workflow'a `applicationId`/`scope`/`pageId`; studio'ya `applicationId` ya da `scope` yok; `page` kapsamına `pageId` yok; `application` kapsamına `pageId` var | **block** — platform 422 |
131
+
132
+ Studio kaydı sonrası bağlı sayfaların çalışma paketi `Pages.Updated` ile yeniden kurulur (B-11):
133
+ `/dev` yolu yeni gövdeyi hemen, `/view` yolu önbellek tazelenince gösterir. Workflow kaydı önbellek
134
+ taşımaz; sonraki koşu yeni gövdeyi görür.
135
+
136
+ ## İfadeden çağrı: `{{ }}` ve `code` adımı (studio)
137
+
138
+ ```jsonc
139
+ // prop bağlaması — page_schema_patch set_binding
140
+ { "op": "set_binding", "target": "txt_toplam", "prop": "content", "expression": "{{ Functions.toplamHesapla(num_fiyat.value, num_adet.value) }}" }
141
+ ```
142
+
143
+ ```js
144
+ // UI flow code adımı (args.value) — await serbest
145
+ const toplam = Functions.toplamHesapla(10, 3);
146
+ state.page.sonuc = toplam;
147
+ ```
148
+
149
+ - Hata gövdeden yayılır ve `Functions.<ad>: <mesaj>` ile öneklenir; prop bağlamasında `runCode`
150
+ hatayı yutar, prop **yazılmaz** ve `page_screenshot` `runtimeErrors` taşır (PAGE-020/021).
151
+ - `isAsync:true` fonksiyonu `{{ }}` içinde çağırma: dönüş Promise'dir, ekranda `[object Promise]`
152
+ görünür. Async fonksiyon `code` adımında `await Functions.x()` ile ya da `function` adımıyla çağrılır.
153
+ - `flow_create`/`flow_update` yazımında gateway her `Functions.<ad>(` çağrısını uygulamanın studio
154
+ fonksiyon listesiyle karşılaştırır (FLOW-025, uyarı): bilinmeyen ad, başka sayfanın sayfa
155
+ fonksiyonu, bildirimden fazla argüman, setter/condition ifadesinde async fonksiyon.
156
+
157
+ ## UI flow `function` adımı ("Call function", K9)
158
+
159
+ ```jsonc
160
+ { "stepId": "hesapla", "name": "hesapla", "type": "function", "kind": "normal",
161
+ "args": { "functionId": "<function_list id>", "functionName": "toplamHesapla",
162
+ "parameters": [
163
+ { "name": "fiyat", "value": { "type": "property", "ref": { "source": "component", "element": "num_fiyat", "property": "value" } } },
164
+ { "name": "adet", "value": { "type": "static", "ref": 3 } } ] },
165
+ "branches": [ { "name": "always", "nextStepId": "yaz" } ] }
166
+ ```
167
+
168
+ - `functionId` **zorunlu**, uygulamada var olmalı ve bir **studio** fonksiyonu olmalı (backend
169
+ `422 GlobalFunctionNotFound` — workflow fonksiyonu adıma bağlanamaz; gateway FLOW-024 ile istek
170
+ gitmeden bloklar). Runtime fonksiyonu **önce id** ile çözer, `functionName` yalnız gösterim ve
171
+ yedektir — yeniden adlandırma akışı kırmaz.
172
+ - `parameters[].name` bildirimdeki adla eşleşir; `value` şekli `microservice` adımıyla aynı
173
+ (`static` · `property` · `storage` · `state` · `variable` · `code` · `page` · `item`). Eksik
174
+ zorunlu parametre adımı düşürür, tanınmayan ad sessizce düşer (FLOW-024 ikisini de uyarır).
175
+ - Çıktı `Steps.<adımAdı>.data`; hata `Steps.<adımAdı>.error.message` (nesne — `microservice`
176
+ adımının dize hatasından farklı). Dal adı `always`; hata yolu `errorSteps` ile aynı mekanizma.
177
+ - Sonucu ekrana yazmak için sonraki `setter` iteratee'si `storage` tipiyle `mapping.source:
178
+ "hesapla.data"` okur (adım **adı**, stepId değil) — tam gövde `ngapps://examples/flow-call-function`.
179
+ - Akışı olaya bağlamak ayrı adımdır: `page_schema_patch set_event { target, event:'click', eventValue:<flow id> }`.
180
+ - `end` adımı koyma; son adımın dalı `nextStepId: null` ile biter (FLOW-023).
181
+
182
+ ## Sunucuda ne kullanılır: `source:'workflow'`
183
+
184
+ Bir hesabı workflow / middleware / automation ifadesinden çağırman gerekiyorsa
185
+ `function_create source:'workflow'` ile tanımla ve **çıplak adla** çağır:
186
+
187
+ ```js
188
+ // workflow code adımı (rule.expression)
189
+ return { toplam: toplamHesapla(input.fiyat, 2) };
190
+ ```
191
+
192
+ ```js
193
+ // automation koşulu
194
+ toplamHesapla(row.fiyat, row.adet) > 1000
195
+ ```
196
+
197
+ - Tenant kapsamlıdır: tanımlandığı andan sonra her uygulamanın her workflow ifadesinde görünür,
198
+ her koşuda DB'den yüklenir (önbellek yok). Gövde bağlamdan bağımsız olmalı — dinamik veriyi
199
+ parametre olarak geçir.
200
+ - `workflow_preview` ile doğrula: `return toplamHesapla(3, 2)` → `data: 5`.
201
+ - İfadede `Functions.<ad>(…)` yazarsan gateway **istek gitmeden bloklar** (`WF-030`); zorlarsan
202
+ Jint `Functions is not defined` fırlatır ve adım hata yoluna girer.
203
+ - Mikroservis alan/filtre ifadeleri hiçbir kaynağı yüklemez — orada fonksiyon yok.
204
+
205
+ ## Güncelleme ve silme
206
+
207
+ - `function_update` platforma **tam gövde** gönderir; gateway mevcut kaydı okuyup vermediğin alanları
208
+ doldurur — yalnız `body` göndermen yeter. `source`/`applicationId`/`scope`/`pageId` değişmez. Ayrı
209
+ patch aracı yoktur: fonksiyonun tek büyük alanı gövdedir.
210
+ - **Yanıt kimin etkileneceğini söyler:** `dependents` (kullanan flow/workflow adları) ve
211
+ `signatureChange` (ad ya da parametre ad/sırası değiştiyse eski → yeni; tip, varsayılan ve gövde
212
+ imzayı değiştirmez). İkisi birden doluysa `warnings[]` gelir — çağrı konumsaldır (K5), `function`
213
+ adımı parametreyi ada göre eşler; güncelleme yine yapılır (K12), silme ise engellenir. Uyarı
214
+ aldıysan çağıran ifadeleri gözden geçir, `dependency_graph(module:'global-function')` listeyi verir.
215
+ - **Yeniden adlandırma çağıranlara yazılır (2026-09-11):** platform yeni adı aynı işlemde çağıranlara
216
+ taşır; yanıt `renamedReferences` ile kaç kaydın yazıldığını söyler. Studio kaynağında `Functions.<eskiAd>`
217
+ başvuruları (akış adımları, `function` adımının `functionName`'i, `code` bağlamaları, diğer fonksiyon
218
+ gövdeleri) yazılır; düz metin (`static`) prop'lar kod değildir, değişmez. Workflow kaynağında
219
+ `<eskiAd>(…)` çağrıları (workflow ifadeleri, otomasyon koşulları, workflow fonksiyonu gövdeleri)
220
+ yazılır; eski ad yeni adın yazılamadığı bir yerde kalırsa — çağrı dışı kullanım (değişken, nesne
221
+ anahtarı) ya da ham sorgu ifadesi (`isExpression: true` `rawQuery`; içindeki SQL çoğunlukla JS metnidir)
222
+ — platform **400** `CantRenameUsedGlobalFunction` ile reddeder ve hiçbir şey yazmaz. Düz SQL
223
+ (`isExpression: false`) kullanım sayılmaz, yazılmaz. Fonksiyonun kendi gövdesindeki çağrılar
224
+ (özyineleme) da yeni adı alır. Tablo adımı alan ifadeleri taramaya girmez, onları elle düzelt.
225
+ - `function_delete`: gateway önce bağımlılık grafiğini okur ve kullanan flow/workflow varsa isteği
226
+ göndermez (409, liste). Studio kaynağında platform silmeyi **engellemez** (K12); bilinçli silme için
227
+ `acknowledgeDependents: true`. Workflow kaynağında platform **400** `CantDeleteUsedGlobalFunction`
228
+ ile reddeder, `acknowledgeDependents` bunu geçemez.
229
+ - Uygulama silinince studio fonksiyonları cascade silinir; deploy ve şablon iki kaynağı da taşır
230
+ (`function` adımlarının `functionId`'si kurulumda yeniden eşlenir, workflow kaynağı ada göre upsert).
231
+
232
+ ## Tuzaklar
233
+
234
+ - **Yanlış kaynak:** sunucu ifadesinde `Functions.x(` → `WF-030` block; tarayıcı ifadesinde çıplak
235
+ workflow adı → `x is not defined`. Aynı hesap iki dünyada gerekiyorsa iki kayıt.
236
+ - **Async inline:** `{{ Functions.veriGetir() }}` → `[object Promise]`. Async fonksiyon yalnız
237
+ `code`/`function` adımından; workflow kaynağı async olamaz.
238
+ - **Sayfa fonksiyonu başka sayfada yok:** `Functions.x is not a function`. Ortak kural uygulama
239
+ kapsamına.
240
+ - **Ad çakışması 422:** studio'da uygulama içinde kapsamlar arası, workflow'da tenant içinde;
241
+ mesaj çakışan kapsamı/sayfayı söyler.
242
+ - **Ayrılmış adlar:** studio'da `Functions` (K1: komponent adı da olamaz, PAGE-009); workflow'da
243
+ motor globalleri (`system`, `input`, `request`, `Now`, `crypto`…). `Functions` workflow kaynağında
244
+ serbesttir — sunucuda o ad alanı yok.
245
+ - **Önekli hata:** gövde hatası `Functions.<ad>: <mesaj>` (studio) ya da `<ad>: <mesaj>` (workflow)
246
+ olarak gelir; `Steps.<adım>.error.message` ya da `runtimeErrors`'ta bu öneki ara.
247
+ - **Mobil yok** (K11): `apps/mobile` runtime'ı `Functions`'ı boş nesne kurar.
248
+ - **Önbellek:** `/view` yolu eski gövdeyi birkaç saniye gösterebilir; `/dev` yolu anlıktır.
249
+ - **Parametre konumsal:** `parameters` sırasını değiştirmek mevcut çağrıların anlamını değiştirir;
250
+ `function` adımları ada göre eşlendiği için etkilenmez.
251
+
252
+ ## Doğrulama
253
+
254
+ 1. `function_list` → kaynak, imza ve id doğru mu (`source` süzgeciyle iki listeyi ayrı gör).
255
+ 2. Studio: `page_runtime_get` özeti `appFunctions` / `pageFunctions` imzalarını taşır — sayfa paketi
256
+ fonksiyonu gördü mü (önbellek tazelenmiş mi).
257
+ 3. Studio: `page_screenshot` `actions` ile butona tıkla, kareyi ve `actionsReport[].flowRuns`'ı oku;
258
+ ifade patladıysa `runtimeErrors`.
259
+ 4. Workflow: `workflow_preview` ile çıplak adla koştur (`return toplamHesapla(3, 2)`); sonuç
260
+ `data`'da.
261
+ 5. Nerede kullanıldığı: `dependency_graph(module:'global-function', id)` — iki kaynakta da
262
+ `{ flows, workflows }` döner (workflow kaynağında `flows` boş).
@@ -51,6 +51,11 @@ Bağımlılıklar bu sırayı zorunlu kılar; atlama:
51
51
  sonra execute+debug)
52
52
  10. workflow_create / (bkz. platform_guide('workflow'); branch bağlantıları + returnDtoId —
53
53
  automation_create returnDtoId'siz workflow 'unready' kalır; automation/middleware muaf)
54
+ 10b. function_create (İSTEĞE BAĞLI, uygulama düzeyinde: 3+ yerde tekrarlanacak hesap ya da hem
55
+ tarayıcıda hem sunucuda geçerli iş kuralı varsa ŞİMDİ tanımla — sayfalar
56
+ ifadelerde Functions.<ad>(…) ile, akışlar 'function' adımıyla çağırır;
57
+ sayfaya özgü fonksiyon (scope:'page') sayfa açıldıktan sonra gelir.
58
+ Kurallar platform_guide('functions'))
54
59
  11. layout_create (header/sidebar + MUTLAKA bir 'slot' — slot'suz layout'a bağlı sayfa
55
60
  boş görünür; bkz. platform_guide('page') Kural 5)
56
61
  12. page_create + … (İŞ BURADA BİTMEZ: her kaydın yönetim ekranı, kimlik varsa giriş
@@ -0,0 +1,231 @@
1
+ # Dal ve Merge Rehberi (environment dallanma)
2
+
3
+ Kendi başına çalışabileceğin bir kopya aç, orada değiştir, sonra `development`'a geri birleştir.
4
+ Deployment (`deployment_start`) bu işin dışındadır: o `development → production` yolu ve **insan
5
+ onaylıdır**. Buradaki tool'ların hiçbiri production'a yazmaz.
6
+
7
+ ## Politika (değişmez)
8
+
9
+ - **Merge hedefi her zaman dalın ebeveynidir.** Ebeveyn `development`'tır; başka bir hedef seçilemez.
10
+ - **Production'a merge eden tool yoktur.** Production'a giden tek yol insan onaylı deployment'tır.
11
+ - Sabit environment'lar (`development`, `production`) silinemez; `environment_delete` bunu HTTP'ye
12
+ gitmeden reddeder.
13
+
14
+ ## Akış
15
+
16
+ ```
17
+ environment_create {projectId, name} → 202, dal "creating"
18
+ environment_list {projectId} → state "ready" olana kadar (30-60 sn)
19
+ … tenant tool'larını environment: "<dal>" ile çağır (page_schema_patch, entity_patch, …)
20
+ merge_plan {projectId, sourceEnvironmentId} → 202, plan "planning"
21
+ merge_get {projectId, planId} → status "planned" olana kadar
22
+ merge_get {projectId, planId, view:"conflicts"} → çakışanları oku
23
+ merge_resolve{projectId, planId, resolutions[]} → her çakışmaya source|target seç
24
+ merge_apply {projectId, planId, message} → 202 (message ZORUNLU)
25
+ merge_get {projectId, planId} → status "applied"
26
+ environment_list {projectId} → dal listede yok, şeması düştü
27
+ ```
28
+
29
+ ## Dalda çalışmak
30
+
31
+ Dal adı `X-Environment` başlığının değeridir. Tenant tool'larına `environment: "odeme_akisi"`
32
+ geçmek yeterlidir; `DEFAULT_ENVIRONMENT` yalnız varsayılandır. Dal `ready` değilken o dalda
33
+ yazmaya çalışmak 400 döner — `environment_list` ile durumu doğrula.
34
+
35
+ Dal açılırken **yalnız tanımlar** kopyalanır. `includeRecords: true` verirsen projenin kendi
36
+ veritabanındaki **bütün** veri tablolarının satırları da gelir — entity'de kayıt taşıması ayarı
37
+ açık olmasa bile (çok dilli companion tablolar ve junction'lar dahil; `files`/`folders` ve audit
38
+ trail tabloları hariç, dış datasource'lara dokunulmaz). Kayıt taşıması ayarı deployment'ın
39
+ (`promote`) kuralıdır ve orada aynen geçerlidir. **Satırlar merge'de geri taşınmaz** — merge yalnız
40
+ tanım işidir.
41
+
42
+ Dalda `page_screenshot` **çalışır** (2026-09-09'dan beri); ayrıntısı bir sonraki bölümde.
43
+
44
+ ## Dalda görsel doğrulama
45
+
46
+ **Dalda kurulan sayfanın karesi dalda alınır** — `page_screenshot {..., environment: "<dal>"}`.
47
+ Studio'nun runtime rotasının üç şeridi vardır ve **ortamı URL belirler**:
48
+
49
+ | Ortam | Şerit |
50
+ |---|---|
51
+ | `production` | `/view/{proje}/{app}/{sayfa}` |
52
+ | `development` | `/dev/{proje}/{app}/{sayfa}` |
53
+ | dal | `/branch/{dal}/{proje}/{app}/{sayfa}` |
54
+
55
+ Sayfanın **bütün** istekleri o dala gider: sayfa şeması da, akışların uç çağrıları da. Yani kare
56
+ "yarı doğru" değildir — gördüğünüz ekran dalın gerçek ekranıdır.
57
+
58
+ Reddedilen tek şey **dal adı olamayacak bir ad**: harfle başlamayan, küçük harf/rakam/alt çizgi
59
+ dışında karakter taşıyan, 3-31 aralığının dışına çıkan ya da rezerve bir ad (`public`, `api`,
60
+ `pg_*` …). Projedeki dalları `environment_list` verir.
61
+
62
+ 2026-09-09 öncesinde bu çağrı **reddediliyordu**: runtime rotası dal adı taşımıyordu, ortam
63
+ modül içi bir store'dan geliyordu ve dal adıyla istenen kare development'ı gösterirdi. O günlerin
64
+ alışkanlığı olan "dalda `page_schema_get` + `page_runtime_get`, kare merge sonrasına" zinciri
65
+ hâlâ geçerli bir doğrulama yoludur, ama artık **zorunlu değildir**.
66
+
67
+ `page_schema_get` (komponent ağacı, prop ve olay bağları) ile `page_runtime_get` (akışlar,
68
+ değişkenler, çözülen ref'ler) kareyi tamamlar: kare ne çizildiğini, bu ikisi neden öyle
69
+ çizildiğini söyler.
70
+
71
+ ## Planı okumak
72
+
73
+ `merge_get` üç görünüm sunar; varsayılan `conflicts`:
74
+
75
+ | view | ne döner |
76
+ |---|---|
77
+ | `summary` | yalnız sayaçlar (`added/updated/deleted/conflicts/unresolved/dataRisk`) |
78
+ | `conflicts` | yalnız çakışan kayıtlar ve onların çakışan elemanları |
79
+ | `full` | değişen her kayıt ve her eleman |
80
+
81
+ `items[]` yalnız **değişen** kayıtları taşır. Her kayıtta:
82
+
83
+ - `kind`: `add` | `update` | `delete` | `conflict`
84
+ - `dataRisk`: entity kaleminde veri riski var — **sebep `dataRiskReasons[]` içindedir**
85
+ - `derivedFromKey`: kalem OTOMATİK ÜRETİLMİŞ bir kayıtsa (varsayılan DTO) kaynağının anahtarı
86
+ - `elements[]`: `path`, `kind`, `base`, `source` (dal), `target` (development), `resolution`
87
+
88
+ `dataRisk` bir **uyarıdır, apply'ı bloklamaz**; üç sebepten biriyle doğrudur:
89
+
90
+ | `dataRiskReasons` | Ne demek |
91
+ |---|---|
92
+ | `field-removed` | Alan siliniyor |
93
+ | `field-narrowed` | Tip / `nullable` / `unique` daraltılıyor |
94
+ | `not-null-without-default-on-populated-table` | **Hedefte satır varken** varsayılansız zorunlu alan ekleniyor — bu apply'ı DDL aşamasında düşürür. Alanı `nullable` yapın ya da `defaultValueType: "default-value"` + `defaultValue` verin |
95
+
96
+ Son satır 2026-09-09'da eklendi; öncesinde bu durum `dataRisk: 0` diyordu ve risk ancak apply
97
+ denenerek öğreniliyordu. Hedef tablo **boşsa** aynı alan riskli sayılmaz.
98
+
99
+ `derivedFromKey` dolu olan kalemi ayrıca çözmeye çalışmayın: kaynağını (entity ya da query)
100
+ çözdüğünüzde aynı yoldaki çakışması **kendiliğinden** aynı tarafa çözülür. Entity adını değiştiren
101
+ bir merge'de entity ve onun varsayılan DTO'su böylece zıt çözülemez.
102
+
103
+ `add` / `update` / `delete` elemanları **otomatik alınır** — karar istemezler. Yalnız `conflict` ve
104
+ `order-conflict` elemanları `merge_resolve` bekler.
105
+
106
+ ## Çakışma çözmek
107
+
108
+ ```json
109
+ { "itemKey": "page:8f1c…", "path": "components[elementId=btn_save].props[name=label].ref", "choice": "source" }
110
+ ```
111
+
112
+ `path` boş bırakılırsa o kaydın **tüm** çakışmaları aynı tarafa çözülür. `source` = dal,
113
+ `target` = development.
114
+
115
+ `merge_resolve` **özet döner** — `{ planId, status, summary, resolved }`. Planın kendisi yanıtta
116
+ yoktur; kalan çakışmalar için `merge_get {planId, view:"conflicts"}` çağırın.
117
+ `summary.unresolved` 0 olduğunda `merge_apply` yolu açıktır.
118
+
119
+ ## Apply'ın reddettiği üç durum
120
+
121
+ | Durum | Kod | Ne yapmalı |
122
+ |---|---|---|
123
+ | Çözülmemiş çakışma var | 409 | `merge_get view:"conflicts"` → `merge_resolve` → tekrar `merge_apply` |
124
+ | Development plan alındığından beri değişti | 409 | `merge_plan` ile **yeniden planla**; eski planı uygulama |
125
+ | Plan 24 saatten eski | 400 | yeniden planla |
126
+
127
+ Aynı `merge_apply` çağrısını tekrarlamak sonucu değiştirmez — 409 geçici bir hata değildir.
128
+
129
+ ## Mesaj zorunludur
130
+
131
+ `merge_apply` mesajsız çalışmaz. Mesaj plana yazılır, plan uygulandıktan sonra da durur ve
132
+ geçmişte bu mesajla görünür — git'teki merge commit mesajının karşılığıdır.
133
+
134
+ - Boş ya da yalnız boşluktan oluşan mesaj **şema katmanında** reddedilir; istek platforma hiç gitmez.
135
+ - En fazla 200 karakter.
136
+ - Kalıp: `<dal> → development: <amaç>`. Ne yaptığını yaz, "merge" yazma.
137
+
138
+ Gateway senin yerine mesaj **uydurmaz**: ne değiştirdiğini bilen sensin.
139
+
140
+ ## Geri almak
141
+
142
+ Uygulanmış bir merge silinmez, **ters bir planla** geri alınır:
143
+
144
+ ```
145
+ merge_revert {projectId, planId, message} → 202, ters plan planning
146
+ merge_get {projectId, planId: <ters plan>} → status planned olana kadar
147
+ merge_apply {projectId, planId: <ters plan>, message}
148
+ ```
149
+
150
+ Bittiğinde ters plan `applied`, kaynak plan `reverted` olur; ikisi de geçmişte durur.
151
+
152
+ Üç şey normal merge'den farklıdır:
153
+
154
+ - **Sütunların anlamı terstir.** Ters planın `elements` satırlarında `source` merge **öncesi**
155
+ değer, `target` **şimdiki** değerdir. Bir kaydı merge'den sonra elle değiştiren biri olduysa o
156
+ satır `conflict` gelir; `source` seçmek geri almayı, `target` seçmek o kaydı olduğu gibi bırakmayı
157
+ seçer.
158
+ - **Pencere vardır.** `RevertWindowDays` (varsayılan 7 gün) dolduğunda 400 döner, çünkü merge
159
+ öncesi anlık görüntü de aynı pencereyle silinir. Uygun bir plan için `merge_list status:'applied'`.
160
+ - **Ters planın ters planı yoktur.** `kind=revert` bir planı geri almaya çalışmak 400 verir; aynı
161
+ değişikliği tekrar istiyorsanız dalı yeniden merge edin.
162
+
163
+ Geri alma reddedildiğinde **mesaj hangi kapıya takıldığını söyler** — üçünü karıştırmayın
164
+ (2026-09-09'dan beri üç ayrı cümle; öncesinde üçü de aynı cümleyi veriyordu):
165
+
166
+ | Ne denendi | Mesaj ne der | Ne yapılır |
167
+ |---|---|---|
168
+ | `kind=revert` bir planı geri almak | "A revert plan cannot itself be reverted" | Ters planın geri aldığı **kaynak planı** geri alın ya da dalı yeniden merge edin |
169
+ | Hiç uygulanmamış plan (`planned`, `failed`, `discarded`) | "this plan is '<durum>'" — planın **gerçek durumu** cümlede | `merge_list status:'applied'` ile uygulanmış planı seçin |
170
+ | Zaten geri alınmış plan | aynı cümle, **`this plan is 'reverted'`** | Geri alma zaten yapılmış; ters planı `merge_get` ile görün |
171
+
172
+ ## Geçmişi okumak
173
+
174
+ Merge sonrası hedefte dokunulan kayıtlar revizyon defterine `source: merge` ile düşer:
175
+ `revision_list {projectId, module, recordId}` bir kaydın merge ile mi yoksa elle mi değiştiğini
176
+ söyler, `revision_diff` ise ne değiştiğini.
177
+
178
+
179
+ `merge_list` projenin merge planlarını en yeniden eskiye verir:
180
+
181
+ ```
182
+ merge_list {projectId} → son planlar (her durumdan)
183
+ merge_list {projectId, status:"applied"} → uygulanmış merge'ler
184
+ merge_list {projectId, environmentId:"<env>"} → o environment'ı kaynak ya da hedef alan planlar
185
+ ```
186
+
187
+ `items[]` bu uçta **her zaman boştur** — bir planın değişiklik listesi için `merge_get`.
188
+ Satırda `message`, `createdBy` (planı alan), `appliedBy` (uygulayan), `appliedAt` ve
189
+ `summary` sayaçları gelir. Sayfalama `pageIndex` / `pageLength` ile.
190
+
191
+ Bir kaydın neden değiştiğini ararken sıra: `merge_list status:"applied"` → ilgili satırın
192
+ `id`'si → `merge_get {planId, view:"full"}`.
193
+
194
+ `activity_list` daha geniştir: dal açma/silme, plan alma/çözme/uygulama ve dağıtım aynı akışta.
195
+
196
+ ```
197
+ activity_list {projectId} → tüm geçmiş, en yeni önce
198
+ activity_list {projectId, kind:"merge.applied"} → yalnız uygulanmış merge'ler
199
+ activity_list {projectId, environmentId:"<env>"} → o dalın hikâyesi
200
+ activity_list {projectId, userId:"<id>"} → bir kişinin yaptıkları
201
+ ```
202
+
203
+ Her satırda `actor`, `actorSource` (`human` | `ai` | `system`) ve türe göre değişen bir
204
+ `summary` vardır. **Bu gateway üzerinden yaptığın her iş `actorSource: "ai"` olarak düşer** —
205
+ istekler `X-Client: mcp` başlığı taşır. Merge satırlarında `subjectId` plan id'sidir;
206
+ ayrıntı için `merge_get`.
207
+
208
+ ## Merge bittikten sonra
209
+
210
+ **Cache için elle bir şey yapmanız gerekmez (2026-09-09'dan beri).** Merge, dokunduğu entity'lerin
211
+ `entityId:` / `entityApi:` / `entityRelationId:` anahtarlarını hedef ortamda **merge biter bitmez**
212
+ yeniden kurar; dalda kurulmuş join'li bir microservice `development`'ta ilk çağrıda çalışır.
213
+ Öncesinde entity anahtarları yalnız geçersizleştiriliyor, yeniden kurulmuyordu ve uç
214
+ `Sequence contains no matching element` ile **500** veriyordu — kurtulmanın tek yolu entity'ye
215
+ anlamsız bir `entity_patch` atmaktı. Cache yenileme hatası merge'i düşürmez: `cacheError`'a yazılır,
216
+ plan `applied` kalır.
217
+
218
+ - `applied` → dal `merged` olur ve **şeması düşer**; `environment_list` artık göstermez.
219
+ - `applied-with-drift` → dal ve şeması **durur**. `verification.driftTables` dal ile development
220
+ arasında hâlâ farklı olan tabloları listeler; incelenmeden dal silinmez.
221
+ - `failed` → plan `failed`, dal `ready`'ye döner. Dal ve içindeki iş kaybolmaz; yeniden planlanır.
222
+
223
+ ## Sınırlar
224
+
225
+ - Projede aynı anda **tek** açık merge planı olur. Yenisini istemeden önce `merge_apply` ya da
226
+ `merge_discard`.
227
+ - Merge sürerken dal ve development'a yazma kilitlidir; **diğer dallar etkilenmez**.
228
+ - Proje başına açık dal sayısı sınırlıdır (varsayılan 5) — sınır bağlantı bütçesidir, ürün kararı
229
+ değil.
230
+ - Dal adı `^[a-z][a-z0-9_]{2,30}$` kuralına uyar ve şema adı olur; `development`, `production`,
231
+ `public`, `pg_*` gibi adlar rezervedir.