@appaflytech/zeyrek-ai-mcp 0.0.34 → 0.0.35
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/dist/knowledge/componentCatalog.js +387 -148
- package/dist/knowledge/componentEvents.js +16 -8
- package/dist/knowledge/normalize.js +18 -0
- package/dist/knowledge/rules.js +23 -0
- package/dist/knowledge/styleResolve.js +15 -3
- package/dist/knowledge/themeResolve.js +1 -1
- package/dist/knowledge/themeSchema.js +2 -1
- package/dist/resources/guides/component.md +1 -1
- package/dist/resources/guides/page.md +8 -0
- package/dist/resources/guides/theme.md +1 -0
- package/dist/tools/flows.js +7 -1
- package/package.json +1 -1
|
@@ -99,18 +99,18 @@ export const componentEventContracts = {
|
|
|
99
99
|
mount: NO_DATA,
|
|
100
100
|
change: {
|
|
101
101
|
payload: { value: 'FilterGroup (iç içe and/or kural ağacı)', jexl: 'string (aynı ağacın hazır jexl ifadesi)' },
|
|
102
|
-
reads: "setter yalnız `value`yi self’e yazar; `jexl` YALNIZ event.data’dadır (params) — sorguya bağlayacağın alan odur"
|
|
102
|
+
reads: "setter yalnız `value`yi self’e yazar; `jexl` YALNIZ event.data’dadır (params) — sorguya bağlayacağın alan odur. `value` (ağaç) de event.data’da gelir — State’e geri yazmak için event.data.value’yu kullan. Ağaç değişmediyse (etkin birleştiriciye yeniden basmak) olay yayılmaz"
|
|
103
103
|
}
|
|
104
104
|
},
|
|
105
105
|
comments: {
|
|
106
106
|
mount: NO_DATA,
|
|
107
107
|
submit: {
|
|
108
108
|
payload: { text: 'string', parentId: "string (yanıtsa üst yorumun id’si, kök yorumda '')", mentions: 'string[] (metinden çözülmüş @kişi listesi)', author: 'string (currentUser)' },
|
|
109
|
-
reads: 'Komponent yorumu ANINDA iyimser olarak listeye ekler (bekleyen katman); kalıcılık akışın işidir — rows
|
|
109
|
+
reads: 'Yük YALNIZ event.data’dadır (self.text/self.mentions boş gelir): {{ event.data.text }}. Komponent yorumu ANINDA iyimser olarak listeye ekler (bekleyen katman); kalıcılık akışın işidir — bekleyen satır, rows’a aynı üst yorum + metin (+ yazar) ile YENİ bir satır gelince yerini ona bırakır; akış kaydetmezse ya da metni değiştirirse "gönderiliyor…" kalır'
|
|
110
110
|
},
|
|
111
|
-
like: { payload: { id: 'string', liked: 'boolean (yeni durum)', author: 'string (currentUser — işlemi yapan)' }, reads: '
|
|
112
|
-
edit: { payload: { id: 'string', text: 'string (yeni metin)', author: 'string (currentUser — işlemi yapan)' }, reads: '
|
|
113
|
-
delete: { payload: { id: 'string', author: 'string (currentUser — işlemi yapan)' }, reads: '
|
|
111
|
+
like: { payload: { id: 'string', liked: 'boolean (yeni durum)', author: 'string (currentUser — işlemi yapan)' }, reads: 'Yük yalnız event.data’dadır. Beğeni de iyimserdir; sayaç rows tazelenene kadar yerel. isDisabled/isReadonly/isViewmode açıkken yayılmaz' },
|
|
112
|
+
edit: { payload: { id: 'string', text: 'string (yeni metin)', author: 'string (currentUser — işlemi yapan)' }, reads: 'Yük yalnız event.data’dadır. Düzenleme de iyimserdir; yeni metin "düzenlendi" işaretiyle rows tazelenene kadar yerel. Metin değişmediyse yayılmaz' },
|
|
113
|
+
delete: { payload: { id: 'string', author: 'string (currentUser — işlemi yapan)' }, reads: 'Yük yalnız event.data’dadır. Satır (kök yorumsa yanıtlarıyla birlikte) listeden hemen gizlenir; uca yazmak akışın işidir' }
|
|
114
114
|
},
|
|
115
115
|
'auth-layout': { mount: NO_DATA, primaryClick: NO_DATA, secondaryClick: NO_DATA },
|
|
116
116
|
layout: { mount: NO_DATA, logout: NO_DATA },
|
|
@@ -345,7 +345,7 @@ export const componentEventContracts = {
|
|
|
345
345
|
'audit-basic': { mount: NO_DATA },
|
|
346
346
|
'audit-history': {
|
|
347
347
|
mount: NO_DATA,
|
|
348
|
-
showMore: { payload: {}, reads: 'yalnız histories visibleLogCount’u aşınca çıkan "Daha fazla göster" düğmesine basılınca; görünür sınır visibleLogCount kadar büyür, kalan kalmayınca düğme kaybolur. Bileşen veri çekmez; backend kayıt başına en fazla 5 işlem verdiği için meta.history bağlıyken düğme ancak visibleLogCount < 5 iken çıkar' }
|
|
348
|
+
showMore: { payload: {}, reads: 'yalnız histories visibleLogCount’u aşınca çıkan "Daha fazla göster" düğmesine basılınca; görünür sınır visibleLogCount kadar büyür, kalan kalmayınca düğme kaybolur; en yeni (ilk) girdi değişince sınır başa döner. Bileşen veri çekmez; backend kayıt başına en fazla 5 işlem verdiği için meta.history bağlıyken düğme ancak visibleLogCount < 5 iken çıkar' }
|
|
349
349
|
},
|
|
350
350
|
'form-validation-errors': { mount: NO_DATA },
|
|
351
351
|
'page-header': {
|
|
@@ -371,7 +371,7 @@ export const componentEventContracts = {
|
|
|
371
371
|
},
|
|
372
372
|
click: {
|
|
373
373
|
payload: {},
|
|
374
|
-
reads:
|
|
374
|
+
reads: "Yalnız akışa bağlıysa çalışır (sarmalayıcı <div>; controls:false iken role=button + Enter/Boşluk da tetikler); controls açıkken videonun YÜZEYİNE tıklamak hem oynatır hem bu olayı tetikler, kontrol çubuğundaki yerel oynat/duraklat düğmesi ise videoyu oynatır AMA bu olayı TETİKLEMEZ (ölçüldü 2026-10-05). isLoading:true iken HİÇ çalışmaz — o dalda oynatıcı yerine iskelet çizilir ve sarmalayıcı tıklanabilir değildir"
|
|
375
375
|
},
|
|
376
376
|
play: {
|
|
377
377
|
payload: { isPlaying: 'boolean (true)' },
|
|
@@ -384,6 +384,14 @@ export const componentEventContracts = {
|
|
|
384
384
|
ended: {
|
|
385
385
|
payload: { isPlaying: 'boolean (false)' },
|
|
386
386
|
reads: 'loop açıkken HİÇ yayılmaz (döngü videosu bitmez). event.data: { currentTime, duration } — bitişte currentTime pratikte duration’a eşittir. Bitişte pause’dan SONRA gelir (spesifikasyon sırası), yani ended akışı pause akışının ardından koşar'
|
|
387
|
+
},
|
|
388
|
+
load: {
|
|
389
|
+
payload: {},
|
|
390
|
+
reads: "Kaynağın İLK KARESİ hazır olunca (loadeddata) yayılır; kaynak her değiştiğinde yeniden. Değer yazmaz (setter yok). event.data: { duration: number (saniye; sonsuz ya da bilinmiyorsa 0), width: number, height: number (kaynağın kendi piksel boyu) }. Yalnız oynatıcı çizilirken yayılır: isLoading:true iken <video> yoktur, load gelmez (iskeleti kaynağı çözen sorgudan kapat). Boş src'de ya da error'da yayılmaz"
|
|
391
|
+
},
|
|
392
|
+
error: {
|
|
393
|
+
payload: {},
|
|
394
|
+
reads: "Kaynak yüklenemediğinde yayılır (404, video olmayan dosya, desteklenmeyen biçim, ağ kopması). Değer yazmaz, ama isPlaying true ise false'a düşer. event.data: { code: number (MediaError.code: 1 iptal · 2 ağ · 3 çözümleme · 4 kaynak yok/desteklenmiyor), message: string (tarayıcıya bağlı, çoğu kez boş) }. Bileşen kendi hata görünümü çizmez: siyah kutu kalır, kullanıcıya bildirmek akışın işidir. Boş src'de yayılmaz"
|
|
387
395
|
}
|
|
388
396
|
},
|
|
389
397
|
// — 2026-08-25 eşleme turu: ng-apps-ui'da olay YAYAN ama burada kaydı olmayan komponentler.
|
|
@@ -662,7 +670,7 @@ export const componentEventContracts = {
|
|
|
662
670
|
fileName: 'string (okunan dosyanın adı; henüz dosya yoksa "")',
|
|
663
671
|
rowCount: 'number (dosyadaki HAM veri satırı sayısı — doğrulamadan önce)'
|
|
664
672
|
},
|
|
665
|
-
reads: "adım her değiştiğinde yayılır; currentStep ve fileName düğüme de yazılır (self.currentStep), rowCount yalnız event.data'dadır"
|
|
673
|
+
reads: "adım her değiştiğinde yayılır; currentStep ve fileName düğüme de yazılır (self.currentStep), rowCount yalnız event.data'dadır. resetAfterComplete açıkken complete'ten hemen sonra { currentStep: 0, fileName: tamamlanan dosya, rowCount: 0 } ile bir kez daha yayılır"
|
|
666
674
|
},
|
|
667
675
|
complete: {
|
|
668
676
|
payload: {
|
|
@@ -2,6 +2,7 @@ import { logStep } from '../observability/trace.js';
|
|
|
2
2
|
import { PlatformApiError } from '../platform/errors.js';
|
|
3
3
|
import { ensureWorkflowErrorPath } from './errorPath.js';
|
|
4
4
|
import { TYPED_STYLE_COMPONENTS } from './styleResolve.js';
|
|
5
|
+
import { FUNCTIONS_NAMESPACE } from './functionGuards.js';
|
|
5
6
|
const SORT_DEFAULT = { name: 'sortField', type: 'sortType', source: 'query-string' };
|
|
6
7
|
const LIMIT_DEFAULT = { name: 'limit', offset: 'offset', source: 'query-string' };
|
|
7
8
|
function asArray(value) {
|
|
@@ -358,6 +359,7 @@ const REQUIRED_COLLECTIONS = ['events', 'validations', 'stateBindings', 'childre
|
|
|
358
359
|
*
|
|
359
360
|
* - `states`: DesignComponentManagementSchema.ToDomain:47 `States.IsSticky`'yi guard'sız okur;
|
|
360
361
|
* Appearance'ın satır 24'te varsayılanı var, States'in yok.
|
|
362
|
+
* - `blocks` doldurulmaz: konum ebeveynin düzenine bağlıdır, eksikse PAGE-037 ile reddedilir.
|
|
361
363
|
* - `events` / `validations` / `stateBindings`: yalnız **micro-op yolunda** zorunlu.
|
|
362
364
|
* `page_create` (POST /pages) bunlarsız 200 döner, `PATCH …/schema` NRE verir; canlı deneyde
|
|
363
365
|
* üçü birlikte verilince geçti, her biri tek başına verilince patladı (klinik H-005 eki).
|
|
@@ -656,6 +658,11 @@ export function styleKeyNote(fixed) {
|
|
|
656
658
|
+ 'değer kaydedilir ama hiç uygulanmaz ve tek işareti tarayıcı konsoludur (F-06). '
|
|
657
659
|
+ "Seçici anahtarlara ('&__body', ':hover', '--token') dokunulmadı."];
|
|
658
660
|
}
|
|
661
|
+
/** PAGE-009 ile aynı kural: JS tanımlayıcısı (tireler çıkarılınca) ve ayrılmış `Functions` değil. */
|
|
662
|
+
function isDerivableComponentName(name) {
|
|
663
|
+
const bare = name.replace(/-/g, '');
|
|
664
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(bare) && bare !== FUNCTIONS_NAMESPACE;
|
|
665
|
+
}
|
|
659
666
|
/**
|
|
660
667
|
* Y-15 — adı eksik, null ya da boş/boşluk olan düğüm runtime'ın ifade ön sözünü bozar: `getNodeNames`
|
|
661
668
|
* null adı `"null"` anahtarına çevirir, `runCode` `const null = Components["null"]` satırını üretir
|
|
@@ -664,6 +671,7 @@ export function styleKeyNote(fixed) {
|
|
|
664
671
|
* hiç denetlemez (`PageSchemaValidator.cs`); Studio her düğüme `name = elementId` yazar
|
|
665
672
|
* (`ScreenBuilderDroppable.svelte`). Kural deterministik olduğu için reddetmek yerine dolduruyoruz.
|
|
666
673
|
* Doldurulan ad da PAGE-009'dan geçmek zorunda: çağıran bunu denetimden ÖNCE koşar. Dolu ada dokunulmaz.
|
|
674
|
+
* `normalizeComponentDefaults` aynı boşluğu yalnız geçerli bir elementId için ikinci kez kapatır (güvenlik ağı).
|
|
667
675
|
*/
|
|
668
676
|
export function fillComponentNames(nodes) {
|
|
669
677
|
const filled = [];
|
|
@@ -688,6 +696,16 @@ export function normalizeComponentDefaults(nodes) {
|
|
|
688
696
|
const fixed = [];
|
|
689
697
|
for (const node of asObjects(nodes)) {
|
|
690
698
|
const missing = [];
|
|
699
|
+
// name'siz düğümü platform kabul eder ama sayfada bir akış ya da `{{ }}` kod prop'u varsa
|
|
700
|
+
// FlowEngine runCode "Cannot read properties of undefined (reading 'catch')" ile düşer, akış
|
|
701
|
+
// `running:1`'de takılır ve hata adsız düğümü işaret etmez (image ölçüm turu, 2026-10-04).
|
|
702
|
+
// Yalnız PAGE-009'un geçerli saydığı elementId'den türetilir: page_create/page_update/layout
|
|
703
|
+
// yollarında PAGE-009 denetimi bu normalizasyondan ÖNCE koşar; bozuk bir elementId'den türeyen
|
|
704
|
+
// ad denetimi atlatıp "Missing initializer in const declaration" ile sayfayı öldürürdü.
|
|
705
|
+
if ((typeof node.name !== 'string' || node.name.trim() === '') && typeof node.elementId === 'string' && isDerivableComponentName(node.elementId)) {
|
|
706
|
+
node.name = node.elementId;
|
|
707
|
+
missing.push('name');
|
|
708
|
+
}
|
|
691
709
|
if (!node.states || typeof node.states !== 'object') {
|
|
692
710
|
node.states = { ...DEFAULT_STATES };
|
|
693
711
|
missing.push('states');
|
package/dist/knowledge/rules.js
CHANGED
|
@@ -2722,6 +2722,29 @@ export const policyRules = [
|
|
|
2722
2722
|
return findings;
|
|
2723
2723
|
})
|
|
2724
2724
|
},
|
|
2725
|
+
{
|
|
2726
|
+
id: 'FLOW-027',
|
|
2727
|
+
module: 'flow',
|
|
2728
|
+
appliesTo: ['create', 'update'],
|
|
2729
|
+
sourceRef: "2026-10-01 kanban ölçüm turu: steps ve errorSteps'te AYNI stepId ('start') flow_create'te 500 `An item with the same key has already been added. Key: start [ArgumentException]` verdi — platform adımları tek sözlüğe stepId anahtarıyla koyuyor, hata mesajı çakışmanın stepId olduğunu söylemiyor",
|
|
2730
|
+
check: definition => {
|
|
2731
|
+
const counts = new Map();
|
|
2732
|
+
for (const step of flowAllSteps(definition)) {
|
|
2733
|
+
if (!step.stepId)
|
|
2734
|
+
continue;
|
|
2735
|
+
counts.set(step.stepId, (counts.get(step.stepId) ?? 0) + 1);
|
|
2736
|
+
}
|
|
2737
|
+
const repeated = [...counts].filter(([, count]) => count > 1).map(([stepId]) => stepId);
|
|
2738
|
+
return repeated.length === 0
|
|
2739
|
+
? []
|
|
2740
|
+
: [{
|
|
2741
|
+
ruleId: 'FLOW-027',
|
|
2742
|
+
severity: 'block',
|
|
2743
|
+
message: `stepId'ler akışta (steps + errorSteps birlikte) benzersiz olmalı; tekrar edenler: ${repeated.map(id => `'${id}'`).join(', ')}. Platform bunları tek sözlüğe anahtar olarak koyar ve "An item with the same key has already been added" ile 500 verir (mesaj stepId'den söz etmez). errorSteps'te de kendi 'start' adımı gerekiyorsa ona farklı bir stepId verin (örn. 'err_start').`,
|
|
2744
|
+
guide: 'ngapps://guides/page'
|
|
2745
|
+
}];
|
|
2746
|
+
}
|
|
2747
|
+
},
|
|
2725
2748
|
{
|
|
2726
2749
|
id: 'MS-013',
|
|
2727
2750
|
module: 'microservice',
|
|
@@ -395,7 +395,9 @@ const STATCARD_FLEX_ALIGN = {
|
|
|
395
395
|
left: 'flex-start',
|
|
396
396
|
center: 'center',
|
|
397
397
|
right: 'flex-end',
|
|
398
|
-
justify: 'stretch'
|
|
398
|
+
justify: 'stretch',
|
|
399
|
+
start: 'flex-start',
|
|
400
|
+
end: 'flex-end'
|
|
399
401
|
};
|
|
400
402
|
function composeStatCardParts(input, root) {
|
|
401
403
|
const value = input.valueStyle;
|
|
@@ -496,6 +498,18 @@ export const TYPED_STYLE_COMPONENTS = {
|
|
|
496
498
|
groups: ['surfaceStyle'],
|
|
497
499
|
ext: { overflowTarget: ROOT_TARGET }
|
|
498
500
|
},
|
|
501
|
+
modal: {
|
|
502
|
+
// Panel portal ile düğüm kutusunun DIŞINA çizilir; yüzey panelin KÖKÜNDE
|
|
503
|
+
// derlenir, taşma da panelin köküne iner (modal ölçümü, 2026-10-05).
|
|
504
|
+
groups: ['surfaceStyle'],
|
|
505
|
+
ext: { overflowTarget: ROOT_TARGET }
|
|
506
|
+
},
|
|
507
|
+
drawer: {
|
|
508
|
+
// Panel portal ile düğüm kutusunun DIŞINA çizilir; yüzey panelin KÖKÜNDE
|
|
509
|
+
// derlenir, taşma da panelin köküne iner (drawer ölçümü, 2026-10-05).
|
|
510
|
+
groups: ['surfaceStyle'],
|
|
511
|
+
ext: { overflowTarget: ROOT_TARGET }
|
|
512
|
+
},
|
|
499
513
|
icon: {
|
|
500
514
|
// Yalnız hover: surface çipin (chipShape/chipColor), typography da boyutun
|
|
501
515
|
// (size) ve rengin (color) çift kanalı olurdu — görsel kararlar semantik
|
|
@@ -517,8 +531,6 @@ export const NODE_SURFACE_TYPES = new Set([
|
|
|
517
531
|
'table',
|
|
518
532
|
'datatable',
|
|
519
533
|
'collapsible-container',
|
|
520
|
-
'drawer',
|
|
521
|
-
'modal',
|
|
522
534
|
'popover',
|
|
523
535
|
'tabs',
|
|
524
536
|
'stepper',
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* `theme_get` bunları `unknownKeys` olarak gösterir, `theme_update` şeması reddeder.
|
|
30
30
|
*/
|
|
31
31
|
export const THEME_TOP_LEVEL_KEYS = [
|
|
32
|
-
'mode', 'palette', 'paletteDark', 'fontFamily', 'headingFontFamily', 'typeScale',
|
|
32
|
+
'mode', 'direction', 'palette', 'paletteDark', 'fontFamily', 'headingFontFamily', 'typeScale',
|
|
33
33
|
'fontSize', 'fontWeight', 'borderRadius', 'radiusScale', 'spacing', 'spacingScale',
|
|
34
34
|
'shadow', 'defaultInputSize', 'colors', 'actions', 'presets', 'componentStyles',
|
|
35
35
|
'componentPresets'
|
|
@@ -30,7 +30,7 @@ export function summarizeTheme(theme) {
|
|
|
30
30
|
if (entries.length > 0)
|
|
31
31
|
overrides[key] = entries;
|
|
32
32
|
}
|
|
33
|
-
for (const key of ['fontFamily', 'headingFontFamily', 'fontSize', 'fontWeight', 'spacing', 'borderRadius', 'defaultInputSize']) {
|
|
33
|
+
for (const key of ['fontFamily', 'headingFontFamily', 'fontSize', 'fontWeight', 'spacing', 'borderRadius', 'defaultInputSize', 'direction']) {
|
|
34
34
|
if (record[key] !== undefined)
|
|
35
35
|
overrides[key] = record[key];
|
|
36
36
|
}
|
|
@@ -91,6 +91,7 @@ const ratioScale = (levels) => z.object(Object.fromEntries(levels.map(level => [
|
|
|
91
91
|
*/
|
|
92
92
|
export const themeInput = z.object({
|
|
93
93
|
mode: z.enum(['light', 'dark']),
|
|
94
|
+
direction: z.enum(['ltr', 'rtl', 'auto']),
|
|
94
95
|
palette: paletteSchema,
|
|
95
96
|
paletteDark: paletteSchema,
|
|
96
97
|
fontFamily: z.string().min(1),
|
|
@@ -127,7 +127,7 @@ Her şema düğümünde iki sözlük vardır; ikisi de ortak render katmanında
|
|
|
127
127
|
|
|
128
128
|
| `appearance` | Değerler | Anlamı |
|
|
129
129
|
|---|---|---|
|
|
130
|
-
| `heightType` | `auto` · `fixed` · `fill` | `auto`: içerik kadar (önerilen — Kural 1d); `fixed`: `heightString` varsa o, yoksa `blocks.h × 10px`; `fill`: **kalanı doldur** — ebeveynin bıraktığı yer (ızgarada `height:100%`, flex sütununda `flex:1 1 auto`, flex satırında `align-self:stretch`). Tam ekran yerleşim kabuğu bununla kurulur, bkz. `platform_guide('layout')` |
|
|
130
|
+
| `heightType` | `auto` · `fixed` · `fill` | `auto`: içerik kadar (önerilen — Kural 1d); `fixed`: `heightString` varsa o, yoksa `blocks.h × 10px`; `fill`: **kalanı doldur** — ebeveynin bıraktığı yer (ızgarada `height:100%`, flex sütununda `flex:1 1 auto`, flex satırında `align-self:stretch`). Tam ekran yerleşim kabuğu bununla kurulur, bkz. `platform_guide('layout')`. **Mobilde (≤ 767 px) mobil bloğu olmayan her düğüme `height: auto !important` yazılır**: yüksekliği `height` olarak yazılan `fixed` düğüm (flex ya da CSS grid ebeveyni, stretch yokken) içeriğine göre çizilir; stretch'li satırdaki `min-height` ve 12 kolonlu eski ebeveynin `grid-row` yüksekliği bundan bağımsızdır. Yazılı yüksekliği mobilde de istiyorsan (`heightType: 'fixed'` iken) `appearance.className`'e ayrılmış **`ng-keep-height-mobile`** belirtecini yaz (`className: "hero ng-keep-height-mobile"`) |
|
|
131
131
|
| `widthType` | `cover` · `contain` · `auto` · `fixed` · `fill` | İlk ikisi görsel/medya sığdırma. Kalanı **flex (ve eski cssgrid) kabın çocuğunun genişlik modu** (2026-09-01): `auto` içerik kadar, `fixed` `widthString`'den, `fill` kabın tüm genişliği (satırda `flex:1 1 100%`, sütunda `align-self:stretch`). **Yazılmazsa eski 12 kolon `blocks.size.w` payı geçerlidir** — öncelik: `fill` > `fixed` > `auto` > span |
|
|
132
132
|
| `widthString` / `heightString` | CSS uzunluğu | Sabit ölçü; **yalnız ilgili `*Type: 'fixed'` iken okunur** (aksi PAGE-017 uyarısı). Kabul: çıplak sayı (px sayılır) · `px % vw vh vmin vmax rem em ch` birimli değer · `calc(...)`. Negatif/`pt`/`fr`/`auto` GEÇMEZ — platform kaydeder ama panel ve runtime sessizce düşürür (PAGE-018). Eski `widthPx` alanı 2026-09-01'de kaldırıldı |
|
|
133
133
|
| `marginType` / `marginValue` | `normal` · `none` · `custom` + px | Dış boşluk: **yazılmazsa `normal` sayılır** = her kenara 4px (`spacing.ts` `CANVAS_NORMAL_MARGIN`); custom=`marginValue`. Bileşenleri dip dibe dizmek için `none` ŞART — `gap:'none'` olsa bile normal margin komşular arasında 8px bırakır (sıkı dizilim tarifi: `platform_guide('page')` Kural 1f-2) |
|
|
@@ -670,6 +670,14 @@ Tire yerine `_` kullan.
|
|
|
670
670
|
> `component_schema_patch` yamalarında), `layout_create`, `layout_update(views)` ve `layout_patch`;
|
|
671
671
|
> `page_schema_validate` aynı kararı verir. Ad doldurulduktan sonra denetlenir: geçersiz bir
|
|
672
672
|
> elementId adsız gelirse o da reddedilir.
|
|
673
|
+
>
|
|
674
|
+
> **`name` hiç verilmezse** gateway onu `elementId` ile tamamlar ve `gatewayNormalized`'da `name`
|
|
675
|
+
> diye bildirir: adsız düğümü platform kabul eder ama sayfada bir akış ya da `{{ }}` kod prop'u
|
|
676
|
+
> varsa FlowEngine `runCode` "Cannot read properties of undefined (reading 'catch')" ile düşer, akış
|
|
677
|
+
> `running:1`'de takılır ve hata adsız düğümü işaret etmez. Tamamlama PAGE-009 denetiminden ÖNCE
|
|
678
|
+
> koşar, yani `elementId` bu kuralın geçerli saydığı bir ad değilse (`'Ana Baslik'`, `'1abc'`,
|
|
679
|
+
> `'Functions'`) tamamlanan ad da reddedilir. Yine de her `add_component` gövdesine
|
|
680
|
+
> `name = elementId` yaz; tamamlama bir güvenlik ağıdır.
|
|
673
681
|
|
|
674
682
|
## Kural 1d — Sayfa iskeleti: `page_container` ve boyutlandırma
|
|
675
683
|
|
|
@@ -18,6 +18,7 @@ yazmalarının aksine burada "önce development'ta dene" diye bir ayrım YOKTUR.
|
|
|
18
18
|
| Alan | Ne yapar | Ürettiği değişken(ler) |
|
|
19
19
|
|---|---|---|
|
|
20
20
|
| `mode` | `'light'` (varsayılan) \| `'dark'` — yayınlanan uygulamanın modu | palet tabanını seçer |
|
|
21
|
+
| `direction` | `'ltr'` \| `'rtl'` \| `'auto'` — sayfanın okuma yönü; `auto` uygulama dilinden türetir (`ar` `he` `fa` `ur` `ps` `sd` `ug` `yi` `dv` → rtl). Ayar YOKSA `dir` hiç yazılmaz (sayfa üst öğenin yönünü miras alır): `ar` ile kurulmuş mevcut proje bu ayar açılmadan aynalanmaz. Sayfa oluşturucu tuvali yönü uygulamaz. Grid yerleşimi kendiliğinden aynalanır; bileşenlerin ok simgeleri ve fiziksel `left/right` CSS'i bileşen bazında düzeltilir (ADR 0006) | CSS değişkeni üretmez, kap `dir` özniteliğine yazılır |
|
|
21
22
|
| `palette` | AYDINLIK moddaki renk override'ları; `accent.onPrimary` isteğe bağlıdır — accent ÜSTÜNDEKİ metin, verilmezse kontrasttan türer (`#4787FA` gibi açık bir mavi siyah metin üretir, tasarımda beyazsa buraya yazın) | `--ng-accent-*` · `--ng-background-*` · `--ng-text-*` · `--ng-border-*` · `--ng-status-*` · `--ng-text-on-accent` |
|
|
22
23
|
| `paletteDark` | KARANLIK moddaki renk override'ları | aynı küme |
|
|
23
24
|
| `fontFamily` · `headingFontFamily` | Gövde ve başlık yazı tipi (Google Fonts adı) | `--ng-font` · `--ng-font-heading` |
|
package/dist/tools/flows.js
CHANGED
|
@@ -428,8 +428,14 @@ export function registerFlowTools(server, platform) {
|
|
|
428
428
|
};
|
|
429
429
|
const authored = { steps: steps ?? [], errorSteps: errorSteps ?? [] };
|
|
430
430
|
const normalized = [...normalizeFlowSteps(authored.steps), ...normalizeFlowSteps(authored.errorSteps)];
|
|
431
|
+
// Kurallar yalnız GÖNDERİLEN adımlara bakar (kayıtlı gövdeyi suçlamamak için); stepId
|
|
432
|
+
// benzersizliği ise birleşik akışta ölçülür: yalnız steps verilip kayıtlı errorSteps'le
|
|
433
|
+
// çakışan kimlik de platformda 500 verir.
|
|
431
434
|
const findings = steps || errorSteps
|
|
432
|
-
?
|
|
435
|
+
? [
|
|
436
|
+
...enforcePolicy(evaluatePolicy(config, policyRules, 'flow', authored, { operation: 'update' }, policyOverride)),
|
|
437
|
+
...enforcePolicy(evaluatePolicy(config, policyRules, 'flow', flow, { operation: 'update' }, policyOverride).filter(finding => finding.ruleId === 'FLOW-027'))
|
|
438
|
+
]
|
|
433
439
|
: [];
|
|
434
440
|
const parameterWarnings = [
|
|
435
441
|
...await requiredParameterWarnings(platform, project, environment, applicationId, flow.steps),
|
package/package.json
CHANGED