@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.
- package/.env.example +2 -2
- package/.env.production.example +8 -0
- package/README.md +9 -8
- package/dist/config.js +18 -3
- package/dist/knowledge/backendConstraints.js +85 -0
- package/dist/knowledge/componentCatalog.js +357 -54
- package/dist/knowledge/componentEvents.js +120 -25
- package/dist/knowledge/functionGuards.js +134 -0
- package/dist/knowledge/normalize.js +53 -2
- package/dist/knowledge/outlines.js +31 -0
- package/dist/knowledge/policy.js +14 -5
- package/dist/knowledge/rules.js +343 -1
- package/dist/platform/csv.js +123 -0
- package/dist/platform/errors.js +62 -3
- package/dist/platform/http.js +1 -0
- package/dist/platform/responses.js +16 -4
- package/dist/platform/screenshot.js +18 -1
- package/dist/resources/examples/flow-call-function.json +66 -0
- package/dist/resources/examples/function-total.json +70 -0
- package/dist/resources/examples/microfunction-node-sum.json +56 -0
- package/dist/resources/examples/page-dynamic-form.json +1 -1
- package/dist/resources/examples/page-sign-in.json +1 -1
- package/dist/resources/guides/component.md +13 -1
- package/dist/resources/guides/entity.md +321 -17
- package/dist/resources/guides/expressions.md +3 -0
- package/dist/resources/guides/functions.md +262 -0
- package/dist/resources/guides/getting-started.md +5 -0
- package/dist/resources/guides/merge.md +231 -0
- package/dist/resources/guides/microfunction.md +166 -0
- package/dist/resources/guides/microservice.md +61 -2
- package/dist/resources/guides/modify-existing.md +23 -0
- package/dist/resources/guides/page.md +20 -4
- package/dist/resources/guides/translation.md +24 -0
- package/dist/resources/guides/workflow.md +1 -1
- package/dist/resources/schema-fingerprint.json +4 -4
- package/dist/resources/schemas/AnalyzeImportQuery.json +51 -0
- package/dist/resources/schemas/ApplyMergePlanCommand.json +19 -0
- package/dist/resources/schemas/CreateBulkRowCommand.json +3 -0
- 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 +119 -1
- package/dist/resources/schemas/CreateWorkflowCommand.json +13 -2
- 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 +3 -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 +119 -1
- package/dist/resources/schemas/PreviewWorkflowCommand.json +13 -2
- 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 +13 -2
- package/dist/resources/schemas/UpdateBulkRowCommand.json +3 -0
- package/dist/resources/schemas/UpdateEntityCommand.json +3 -1
- 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 +119 -1
- package/dist/resources/schemas/UpdateWorkflowCommand.json +13 -2
- package/dist/server.js +15 -3
- package/dist/tools/activities.js +40 -0
- package/dist/tools/automations.js +14 -5
- package/dist/tools/common.js +16 -0
- package/dist/tools/dependencies.js +1 -1
- package/dist/tools/environments.js +52 -0
- package/dist/tools/files.js +51 -50
- package/dist/tools/flows.js +95 -2
- package/dist/tools/functions.js +331 -0
- package/dist/tools/importSchemas.js +79 -0
- package/dist/tools/imports.js +241 -0
- package/dist/tools/merges.js +113 -0
- package/dist/tools/microfunctions.js +155 -0
- package/dist/tools/microservices.js +42 -3
- package/dist/tools/pages.js +62 -10
- package/dist/tools/platformInfo.js +4 -1
- package/dist/tools/revisions.js +94 -0
- package/dist/tools/rows.js +342 -22
- package/dist/tools/screenWrite.js +11 -2
- package/dist/tools/templates.js +32 -5
- package/dist/tools/workflows.js +24 -6
- 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.
|