@appaflytech/zeyrek-ai-mcp 0.0.1

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 (88) hide show
  1. package/.env.example +46 -0
  2. package/README.md +260 -0
  3. package/dist/config.js +128 -0
  4. package/dist/index.js +88 -0
  5. package/dist/knowledge/componentCatalog.js +438 -0
  6. package/dist/knowledge/componentEvents.js +164 -0
  7. package/dist/knowledge/coverage.js +60 -0
  8. package/dist/knowledge/normalize.js +1309 -0
  9. package/dist/knowledge/outlines.js +167 -0
  10. package/dist/knowledge/policy.js +44 -0
  11. package/dist/knowledge/reservedTables.js +75 -0
  12. package/dist/knowledge/rules.js +1725 -0
  13. package/dist/observability/trace.js +337 -0
  14. package/dist/platform/errors.js +132 -0
  15. package/dist/platform/http.js +169 -0
  16. package/dist/platform/responses.js +94 -0
  17. package/dist/platform/token.js +79 -0
  18. package/dist/resources/examples/entity-pair-m2m.json +105 -0
  19. package/dist/resources/examples/flow-list-to-form.json +65 -0
  20. package/dist/resources/examples/flow-load-table.json +178 -0
  21. package/dist/resources/examples/microservice-table-list.json +49 -0
  22. package/dist/resources/examples/middleware-authenticate.json +194 -0
  23. package/dist/resources/examples/page-detail-profile.json +95 -0
  24. package/dist/resources/examples/page-dynamic-form.json +221 -0
  25. package/dist/resources/examples/page-form-upsert.json +279 -0
  26. package/dist/resources/examples/page-html-embed.json +106 -0
  27. package/dist/resources/examples/page-sign-in.json +194 -0
  28. package/dist/resources/examples/workflow-basic.json +94 -0
  29. package/dist/resources/guides/component.md +108 -0
  30. package/dist/resources/guides/entity.md +348 -0
  31. package/dist/resources/guides/expressions.md +139 -0
  32. package/dist/resources/guides/getting-started.md +109 -0
  33. package/dist/resources/guides/html.md +106 -0
  34. package/dist/resources/guides/microservice.md +313 -0
  35. package/dist/resources/guides/middleware.md +271 -0
  36. package/dist/resources/guides/modify-existing.md +35 -0
  37. package/dist/resources/guides/page.md +1574 -0
  38. package/dist/resources/guides/view.md +89 -0
  39. package/dist/resources/guides/workflow.md +359 -0
  40. package/dist/resources/knowledge.js +44 -0
  41. package/dist/resources/schemas/CreateDatasourceCommand.json +54 -0
  42. package/dist/resources/schemas/CreateDiscoveredEntitiesCommand.json +133 -0
  43. package/dist/resources/schemas/CreateEntityCommand.json +387 -0
  44. package/dist/resources/schemas/CreateMicroserviceCommand.json +528 -0
  45. package/dist/resources/schemas/CreateQueryCommand.json +43 -0
  46. package/dist/resources/schemas/CreateViewCommand.json +158 -0
  47. package/dist/resources/schemas/CreateWorkflowCommand.json +1719 -0
  48. package/dist/resources/schemas/Filter.json +124 -0
  49. package/dist/resources/schemas/GetRowsQuery.json +122 -0
  50. package/dist/resources/schemas/PreviewMicroserviceCommand.json +565 -0
  51. package/dist/resources/schemas/PreviewQueryCommand.json +74 -0
  52. package/dist/resources/schemas/PreviewWorkflowCommand.json +981 -0
  53. package/dist/resources/schemas/StepDto.json +900 -0
  54. package/dist/resources/schemas/UpdateDatasourceCommand.json +58 -0
  55. package/dist/resources/schemas/UpdateEntityCommand.json +679 -0
  56. package/dist/resources/schemas/UpdateMicroserviceCommand.json +512 -0
  57. package/dist/resources/schemas/UpdateQueryCommand.json +86 -0
  58. package/dist/resources/schemas/UpdateViewCommand.json +153 -0
  59. package/dist/resources/schemas/UpdateWorkflowCommand.json +1719 -0
  60. package/dist/resources/schemas.js +40 -0
  61. package/dist/server.js +63 -0
  62. package/dist/tools/access.js +27 -0
  63. package/dist/tools/applications.js +59 -0
  64. package/dist/tools/automations.js +103 -0
  65. package/dist/tools/common.js +18 -0
  66. package/dist/tools/components.js +280 -0
  67. package/dist/tools/datasources.js +82 -0
  68. package/dist/tools/dependencies.js +17 -0
  69. package/dist/tools/deployments.js +17 -0
  70. package/dist/tools/dtos.js +54 -0
  71. package/dist/tools/entities.js +166 -0
  72. package/dist/tools/files.js +138 -0
  73. package/dist/tools/flows.js +226 -0
  74. package/dist/tools/folders.js +51 -0
  75. package/dist/tools/layouts.js +105 -0
  76. package/dist/tools/microservices.js +198 -0
  77. package/dist/tools/organizations.js +65 -0
  78. package/dist/tools/pages.js +597 -0
  79. package/dist/tools/platformInfo.js +44 -0
  80. package/dist/tools/projects.js +152 -0
  81. package/dist/tools/queries.js +48 -0
  82. package/dist/tools/rows.js +115 -0
  83. package/dist/tools/screens.js +97 -0
  84. package/dist/tools/templates.js +65 -0
  85. package/dist/tools/variables.js +94 -0
  86. package/dist/tools/views.js +58 -0
  87. package/dist/tools/workflows.js +196 -0
  88. package/package.json +49 -0
