@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.
- package/.env.example +46 -0
- package/README.md +260 -0
- package/dist/config.js +128 -0
- package/dist/index.js +88 -0
- package/dist/knowledge/componentCatalog.js +438 -0
- package/dist/knowledge/componentEvents.js +164 -0
- package/dist/knowledge/coverage.js +60 -0
- package/dist/knowledge/normalize.js +1309 -0
- package/dist/knowledge/outlines.js +167 -0
- package/dist/knowledge/policy.js +44 -0
- package/dist/knowledge/reservedTables.js +75 -0
- package/dist/knowledge/rules.js +1725 -0
- package/dist/observability/trace.js +337 -0
- package/dist/platform/errors.js +132 -0
- package/dist/platform/http.js +169 -0
- package/dist/platform/responses.js +94 -0
- package/dist/platform/token.js +79 -0
- package/dist/resources/examples/entity-pair-m2m.json +105 -0
- package/dist/resources/examples/flow-list-to-form.json +65 -0
- package/dist/resources/examples/flow-load-table.json +178 -0
- package/dist/resources/examples/microservice-table-list.json +49 -0
- package/dist/resources/examples/middleware-authenticate.json +194 -0
- package/dist/resources/examples/page-detail-profile.json +95 -0
- package/dist/resources/examples/page-dynamic-form.json +221 -0
- package/dist/resources/examples/page-form-upsert.json +279 -0
- package/dist/resources/examples/page-html-embed.json +106 -0
- package/dist/resources/examples/page-sign-in.json +194 -0
- package/dist/resources/examples/workflow-basic.json +94 -0
- package/dist/resources/guides/component.md +108 -0
- package/dist/resources/guides/entity.md +348 -0
- package/dist/resources/guides/expressions.md +139 -0
- package/dist/resources/guides/getting-started.md +109 -0
- package/dist/resources/guides/html.md +106 -0
- package/dist/resources/guides/microservice.md +313 -0
- package/dist/resources/guides/middleware.md +271 -0
- package/dist/resources/guides/modify-existing.md +35 -0
- package/dist/resources/guides/page.md +1574 -0
- package/dist/resources/guides/view.md +89 -0
- package/dist/resources/guides/workflow.md +359 -0
- package/dist/resources/knowledge.js +44 -0
- package/dist/resources/schemas/CreateDatasourceCommand.json +54 -0
- package/dist/resources/schemas/CreateDiscoveredEntitiesCommand.json +133 -0
- package/dist/resources/schemas/CreateEntityCommand.json +387 -0
- package/dist/resources/schemas/CreateMicroserviceCommand.json +528 -0
- package/dist/resources/schemas/CreateQueryCommand.json +43 -0
- package/dist/resources/schemas/CreateViewCommand.json +158 -0
- package/dist/resources/schemas/CreateWorkflowCommand.json +1719 -0
- package/dist/resources/schemas/Filter.json +124 -0
- package/dist/resources/schemas/GetRowsQuery.json +122 -0
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +565 -0
- package/dist/resources/schemas/PreviewQueryCommand.json +74 -0
- package/dist/resources/schemas/PreviewWorkflowCommand.json +981 -0
- package/dist/resources/schemas/StepDto.json +900 -0
- package/dist/resources/schemas/UpdateDatasourceCommand.json +58 -0
- package/dist/resources/schemas/UpdateEntityCommand.json +679 -0
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +512 -0
- package/dist/resources/schemas/UpdateQueryCommand.json +86 -0
- package/dist/resources/schemas/UpdateViewCommand.json +153 -0
- package/dist/resources/schemas/UpdateWorkflowCommand.json +1719 -0
- package/dist/resources/schemas.js +40 -0
- package/dist/server.js +63 -0
- package/dist/tools/access.js +27 -0
- package/dist/tools/applications.js +59 -0
- package/dist/tools/automations.js +103 -0
- package/dist/tools/common.js +18 -0
- package/dist/tools/components.js +280 -0
- package/dist/tools/datasources.js +82 -0
- package/dist/tools/dependencies.js +17 -0
- package/dist/tools/deployments.js +17 -0
- package/dist/tools/dtos.js +54 -0
- package/dist/tools/entities.js +166 -0
- package/dist/tools/files.js +138 -0
- package/dist/tools/flows.js +226 -0
- package/dist/tools/folders.js +51 -0
- package/dist/tools/layouts.js +105 -0
- package/dist/tools/microservices.js +198 -0
- package/dist/tools/organizations.js +65 -0
- package/dist/tools/pages.js +597 -0
- package/dist/tools/platformInfo.js +44 -0
- package/dist/tools/projects.js +152 -0
- package/dist/tools/queries.js +48 -0
- package/dist/tools/rows.js +115 -0
- package/dist/tools/screens.js +97 -0
- package/dist/tools/templates.js +65 -0
- package/dist/tools/variables.js +94 -0
- package/dist/tools/views.js +58 -0
- package/dist/tools/workflows.js +196 -0
- 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`.
|