@@ -0,0 +1,139 @@
1
+ # İfade Sözlüğü (workflow/microservice ifadeleri + UI flow bağlamı)
2
+
3
+ İfade yazılan HER yerde bu sözlük geçerlidir. İki ayrı dünya var — karıştırma:
4
+
5
+ 1. **Backend (Jint, sunucuda):** workflow/automation/middleware step ifadeleri
6
+ (`rule.expression`, `bodyExpression`, condition `items[].expression`), microservice
7
+ filtre/alan `value`'ları (`source:'expression'`). Kültür **tr-TR**, saat dilimi **UTC**.
8
+ 2. **UI flow (tarayıcıda):** sayfa olay akışlarının `code` adımı, `{{ … }}` inline prop
9
+ ifadeleri, `value.type:'code'` ref'leri.
10
+
11
+ Uydurma fonksiyon adı runtime'da `X is not defined` 500'üdür — yalnız buradakileri kullan.
12
+
13
+ ## 1. Backend ifadeleri — kullanılabilir bağlam
14
+
15
+ **Değişkenler:** step çıktıları (`<stepAdı>.data`), middleware değişkenleri (`user`,
16
+ `settings`, `permissions`… — `workflow_middleware_variables` ile keşfet), HTTP bağlamı:
17
+ `cookie`, `header`, `queryString`, `body`, `triggerSource`/`context` (tetikleyen ucun
18
+ type/name/roles/impersonatedUserId'ı). Workflow'da istek girdisi `input.`, automation'da
19
+ tetikleyen satır `row` / `previousRow` / `user`.
20
+
21
+ **Fonksiyonlar (qm'de aktif kullanılanlar önce):**
22
+
23
+ | Çağrı | Ne yapar | Gerçek örnek (qm) |
24
+ |---|---|---|
25
+ | `system.getPageUrl(path)` | Sayfanın environment'a göre doğru serve URL'ini üretir — e-posta/redirect linki için TEK doğru yol, sabit URL yazma | `system.getPageUrl(`/web/dif-kayit?id=${row.finding_record}`)` |
26
+ | `system.generateToken({claims})` | Org secret'ıyla JWT üretir — sign-in ucunun kalbi | `{ access_token: system.generateToken({ userId: user.data.id, email: user.data.email }) }` |
27
+ | `system.validateToken(token)` | Org secret'ıyla doğrular; dönüş `{ isValid, claims }` — **claim'ler bir seviye içeride** ve anahtarları `generateToken`'a verdiğin sözlüğün anahtarları (`r.claims.userId`); `r.id` YOK | `const r = system.validateToken(cookie.APP_Token)` → condition: `token.data.isValid && token.data.claims.userId` |
28
+ | `file.readAsBase64(fileId)` | Drive dosyasını `data:<mime>;base64,…` döner | şablon okuma |
29
+ | `file.excel(docBase64, schema)` · `file.word(...)` · `file.powerpoint(...)` | Office ŞABLONUNU veriyle doldurur, base64 döner | `file.excel(file.readAsBase64(tpl.data.template.id), buildPayload.data)` |
30
+ | `file.readAllText(fileId)` | Dosya metnini okur (docx dahil) | |
31
+ | `UtcNow()` | UTC şimdi (Date işlemleri çalışır) | `const d = UtcNow(); d.setDate(d.getDate() + 7); return d` |
32
+ | `Now(tz)` | Verilen saat diliminde şimdi, **`"yyyy-MM-ddTHH:mm:ss"` METİN olarak**. **JS motoru UTC'ye sabitlidir** (`opt.TimeZone = Utc`), yani `new Date()` her zaman UTC'dir — yerel gün/saat mantığı için bunu kullanın, offset'i koda gömmeyin | `Now('Europe/Istanbul')` → `"2026-08-18T19:11:10"` |
33
+ | `Today(tz)` | O saat diliminde bugün, `"yyyy-MM-dd"` metni — gün sınırı filtreleri için en kısa yol | `Today('Europe/Istanbul') + 'T00:00:00'` |
34
+ | `ToTimeZone(v, tz)` | Bir değeri (Date, DateTimeOffset ya da ISO metin) o saat dilimine çevirir, aynı metin biçiminde | `ToTimeZone(Steps.randevu.data.baslangic, 'Europe/Istanbul')` |
35
+
36
+ > **Bu üçü METİN döner, Date DÖNMEZ** — bilerek. `UtcNow()` bir JS `Date` döndürür ve üzerinde
37
+ > `getTime()`/`getUTCFullYear()` çalışır; ama Jint'in `DateTimeOffset` → `Date` çevriminde **saat
38
+ > dilimi bilgisi kaybolur** ve CLR üyeleri (`.Year`, `.AddDays`) erişilemez. Metin biçimi hem
39
+ > sıralanabilir hem de datetime filtrelerine doğrudan verilebilir. Gün aritmetiği gerekiyorsa
40
+ > `UtcNow()` üzerinde `getTime()` ile yapın.
41
+ >
42
+ > **Tuzak:** çözümlenemeyen bir datetime filtre değeri 400 vermez — platform o filtreyi
43
+ > **sessizce düşürür** ve uç TÜM satırları döndürür. Bir tarih filtresi yazdıktan sonra
44
+ > `microservice_debug` ile ifadenin neye çözüldüğüne bakın (`source:'filter'` satırları).
45
+ | `GenerateGuid()` / `crypto.UUID.generate()` | v7 GUID string | |
46
+ | `Authorized(userRoles)` | `triggerSource.roles` ile kesişim; **hedefte rol tanımlı değilse true** | middleware'de rol kontrolü: `Authorized(user.roles)` |
47
+ | `crypto.JWT.encode(privateKey, payload)` / `crypto.JWT.validate(key, token)` | Harici anahtarla JWT | dış sistem entegrasyonu |
48
+ | **`crypto.SHA256.encode(text)`** | **Adına rağmen SHA-256 DEĞİL:** `Hasher.Hash` = PBKDF2-HMAC-SHA512, 350.000 tur, 64 bayt, **salt = girdinin kendisi**, çıktı BÜYÜK HARF hex (128 karakter). Parola saklama/doğrulama için uygundur; genel amaçlı özet, imza ya da dış sistemle eşleşmesi gereken bir hash için KULLANMA | `hash === crypto.SHA256.encode(input.password)` |
49
+ | `crypto.base64.encode/decode` · `crypto.qr.decode` | | |
50
+ | `system.generatePKCE()` | `{codeChallange, codeVerifier}` — alan adı gerçekten `codeChallange` | OAuth akışı |
51
+ | `convert.CSV(obj)` · `convert.PDF(html)` · `convert.TXT` · `convert.HTML` · `convert.FileToPDF` | dönüştürücüler | |
52
+ | `request.url.{pathname, searchParams, href, …}` · `request.body/header/cookie` | İstek nesnesi — **`workflow_preview`'da YOKTUR** (yalnız gerçek istekte yüklenir) | `const slug = request.url.pathname.split("/p/")?.[1]` |
53
+ | `log(msg)` | sunucu loguna yazar (teşhis) | |
54
+ | `deepEqual(a, b)` / `a.deepEqual(b)` | derin karşılaştırma | automation condition'da `row` vs `previousRow` |
55
+
56
+ **Tuzaklar:** tarih formatlamada `toLocaleDateString('tr-TR', { timeZone: 'UTC' })` kullan
57
+ (motor tr-TR + UTC); automation zinciri istek başına workflow başına 10 koşumda
58
+ `InfiniteLoopException` ile kesilir (sonsuz döngü koruması).
59
+
60
+ **Tohum parola üretmek istiyorsan** hash'i platformun kendisine ürettir: parolayı düz metin alan
61
+ bir workflow yazıp `crypto.SHA256.encode(input.password)` sonucunu döndür, ya da kullanıcı kaydını
62
+ açan ucu kullan. Dışarıda kendi SHA-256'nı hesaplayıp yazarsan giriş akışı **hiçbir zaman**
63
+ eşleşmez — algoritma yukarıdaki satırda yazan PBKDF2'dir.
64
+
65
+ ## 2. UI flow ifadeleri — kullanılabilir bağlam
66
+
67
+ `code` adımı `(async () => { … })()` içinde koşar → **`await` serbest**; dönüş değeri akışa
68
+ taşınmaz — etkiyi `Page`/`state`/komponent yazarak üretirsin. Akış `success` değil **`always`**
69
+ dalından devam eder.
70
+
71
+ | Global | İçerik |
72
+ |---|---|
73
+ | `Page` | `Page.user`, `Page.variables`, `Page.components`, `Page.properties`, `Page.queryParams`, `Page.authorized(roles)` |
74
+ | **Komponent adları** | Her komponent adıyla doğrudan değişkendir: `specialties_table.rows = data` hem prop'u yazar hem UI'ı günceller (change event). Addaki `-` silinir: `tickets-table` → `ticketstable` |
75
+ | `state.page` / `state.app` | Kalıcı state (oku/yaz): `state.page.selectedId = row.id`. **Tanımlı değişkenler de buradadır:** `variable_create` ile yazılan her `key` sayfa düzeyinde `state.page.<key>`, uygulama düzeyinde `state.app.<key>` olur; `value` nesneyse alanlarına inilir (`state.page.MyTest.isActive`) |
76
+ | `Steps` | Adım çıktıları: `Steps.load_specialties` (stepId ile); `error` = son hata |
77
+ | `self` · `item` · `Row` / `RowIndex` | Tetikleyen komponent (yazılabilir) · repeater/tablo satırı (yazmak satırı günceller) |
78
+ | `event` | `{name, data, source: {id, props}}` |
79
+ | `cookie` | `cookie.get(name)` / `cookie.set(name, value, {expiresInHours, path})` / `cookie.remove(name)` — tarayıcı cookie'si |
80
+ | `setComponentProperty(name, key, value)` / `getComponentProperty(name, key)` | fonksiyon alternatifi |
81
+ | `LocalStorage` · `Widget` · `params` | yerel veri · widget bağlamı · olay parametreleri |
82
+ | `log(...)` | console (proxy'leri temizler) |
83
+
84
+ **Prop'a doğrudan ifade bağlama (`{{ }}`):** akış kurmadan bir prop'u ifadeye bağlamak için
85
+ prop `type: 'code'` olur, **ifade `ref` alanına `{{ }}` içinde** yazılır, `data` tasarım zamanı
86
+ değerini taşır:
87
+ `"text": { "type": "code", "data": "Button text", "ref": "{{ state.page.MyTest.isActive ? 'Test' : 'FalseTest' }}" }`
88
+
89
+ ## 3. Adım argümanlarında `value.type` çözümlemesi
90
+
91
+ `microservice`/`setter` adımlarının `parameters[]`/`iteratees[]` değerlerinde:
92
+
93
+ | type | ref | Anlamı |
94
+ |---|---|---|
95
+ | `static` | değerin kendisi | sabit |
96
+ | `storage` | **stepId** | o adımın çıktısı; `arrayPath` ile dizi öğelerinden alan toplanır (`|` ile birleşir) |
97
+ | `property` | `{element, property}` | komponent prop'u |
98
+ | `variable` | `{name}` | sayfa/uygulama değişkeni (`variable_list`) |
99
+ | `state` | `'key'` ya da `'app:key'` | state scope'u (varsayılan `page`) |
100
+ | `code` | JS kaynak string | §2 bağlamıyla eval |
101
+ | `item` | — | repeater satırı |
102
+ | `page` | property yolu | `Page.properties`'ten |
103
+
104
+ ### 2a. `Page.user` — iki tuzağı birden taşır
105
+
106
+ `Page.user`, sayfaya bağlı middleware'in `set-user` çıktısıdır. **Sayfa `middlewareIds` ile o
107
+ middleware'e bağlı değilse `Page.user` UNDEFINED'dır** (ucu bağlamak yetmez —
108
+ `platform_guide('page')` Kural 8). Ayrıca **`roles` dizisi DTO'da genelde yoktur**: `dto_get`
109
+ ile bak, çoğu kurulumda yalnız `role`, `role_name`, `roles_csv` var.
110
+
111
+ İkisini birden karşılayan tek doğru başlangıç:
112
+
113
+ ```js
114
+ var u = Page.user || {};
115
+ var rc = u.roles_csv || (u.role ? ',' + u.role + ',' : '');
116
+ var has = function (r) { return rc.indexOf(',' + r + ',') >= 0; };
117
+ ```
118
+
119
+ Aynı guard `condition` adımının `rules[].expression`'ında da şart — orada patlayan bir ifade
120
+ hata vermek yerine kuralı **eşleşmemiş sayar** ve akış sessizce `else` dalına gider:
121
+
122
+ ```js
123
+ (((Page.user && (Page.user.roles_csv || '')) || '').indexOf(',admin,') >= 0)
124
+ ```
125
+
126
+ Karıştırma: `roles_csv` **UI/filtre** tarafının yoludur; backend middleware'inde rol kapısı
127
+ `Authorized(user.roles)` ile kurulur ve orada dizi çalışır.
128
+
129
+ ## 4. Hangi dünyada hangi erişim VAR/YOK
130
+
131
+ | | Backend | UI flow |
132
+ |---|:-:|:-:|
133
+ | `user` (middleware değişkeni) | ✓ | `Page.user` |
134
+ | `input.` (istek girdisi) | ✓ (yalnız workflow step'leri) | — (`event.data` / `params`) |
135
+ | `request.` | ✓ (preview hariç) | — (`Page.queryParams`) |
136
+ | Komponentlere erişim | — | ✓ (adıyla) |
137
+ | `system.` / `file.` / `crypto.` / `convert.` | ✓ | — |
138
+ | `cookie` | okunur sözlük (`cookie.X`) | `get/set/remove` fonksiyonları |
139
+ | `await` | — (senkron ifade) | ✓ (`code` adımı) |
@@ -0,0 +1,109 @@
1
+ # Sıfırdan Proje Kurulumu (boş org dahil)
2
+
3
+ ## Kuruluş sırası
4
+
5
+ Bağımlılıklar bu sırayı zorunlu kılar; atlama:
6
+
7
+ ```
8
+ 1. project_create (application zorunlu: ilk application projeyle birlikte açılır;
9
+ application slug'ı ORG GENELİNDE tekildir — 'web' büyük olasılıkla
10
+ doludur, 409'da project_list ile mevcut slug'ları tara)
11
+ 2. project_get (environment id'leri + application id burada)
12
+ 3. datasource_list (her projede built-in datasource hazır gelir — çoğu iş için yeterli;
13
+ dış DB gerekiyorsa datasource_test_connection → datasource_create)
14
+ 4. entity_list (ÖNCE BAK: platform her projeye hazır entity'ler açar — users (kimlik:
15
+ (applicationId'siz) email/password/first_name/last_name), roles, user_roles, permissions.
16
+ applicationId VERİRSEN bunlar listede GÖRÜNMEZ. Ürünün "müşteri" /
17
+ "öğrenci" / "üye" kavramı için sıfırdan bir kimlik tablosu açmadan önce
18
+ users'ı gör — bkz. platform_guide('entity') §'Hazır entity'ler')
19
+ 5. entity_create (applicationIds Studio'nun application bazlı entity listesi içindir —
20
+ boşsa satır uçları ÇALIŞIR ama entity Studio listesinde görünmez;
21
+ önce ilişkisiz gövdeler, sonra update/patch ile ilişki alanları —
22
+ bkz. platform_guide('entity'))
23
+ 6. row_create (test verisi; alan tanımlarını row_list ile doğrula)
24
+ 7. dto_list / dto_create (workflow/automation'ın parameterDtoId/returnDtoId sözleşmeleri;
25
+ platform entity başına DTO üretir — önce dto_list ile ara)
26
+ 8. workflow_create (type: 'middleware' — YALNIZ ihtiyaç varsa; bkz. aşağıdaki karar tablosu.
27
+ Kuruyorsan guard + 'user' değişkeni; uçlara middlewareIds ile
28
+ bağlanır — bkz. platform_guide('middleware'))
29
+ 9. microservice_create (bkz. platform_guide('microservice'); kullanıcıya özel uçlarda
30
+ middlewareIds + filtre 'user.id' expression'ı; önce preview,
31
+ sonra execute+debug)
32
+ 10. workflow_create / (bkz. platform_guide('workflow'); branch bağlantıları + returnDtoId —
33
+ automation_create returnDtoId'siz workflow 'unready' kalır; automation/middleware muaf)
34
+ 11. layout_create (header/sidebar + MUTLAKA bir 'slot' — slot'suz layout'a bağlı sayfa
35
+ boş görünür; bkz. platform_guide('page') Kural 5)
36
+ 12. page_create + … (İŞ BURADA BİTMEZ: her kaydın yönetim ekranı, kimlik varsa giriş
37
+ page_schema_patch ekranı. Arketipler: platform_guide('page') Kural 7 —
38
+ + flow_create liste / form(create+edit) / detay / giriş)
39
+ 13. application_update (homepageId — ana sayfa sayfadan değil application'dan seçilir)
40
+ ```
41
+
42
+ ## İlk kullanıcıyı kim açar? (tavuk-yumurta kilidi)
43
+
44
+ Kimlik kurulmuş yeni bir projede **giriş yapabilecek hiç kimse yoktur** ve zincir kendi kendini
45
+ kilitler:
46
+
47
+ 1. `users.password` alanı **hash'lidir** (`Hasher.Hash` / `crypto.SHA256.encode`, PBKDF2).
48
+ `row_create` parolayı **hash'lemez** — düz metin yazar ve o kullanıcı asla giriş yapamaz
49
+ (ölçüldü). Yani kullanıcı ancak `crypto.SHA256.encode(...)` çağıran bir **workflow** üzerinden
50
+ açılabilir.
51
+ 2. O workflow'un ucu, kimlik kurulduğu için `middlewareIds` ile auth middleware'ine bağlıdır.
52
+ 3. Auth middleware'i token'ı **çerezten** okur; ortada henüz kullanıcı yoktur, dolayısıyla token
53
+ da yoktur.
54
+ 4. **Yeni projede `users` tablosu BOŞ gelir** — `organization_sync_users` Studio operatörünü
55
+ otomatik kopyalamaz.
56
+
57
+ **Bootstrap deseni** (crm koşumunda uygulandı):
58
+
59
+ ```
60
+ 1. Kullanıcı yazan workflow'a bağlı, middlewareIds: [] olan GEÇİCİ bir uç aç
61
+ (ör. slug: 'bootstrap-user') — parolayı workflow içinde crypto.SHA256.encode ile hash'le.
62
+ 2. microservice_execute ile ilk yöneticiyi yaz (rol bağını da kur: user_roles satırı).
63
+ 3. Ucu HEMEN sil (microservice_delete). Kalırsa herkese açık kullanıcı yaratma ucu bırakmış olursun.
64
+ 4. Giriş ucundan token al, sonraki her şeyi normal korumalı yoldan yap.
65
+ ```
66
+
67
+ Silmeyi unutmamak için ucu açtığın anda "sil" adımını görev listene yaz; `microservice_list` ile
68
+ proje kapanışında `bootstrap` içeren slug kalmadığını doğrula.
69
+
70
+ ## Middleware gerekli mi? (karar tablosu)
71
+
72
+ Middleware bir kontrol listesi maddesi değil; **ihtiyaca** kurulur:
73
+
74
+ | Durum | Karar |
75
+ |---|---|
76
+ | Ürün kullanıcı barındırıyor (giriş, "benim kayıtlarım", role göre değişen ekran) | Auth middleware **kur** |
77
+ | Ayarların satır olarak tutulduğu bir tablo var ve uçlar bunu okuyor | Ayar setter'ı **kur** |
78
+ | İçerik herkese açık, oturum kavramı yok (katalog, vitrin, form toplama) | **Hiçbiri kurulmaz** — boşuna middleware ürün karmaşası |
79
+
80
+ **Kimlik kurduysan yarım bırakma:** giriş sayfası + korunması gereken **her** uç ve **her** sayfa
81
+ `middlewareIds` ile bağlı olmalı. Bir-iki uca bağlayıp gerisini açık bırakmak, hiç kurmamaktan
82
+ kötüdür — sistem güvenli görünür, değildir.
83
+
84
+ ## Örnek arama davranışı
85
+
86
+ Örnek gövde için **mevcut projeleri taramak yerine** önce şunlara bak:
87
+
88
+ 1. `ngapps://examples/index` — onaylanmış altın örnekler (m2m entity çifti, table-source
89
+ microservice, tam workflow). Boş org'da tek örnek kaynağı budur.
90
+ 2. `ngapps://schemas/index` — API gövdelerinin JSON şemaları (alan adları buradan doğrulanır).
91
+ 3. Org'da proje varsa `*_get` çıktısı hâlâ iyi bir şablondur — ama önce örnek kütüphanesi.
92
+
93
+ ## Rehber yetmezse: kaynağa bak, sonra söyle
94
+
95
+ Bu rehberler platformun yazılı olmayan kurallarını taşır ama tamamı değildir. Bir gövdenin şekli,
96
+ bir alanın davranışı ya da bir hatanın sebebi buradan çıkmıyorsa **kaynak koda bakmak serbesttir ve
97
+ doğru olanı yapmaktır** — doğruluğun en güvenilir kaynağı koddur (backend: `src/NgApps.*`,
98
+ Studio/komponentler: zeyrek-frontend). Rehberlerde geçen dosya:satır referansları bu yüzden var.
99
+
100
+ Tek beklenti: **koda inmek zorunda kaldığın noktayı söyle.** Her iniş bilgi katmanında bir eksiği
101
+ işaret eder ve o eksik rehbere/lint'e taşınacak bir görevdir. Tahminle ilerlemek yerine koda bakmak;
102
+ koda baktığını gizlemek yerine raporlamak.
103
+
104
+ ## Her yazmadan sonra doğrula
105
+
106
+ - create/update → ilgili `*_get` ile geri oku
107
+ - microservice → `microservice_execute`, beklenmedik sonuçta `microservice_debug`
108
+ - workflow → `workflow_preview`; automation → `automation_trigger` + `automation_histories`
109
+ - "API 200 döndü" tek başına bitti saymaz; politika bulgularını (`policyFindings`) oku ve gereğini yap
@@ -0,0 +1,106 @@
1
+ # HTML Komponent Rehberi (kaçış kapısı)
2
+
3
+ Hazır komponentler bir gereksinimi karşılamıyorsa cevap "yapılamaz" değil, `html`
4
+ komponentidir: ham HTML + Mustache şablonu + scoped CSS + satır içi script + flow köprüsü.
5
+ Genel komponent kuralları: `platform_guide('component')`; tam gövde örneği:
6
+ `ngapps://examples/page-html-embed`.
7
+
8
+ ## Karar kuralları
9
+
10
+ - Önce katalog: iş bir hazır komponentle oluyorsa onu kullan (daha az bakım, tema uyumu).
11
+ - Hazır komponent yetmiyorsa (özel görselleştirme, üçüncü parti JS kütüphanesi, alışılmadık
12
+ etkileşim) `html` kullan — platformdan çıkmak GEREKMEZ.
13
+ - `html` içinde platform verisi gösterme işi **Mustache + context**'le, platforma komut verme
14
+ işi **actions + fireEvent**'le kurulur. İkisini script içinde elle taklit etme.
15
+ - **"Alan sayısı/tipleri veriden geliyor" `html` sebebi DEĞİLDİR.** Dinamik form (anket, kural
16
+ tabanlı başvuru formu, satır başına farklı girdi) `repeater` + `{{ item.<alan> }}` iki yönlü
17
+ bağıyla hazır komponentlerle kurulur — tarif `platform_guide('page')` **Kural 1g**. Ölçüldü
18
+ (2026-08-19): aynı anket ekranı `html` ile de, native komponentlerle de uçtan uca çalışıyor;
19
+ native sürümde tema/erişilebilirlik/klavye davranışı ve doğrulama duvarı bedavaya geliyor.
20
+ `html`'i gerçekten katalogda karşılığı olmayan iş için sakla (üçüncü parti JS, alışılmadık
21
+ etkileşim). **Grafik artık o listede DEĞİL:** katalogda `chart` komponenti var (ECharts;
22
+ bar·line·area·pie·donut + waterfall/histogram/pareto/bullet/tornado/radial, drill-down ve dışa
23
+ aktarma dahil) — önce onu dene, `html` yalnız onun kapsamadığı görselleştirme için.
24
+
25
+ ## Prop sözleşmesi
26
+
27
+ | Prop | Sözleşme |
28
+ |---|---|
29
+ | `content` | Ham HTML. `{{` içeriyorsa Mustache şablonu olarak `context` ile render edilir; şablon hatası ham içeriğe düşer (sayfa ölmez). `type:'code'` + `{{ }}` ifadesiyle de beslenebilir |
30
+ | `context` | Mustache değişken sözlüğü (nesne). **Flow'dan HTML'e veri dönüşü budur:** setter adımı `context`'e yazınca içerik otomatik yeniden render olur |
31
+ | `style` | emotion `css()` bloğu: iç seçiciler (`.sinif { … }`, `&:hover`) çalışır, üretilen sınıf komponente scope'ludur — sayfa geneline sızmaz |
32
+ | `actions` | `[{ key, text, flow }]` — `key` fireEvent adı, `flow` çalıştırılacak akış (`type:'flow', ref:<flowId>`) |
33
+ | `isHidden` | Ortak katmandan gizler |
34
+
35
+ Şema olayı yalnız `mount`'tur. **Aksiyonlar `set_event` ile bağlanMAZ** — her aksiyon satırı
36
+ akışını kendi `flow` prop'unda taşır.
37
+
38
+ ## HTML → flow: fireEvent
39
+
40
+ ```html
41
+ <button onclick="fireEvent('kaydet', { tutar: 42 })">Kaydet</button>
42
+ <script>
43
+ document.querySelector('#ozel-grafik').addEventListener('dblclick', () => {
44
+ fireEvent('detay_ac', { kaynak: 'grafik' }) // script içinde komponent-bağlı, async güvenli
45
+ })
46
+ </script>
47
+ ```
48
+
49
+ - Akış tarafında `event.name = 'kaydet'`, `event.data = { tutar: 42 }` (`code` adımı ve
50
+ `value.type:'code'` ifadeleri).
51
+ - Satır içi öznitelik (`onclick="fireEvent(…)"`) global köprüyü kullanır; script gövdesindeki
52
+ `fireEvent` komponente bağlıdır ve `setTimeout`/`fetch.then` içinden de çalışır. Global'i
53
+ komponent dışından çağırman gerekirse üçüncü argümanla hedefi ver:
54
+ `fireEvent('kaydet', {...}, '<elementId>')`.
55
+ - Eşleşmeyen `key` ya da akışsız aksiyon console'a warn düşer — sessiz ölüm yok.
56
+
57
+ ## Flow → HTML: context + Mustache
58
+
59
+ ```jsonc
60
+ // content
61
+ "<ul>{{#satirlar}}<li>{{ad}} — {{adet}}</li>{{/satirlar}}</ul>"
62
+ // akışta: microservice → setter
63
+ { "type": "change", "element": "ozet_html", "property": "context", "source": "component",
64
+ "mapping": { "source": "", "mappings": {} },
65
+ "value": { "type": "code", "ref": "({ satirlar: Array.isArray(Steps.yukle?.data) ? Steps.yukle.data : [] })" } }
66
+ ```
67
+
68
+ `context` değişince içerik yeniden render olur ve **script'ler yeniden çalışır** — script'leri
69
+ yeniden girilebilir yaz ya da `onCleanup` kullan.
70
+
71
+ ## Script kuralları
72
+
73
+ - Satır içi `<script>` çalışır; içerik her değiştiğinde yeniden çalışır.
74
+ - `<script src="…">` **yüklenmez** (öznitelik bilinçli kopyalanmıyor). Harici kütüphane:
75
+ `loadScript(url)` — Promise döner, url bazında tekilleştirir, tekrar koşumda yeniden indirmez.
76
+ - `onCleanup(fn)`: interval/listener temizliği — bir sonraki script koşumundan önce ve
77
+ komponent yok edilirken çalışır.
78
+ - Script'ler flow ifade bağlamına (`Page`, `Steps`, komponent adları, `state.*`) ERİŞEMEZ;
79
+ köprü yalnız `fireEvent` (dışarı) ve `context` (içeri). Platform verisi gerekiyorsa akışta
80
+ toplayıp `context`'e yaz.
81
+
82
+ > Aşağıdaki örnek `loadScript`'in nasıl çalıştığını gösterir; **sıradan grafik ihtiyacı için
83
+ > `chart` komponentini kullan** (2026-08-25: katalogda kayıtlı).
84
+
85
+ ```html
86
+ <div id="grafik" style="height:300px"></div>
87
+ <script>
88
+ loadScript('https://cdn.jsdelivr.net/npm/chart.js').then(() => {
89
+ const chart = new Chart(document.querySelector('#grafik'), { /* … */ })
90
+ onCleanup(() => chart.destroy())
91
+ })
92
+ </script>
93
+ ```
94
+
95
+ ## Kötü / iyi
96
+
97
+ - ✘ Script içinde `fetch('/m/uygulama/uc')` ile platform ucunu elle çağırmak — kimlik/tenancy
98
+ dışında kalır. ✔ Akışta `microservice` adımı + setter ile `context`'e yaz.
99
+ - ✘ `content`'e sayfa değişkenini string birleştirmeyle gömmek. ✔ Mustache + `context`
100
+ (ya da `type:'code'` content).
101
+ - ✘ `set_event` ile `kaydet` olayına bağ kurmaya çalışmak (PAGE-008 reddeder). ✔ `actions`
102
+ satırının `flow` prop'u.
103
+ - ✘ `setInterval`'i temizliksiz kurmak (içerik değişince ikinci kopya başlar). ✔ `onCleanup`.
104
+
105
+ Kaynak: `zeyrek-frontend/packages/ng-apps-ui/src/components/html/*` (Html.svelte, html.functions.ts,
106
+ schema.ts) ve `zeyrek-frontend/docs/features/html-component.md`.