@appaflytech/zeyrek-ai-mcp 0.0.31 → 0.0.33
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/README.md +5 -5
- package/dist/config.js +0 -26
- package/dist/knowledge/backendConstraints.js +1 -18
- package/dist/knowledge/componentCatalog.js +27 -493
- package/dist/knowledge/componentEvents.js +2 -120
- package/dist/knowledge/connectDataDefinition.js +4 -4
- package/dist/knowledge/connectDataRules.js +1 -1
- package/dist/knowledge/mobileComponentCatalog.js +13 -8
- package/dist/knowledge/mobileStore.js +227 -0
- package/dist/knowledge/normalize.js +48 -131
- package/dist/knowledge/outlines.js +0 -36
- package/dist/knowledge/platform/lint.js +1 -1
- package/dist/knowledge/platform/nativeBoxModel.js +1 -1
- package/dist/knowledge/policy.js +4 -18
- package/dist/knowledge/process.js +1 -1
- package/dist/knowledge/reservedTables.js +0 -79
- package/dist/knowledge/rules.js +10 -83
- package/dist/knowledge/schemaGuard.js +0 -11
- package/dist/observability/trace.js +2 -5
- package/dist/platform/capture/capture.js +1 -25
- package/dist/platform/errors.js +10 -162
- package/dist/platform/http.js +1 -6
- package/dist/platform/responses.js +4 -34
- package/dist/platform/schemaReadMemory.js +2 -2
- package/dist/platform/secrets.js +1 -8
- package/dist/resources/examples/middleware-authenticate.json +1 -1
- package/dist/resources/examples/mobile-app-shell-drawer.json +62 -61
- package/dist/resources/examples/mobile-list-detail-form.json +51 -20
- package/dist/resources/examples/page-detail-profile.json +1 -2
- package/dist/resources/examples/page-dynamic-form.json +2 -3
- package/dist/resources/examples/page-html-embed.json +1 -1
- package/dist/resources/examples/workflow-basic.json +2 -8
- package/dist/resources/guides/access.md +4 -18
- package/dist/resources/guides/bpm.md +1 -6
- package/dist/resources/guides/component.md +4 -83
- package/dist/resources/guides/entity.md +8 -50
- package/dist/resources/guides/getting-started.md +1 -38
- package/dist/resources/guides/merge.md +3 -37
- package/dist/resources/guides/microservice.md +0 -78
- package/dist/resources/guides/middleware.md +3 -35
- package/dist/resources/guides/mobile.md +85 -2
- package/dist/resources/guides/page.md +26 -278
- package/dist/resources/guides/workflow.md +0 -51
- package/dist/resources/rules.js +5 -11
- package/dist/resources/schema-fingerprint.json +5 -7
- package/dist/resources/schemas/CreateEntityCommand.json +0 -118
- package/dist/resources/schemas/CreateMicroserviceCommand.json +1 -13
- package/dist/resources/schemas/CreateQueryCommand.json +0 -4
- package/dist/resources/schemas/CreateWorkflowCommand.json +1 -146
- package/dist/resources/schemas/DataJobDto.json +1 -6
- package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +2 -20
- package/dist/resources/schemas/MicroserviceDto.json +1 -13
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +1 -10
- package/dist/resources/schemas/PreviewWorkflowCommand.json +1 -25
- package/dist/resources/schemas/StartMobileBuildCommand.json +54 -0
- package/dist/resources/schemas/StepDto.json +1 -25
- package/dist/resources/schemas/UpdateEntityCommand.json +0 -118
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +1 -13
- package/dist/resources/schemas/UpdateQueryCommand.json +0 -4
- package/dist/resources/schemas/UpdateViewCommand.json +2 -0
- package/dist/resources/schemas/UpdateWorkflowCommand.json +1 -146
- package/dist/resources/schemas/UpsertMobileStoreSettingsCommand.json +259 -0
- package/dist/server.js +5 -25
- package/dist/tools/access.js +2 -369
- package/dist/tools/common.js +0 -7
- package/dist/tools/components.js +2 -15
- package/dist/tools/datasources.js +2 -2
- package/dist/tools/dependencies.js +1 -1
- package/dist/tools/deployments.js +3 -38
- package/dist/tools/designSchemaPatch.js +3 -13
- package/dist/tools/dtos.js +5 -36
- package/dist/tools/entities.js +12 -79
- package/dist/tools/externalComponents.js +1 -1
- package/dist/tools/flows.js +10 -45
- package/dist/tools/folders.js +1 -1
- package/dist/tools/imports.js +2 -5
- package/dist/tools/layouts.js +5 -6
- package/dist/tools/merges.js +2 -2
- package/dist/tools/microservices.js +20 -50
- package/dist/tools/mobileStore.js +268 -0
- package/dist/tools/pages.js +35 -89
- package/dist/tools/platformInfo.js +6 -20
- package/dist/tools/projects.js +9 -71
- package/dist/tools/rows.js +12 -62
- package/dist/tools/schemaOps.js +1 -29
- package/dist/tools/screenWrite.js +1 -22
- package/dist/tools/screens.js +3 -6
- package/dist/tools/templates.js +1 -26
- package/dist/tools/translations.js +1 -1
- package/dist/tools/workflows.js +5 -10
- package/package.json +2 -2
|
@@ -3,7 +3,6 @@ import { PlatformApiError } from '../platform/errors.js';
|
|
|
3
3
|
import { ensureWorkflowErrorPath } from './errorPath.js';
|
|
4
4
|
import { DOCUMENT_STYLE_TYPES, TYPED_STYLE_COMPONENTS } from './styleResolve.js';
|
|
5
5
|
import { STATE_STORAGE_KINDS, STEP_ALIASES } from './platform/profile.js';
|
|
6
|
-
import { inlineStyleFields } from './componentCatalog.js';
|
|
7
6
|
const SORT_DEFAULT = { name: 'sortField', type: 'sortType', source: 'query-string' };
|
|
8
7
|
const LIMIT_DEFAULT = { name: 'limit', offset: 'offset', source: 'query-string' };
|
|
9
8
|
function asArray(value) {
|
|
@@ -373,17 +372,9 @@ const REQUIRED_COLLECTIONS = ['events', 'validations', 'stateBindings', 'childre
|
|
|
373
372
|
// PropValueType (DesignComponentProperty.cs:421) — 'translation' listeden düşünce çeviriye bağlı
|
|
374
373
|
// prop'un KENDİSİ veri sanılıp static Prop'a sarılıyordu: istek 200 dönüyor, prop bozuk kuruluyordu
|
|
375
374
|
// (09-04 Y-22). Enum burada eksiksiz tutulur.
|
|
376
|
-
export const PROP_VALUE_TYPES = new Set(['static', 'file', 'flow', 'widget', 'element', 'page', 'code', 'translation'
|
|
377
|
-
// Prop'un TAŞIYICISI da aranır: `type` tek başına yetmez, çünkü liste öğesinin kendi `type` alanı
|
|
378
|
-
// olabilir ve değeri Prop tipi adıyla çakışabilir — datatable kolonunda dosya alanı tam olarak
|
|
379
|
-
// böyledir (`{ name, label, type: 'file', isFilterable }`). Yalnız `type`'a bakan sürüm o öğeyi
|
|
380
|
-
// kurulu bir Prop sanıp sarmadan bırakıyordu ve platform 500 JsonException veriyordu (koşu
|
|
381
|
-
// bulgusu S-2'nin gateway ayağı; Studio ayağı `staticFieldListItems` ile aynı kararı verdi).
|
|
375
|
+
export const PROP_VALUE_TYPES = new Set(['static', 'file', 'flow', 'widget', 'element', 'page', 'code', 'translation']);
|
|
382
376
|
function isPropShaped(value) {
|
|
383
|
-
|
|
384
|
-
return false;
|
|
385
|
-
const candidate = value;
|
|
386
|
-
return PROP_VALUE_TYPES.has(String(candidate.type)) && ('data' in candidate || 'ref' in candidate);
|
|
377
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value) && PROP_VALUE_TYPES.has(String(value.type));
|
|
387
378
|
}
|
|
388
379
|
function wrapPropDictionaryValues(dictionary) {
|
|
389
380
|
let wrapped = false;
|
|
@@ -626,16 +617,12 @@ export function codePropTemplateErrors(ops) {
|
|
|
626
617
|
*
|
|
627
618
|
* Seçici anahtarlara (`&__body`, `:hover`, `--token`) DOKUNULMAZ; yalnız `a-b` biçimli düz CSS
|
|
628
619
|
* özellik adları camelCase'e çevrilir ve çevrim `gatewayNormalized` ile bildirilir.
|
|
629
|
-
*
|
|
630
|
-
* TB-129 — `inlineFields` verilirse o ÜST DÜZEY alanların altına hiç girilmez: `table.style.th`
|
|
631
|
-
* gibi dallar satır içi `style` attribute'una basılır ve kebab-case zorunludur
|
|
632
|
-
* (`INLINE_STYLE_FIELDS_BY_TYPE`). Çeviri orada stili öldürüyordu.
|
|
633
620
|
*/
|
|
634
621
|
const styleKeyPattern = /^[a-z][a-z0-9]*(-[a-z0-9]+)+$/;
|
|
635
622
|
export function isStylePropName(name) {
|
|
636
623
|
return name === 'style' || /Style$/.test(name);
|
|
637
624
|
}
|
|
638
|
-
export function normalizeStyleKeys(value, label, fixed
|
|
625
|
+
export function normalizeStyleKeys(value, label, fixed) {
|
|
639
626
|
if (Array.isArray(value)) {
|
|
640
627
|
for (const entry of value)
|
|
641
628
|
normalizeStyleKeys(entry, label, fixed);
|
|
@@ -644,10 +631,7 @@ export function normalizeStyleKeys(value, label, fixed, inlineFields) {
|
|
|
644
631
|
if (!value || typeof value !== 'object')
|
|
645
632
|
return;
|
|
646
633
|
const record = value;
|
|
647
|
-
const skipped = new Set(inlineFields ?? []);
|
|
648
634
|
for (const key of Object.keys(record)) {
|
|
649
|
-
if (skipped.has(key))
|
|
650
|
-
continue;
|
|
651
635
|
normalizeStyleKeys(record[key], label, fixed);
|
|
652
636
|
if (!styleKeyPattern.test(key))
|
|
653
637
|
continue;
|
|
@@ -746,10 +730,8 @@ export function normalizeComponentDefaults(nodes) {
|
|
|
746
730
|
if (node.props && typeof node.props === 'object' && !Array.isArray(node.props)) {
|
|
747
731
|
const props = node.props;
|
|
748
732
|
const styleKeys = [];
|
|
749
|
-
// Satır içi stil dalları komponent TİPİNE göre atlanır; tip bilinmiyorsa eski davranış.
|
|
750
|
-
const inlineFields = (name) => name === 'style' ? inlineStyleFields(typeof node.type === 'string' ? node.type : undefined) : undefined;
|
|
751
733
|
for (const name of Object.keys(props).filter(isStylePropName)) {
|
|
752
|
-
normalizeStyleKeys(props[name], `${String(node.elementId ?? node.name ?? '?')}.${name}`, styleKeys
|
|
734
|
+
normalizeStyleKeys(props[name], `${String(node.elementId ?? node.name ?? '?')}.${name}`, styleKeys);
|
|
753
735
|
}
|
|
754
736
|
if (styleKeys.length > 0)
|
|
755
737
|
missing.push(`stil anahtarları camelCase'e çevrildi: ${styleKeys.join(' · ')}`);
|
|
@@ -854,31 +836,19 @@ function normalizeReplacePropValue(op) {
|
|
|
854
836
|
}
|
|
855
837
|
return notes;
|
|
856
838
|
}
|
|
857
|
-
// connectData sarmalı burada değiştirilmez: gövde duvarı (CD-005, `connectDataOpIssues`) op'u
|
|
858
|
-
// set_connect_data'ya yönlendirerek rejectedOps'a yazar; burada atmak listeyi tek hataya indirirdi.
|
|
859
|
-
if (propType === 'connectData')
|
|
860
|
-
return notes;
|
|
861
839
|
// Applier her sarmalın tipini korur, ama page/file/flow/widget/element taşıyıcıları başka alanlara
|
|
862
840
|
// (FlowId, RedirectPageId, dosya) yazılır ve bu op'la bağları kurulmaz. Remove+add önerilmez:
|
|
863
841
|
// düğümü yeniden kurmak ona yazan setter iteratee'lerinin element'ini siler (G-04, FLOW-018).
|
|
864
842
|
throw new PlatformApiError(`${label}: '${propType}' tipli Prop replace_prop ile kurulmaz — bu op static, code ve translation sarmalını taşır. Komponenti silip yeniden EKLEMEYİN: ona yazan setter adımlarının hedefi silinir (FLOW-018). Akış bağı için set_event, diğer tipler için page_update(schema) ile tam şema yazın.`, 400);
|
|
865
843
|
}
|
|
866
|
-
|
|
867
|
-
* `typesByElementId` — TB-129: `replace_prop` op'u yalnız elementId taşır, stil çevirisinin
|
|
868
|
-
* komponent tipine bakabilmesi için haritayı çağıran (okuduğu şemadan) verir. Verilmezse çeviri
|
|
869
|
-
* tip ayrımı yapmaz; bu, harita okunamadığında yazmayı engellememek için bilinçli düşüştür.
|
|
870
|
-
*/
|
|
871
|
-
export function normalizeSchemaOps(ops, typesByElementId) {
|
|
844
|
+
export function normalizeSchemaOps(ops) {
|
|
872
845
|
const components = [];
|
|
873
846
|
const props = [];
|
|
874
847
|
const validations = [];
|
|
875
848
|
for (const op of asObjects(ops)) {
|
|
876
849
|
if (op.op === 'replace_prop') {
|
|
877
850
|
if (isStylePropName(String(op.prop ?? ''))) {
|
|
878
|
-
|
|
879
|
-
? inlineStyleFields(typesByElementId?.get(String(op.target ?? '')))
|
|
880
|
-
: undefined;
|
|
881
|
-
normalizeStyleKeys(op.value, `'${String(op.target ?? '?')}.${String(op.prop)}'`, props, inline);
|
|
851
|
+
normalizeStyleKeys(op.value, `'${String(op.target ?? '?')}.${String(op.prop)}'`, props);
|
|
882
852
|
}
|
|
883
853
|
props.push(...normalizeReplacePropValue(op));
|
|
884
854
|
continue;
|
|
@@ -2095,95 +2065,6 @@ export function flowBindings(schema, hostEvents) {
|
|
|
2095
2065
|
visitNode(node);
|
|
2096
2066
|
return bindings;
|
|
2097
2067
|
}
|
|
2098
|
-
/**
|
|
2099
|
-
* TB-125 — op listesi UYGULANDIKTAN sonra şemada (ve düzey olaylarında) hâlâ referanslı olan
|
|
2100
|
-
* akışlar. Simülasyon yalnız akış referansını umursar: eklenen düğüm ağacın köküne konur (konum
|
|
2101
|
-
* sayıma girmez), silinen düğüm ağaçtan çıkarılır, olay op'ları olay dizisini günceller.
|
|
2102
|
-
* `batch` op'u iç listesiyle düzleştirilir.
|
|
2103
|
-
*/
|
|
2104
|
-
function survivingFlowRefs(nodes, hostEvents, ops) {
|
|
2105
|
-
const simulated = structuredClone(nodes);
|
|
2106
|
-
const simulatedHostEvents = structuredClone(hostEvents);
|
|
2107
|
-
const removeNode = (list, target) => {
|
|
2108
|
-
const index = list.findIndex(node => node.elementId === target);
|
|
2109
|
-
if (index >= 0) {
|
|
2110
|
-
list.splice(index, 1);
|
|
2111
|
-
return true;
|
|
2112
|
-
}
|
|
2113
|
-
for (const node of list) {
|
|
2114
|
-
if (Array.isArray(node.children) && removeNode(node.children, target))
|
|
2115
|
-
return true;
|
|
2116
|
-
}
|
|
2117
|
-
return false;
|
|
2118
|
-
};
|
|
2119
|
-
const eventsOf = (target) => {
|
|
2120
|
-
if (target === 'page')
|
|
2121
|
-
return simulatedHostEvents;
|
|
2122
|
-
const node = findNodeByElementId(simulated, target);
|
|
2123
|
-
if (!node)
|
|
2124
|
-
return undefined;
|
|
2125
|
-
if (!Array.isArray(node.events))
|
|
2126
|
-
node.events = [];
|
|
2127
|
-
return node.events;
|
|
2128
|
-
};
|
|
2129
|
-
const apply = (op) => {
|
|
2130
|
-
if (op.op === 'batch') {
|
|
2131
|
-
for (const inner of asObjects(op.ops))
|
|
2132
|
-
apply(inner);
|
|
2133
|
-
return;
|
|
2134
|
-
}
|
|
2135
|
-
if (op.op === 'add_component' && op.component && typeof op.component === 'object') {
|
|
2136
|
-
simulated.push(structuredClone(op.component));
|
|
2137
|
-
return;
|
|
2138
|
-
}
|
|
2139
|
-
const target = String(op.target ?? '');
|
|
2140
|
-
if (target === '')
|
|
2141
|
-
return;
|
|
2142
|
-
if (op.op === 'remove_component') {
|
|
2143
|
-
removeNode(simulated, target);
|
|
2144
|
-
return;
|
|
2145
|
-
}
|
|
2146
|
-
if (op.op !== 'set_event' && op.op !== 'add_event' && op.op !== 'remove_event')
|
|
2147
|
-
return;
|
|
2148
|
-
const events = eventsOf(target);
|
|
2149
|
-
if (events === undefined)
|
|
2150
|
-
return;
|
|
2151
|
-
const eventName = String(op.event ?? '');
|
|
2152
|
-
const eventValue = typeof op.eventValue === 'string' ? op.eventValue : undefined;
|
|
2153
|
-
const named = events.filter(event => String(event.name ?? '') === eventName && typeof event.value === 'string' && event.value !== '');
|
|
2154
|
-
if (op.op === 'add_event') {
|
|
2155
|
-
if (eventValue !== undefined)
|
|
2156
|
-
events.push({ name: eventName, value: eventValue });
|
|
2157
|
-
return;
|
|
2158
|
-
}
|
|
2159
|
-
if (op.op === 'set_event') {
|
|
2160
|
-
// set_event adın BÜTÜN bağlarını tek kayda indirir.
|
|
2161
|
-
for (const event of named)
|
|
2162
|
-
events.splice(events.indexOf(event), 1);
|
|
2163
|
-
if (eventValue !== undefined)
|
|
2164
|
-
events.push({ name: eventName, value: eventValue });
|
|
2165
|
-
return;
|
|
2166
|
-
}
|
|
2167
|
-
// Değersiz remove_event çoklu bağda platformda ambiguous-event ile düşer: hiçbir bağ kalkmaz.
|
|
2168
|
-
const removed = eventValue === undefined
|
|
2169
|
-
? (named.length === 1 ? named : [])
|
|
2170
|
-
: named.filter(event => event.value === eventValue);
|
|
2171
|
-
for (const event of removed)
|
|
2172
|
-
events.splice(events.indexOf(event), 1);
|
|
2173
|
-
};
|
|
2174
|
-
for (const op of ops)
|
|
2175
|
-
apply(op);
|
|
2176
|
-
const surviving = new Set();
|
|
2177
|
-
for (const event of simulatedHostEvents) {
|
|
2178
|
-
if (typeof event.value === 'string')
|
|
2179
|
-
surviving.add(event.value);
|
|
2180
|
-
}
|
|
2181
|
-
for (const node of simulated) {
|
|
2182
|
-
for (const flowId of collectFlowRefs(node))
|
|
2183
|
-
surviving.add(flowId);
|
|
2184
|
-
}
|
|
2185
|
-
return surviving;
|
|
2186
|
-
}
|
|
2187
2068
|
/**
|
|
2188
2069
|
* Bir yamanın SİLECEĞİ akışlar. Platform referanssız kalan akışı KALICI siler; uyarı yamadan sonra
|
|
2189
2070
|
* geldiğinde "önce yedekle" tavsiyesi uygulanamaz hâle geliyordu (09-05 koşusu: sekiz adımlı giriş
|
|
@@ -2196,11 +2077,38 @@ export function orphanedFlowPlan(schema, pageEvents, ops) {
|
|
|
2196
2077
|
// `remove_component` akışı uyarısız siliyordu).
|
|
2197
2078
|
const opList = asObjects(ops).flatMap(op => op.op === 'batch' ? asObjects(op.ops) : [op]);
|
|
2198
2079
|
const plan = [];
|
|
2199
|
-
//
|
|
2200
|
-
//
|
|
2201
|
-
//
|
|
2202
|
-
|
|
2203
|
-
const
|
|
2080
|
+
// Plan yamanın SON durumuna bakar: aynı yamada başka düğüme ya da eklenen gövdeye bağlanan akış
|
|
2081
|
+
// referanssız değildir (K37-d: bağı `click`'ten `itemPress`'e taşıyan yama reddediliyordu). Aynı
|
|
2082
|
+
// yamada kaldırılan düğüme eklenen bağ sayılmaz.
|
|
2083
|
+
const removedTargets = new Set(opList.filter(op => op.op === 'remove_component').map(op => String(op.target ?? '')));
|
|
2084
|
+
const boundByPatch = new Set();
|
|
2085
|
+
for (const op of opList) {
|
|
2086
|
+
if ((op.op === 'add_event' || op.op === 'set_event') && typeof op.eventValue === 'string' && !removedTargets.has(String(op.target ?? ''))) {
|
|
2087
|
+
boundByPatch.add(op.eventValue);
|
|
2088
|
+
}
|
|
2089
|
+
if (op.op === 'add_component' && op.component && typeof op.component === 'object') {
|
|
2090
|
+
for (const flowId of collectFlowRefs(op.component))
|
|
2091
|
+
boundByPatch.add(flowId);
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
const survivingRefs = (skipElementId, skipEvent) => {
|
|
2095
|
+
const surviving = new Set(boundByPatch);
|
|
2096
|
+
for (const event of asObjects(pageEvents)) {
|
|
2097
|
+
if (typeof event.value === 'string')
|
|
2098
|
+
surviving.add(event.value);
|
|
2099
|
+
}
|
|
2100
|
+
collectFlowRefsExcept(nodes, skipElementId, surviving);
|
|
2101
|
+
if (skipEvent !== undefined) {
|
|
2102
|
+
const node = findNodeByElementId(nodes, skipElementId);
|
|
2103
|
+
for (const event of asObjects(node?.events)) {
|
|
2104
|
+
if (String(event.name ?? '') !== skipEvent && typeof event.value === 'string')
|
|
2105
|
+
surviving.add(event.value);
|
|
2106
|
+
}
|
|
2107
|
+
for (const flowId of collectFlowRefs({ ...(node ?? {}), events: [] }))
|
|
2108
|
+
surviving.add(flowId);
|
|
2109
|
+
}
|
|
2110
|
+
return surviving;
|
|
2111
|
+
};
|
|
2204
2112
|
for (const op of opList) {
|
|
2205
2113
|
const target = String(op.target ?? '');
|
|
2206
2114
|
if (target === '')
|
|
@@ -2210,6 +2118,7 @@ export function orphanedFlowPlan(schema, pageEvents, ops) {
|
|
|
2210
2118
|
if (!doomed)
|
|
2211
2119
|
continue;
|
|
2212
2120
|
const losing = collectFlowRefs(doomed);
|
|
2121
|
+
const surviving = survivingRefs(target);
|
|
2213
2122
|
const orphaned = [...losing].filter(flowId => !surviving.has(flowId));
|
|
2214
2123
|
if (orphaned.length > 0)
|
|
2215
2124
|
plan.push({ target, op: 'remove_component', flowIds: orphaned });
|
|
@@ -2231,7 +2140,10 @@ export function orphanedFlowPlan(schema, pageEvents, ops) {
|
|
|
2231
2140
|
// oraya bağlı akış kapıdan geçip kalıcı silinirdi. Düzey olayı olmayan widget'ta applier da
|
|
2232
2141
|
// düğüm aramasına düşer.
|
|
2233
2142
|
if (op.op === 'remove_event' && target === 'page' && Array.isArray(pageEvents)) {
|
|
2234
|
-
const
|
|
2143
|
+
const hostEvents = asObjects(pageEvents);
|
|
2144
|
+
const removed = removedBy(boundTo(hostEvents));
|
|
2145
|
+
const surviving = new Set([...boundByPatch, ...hostEvents.filter(event => !removed.includes(event) && typeof event.value === 'string').map(event => String(event.value))]);
|
|
2146
|
+
collectFlowRefsExcept(nodes, '', surviving);
|
|
2235
2147
|
const flowIds = [...new Set(removed.map(event => String(event.value)))].filter(flowId => !surviving.has(flowId));
|
|
2236
2148
|
if (flowIds.length > 0)
|
|
2237
2149
|
plan.push({ target, op: 'remove_event', flowIds });
|
|
@@ -2243,6 +2155,11 @@ export function orphanedFlowPlan(schema, pageEvents, ops) {
|
|
|
2243
2155
|
const losing = op.op === 'set_event' ? named.filter(event => event.value !== eventValue) : removedBy(named);
|
|
2244
2156
|
if (losing.length === 0)
|
|
2245
2157
|
continue;
|
|
2158
|
+
const surviving = survivingRefs(target, eventName);
|
|
2159
|
+
for (const event of named) {
|
|
2160
|
+
if (!losing.includes(event))
|
|
2161
|
+
surviving.add(String(event.value));
|
|
2162
|
+
}
|
|
2246
2163
|
const flowIds = [...new Set(losing.map(event => String(event.value)))].filter(flowId => !surviving.has(flowId));
|
|
2247
2164
|
if (flowIds.length > 0)
|
|
2248
2165
|
plan.push({ target, op: String(op.op), flowIds });
|
|
@@ -357,39 +357,3 @@ export function functionOutline(definition) {
|
|
|
357
357
|
view: 'outline'
|
|
358
358
|
};
|
|
359
359
|
}
|
|
360
|
-
export function processOutline(payload) {
|
|
361
|
-
const model = (payload.definition && typeof payload.definition === 'object' ? payload.definition : payload);
|
|
362
|
-
const describeAssignee = (value) => {
|
|
363
|
-
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
364
|
-
return value ?? null;
|
|
365
|
-
const assignee = value;
|
|
366
|
-
const rule = [assignee.rule, assignee.arg].filter(part => part !== undefined && part !== null).join(':');
|
|
367
|
-
return assignee.of ? `${rule} of ${String(assignee.of)}` : rule;
|
|
368
|
-
};
|
|
369
|
-
const describeNodes = (nodes, depth) => asArray(nodes).flatMap(node => [{
|
|
370
|
-
id: node.id,
|
|
371
|
-
type: node.type,
|
|
372
|
-
depth,
|
|
373
|
-
editable: node.editable ?? 'locked',
|
|
374
|
-
description: node.description ?? null,
|
|
375
|
-
assignee: describeAssignee(node.assignee ?? node.to),
|
|
376
|
-
policy: node.policy ?? null,
|
|
377
|
-
sla: Array.isArray(node.sla) ? asArray(node.sla).map(sla => sla.duration) : node.sla ?? null,
|
|
378
|
-
on: asArray(node.on).map(handler => `${String(handler.event)} → ${String(handler.handler?.type ?? '?')}${handler.afterHandlers ? ` (${String(handler.afterHandlers)})` : ''}`)
|
|
379
|
-
}, ...describeNodes(node.nodes, depth + 1)]);
|
|
380
|
-
const nodes = describeNodes(model.nodes, 0);
|
|
381
|
-
return {
|
|
382
|
-
id: payload.id ?? null,
|
|
383
|
-
slug: model.slug ?? payload.slug,
|
|
384
|
-
name: model.name ?? payload.name,
|
|
385
|
-
version: payload.version ?? null,
|
|
386
|
-
activeVersionId: payload.activeVersionId ?? null,
|
|
387
|
-
versions: asArray(payload.versions).map(version => ({ number: version.number, state: version.state })),
|
|
388
|
-
nodeCount: nodes.length,
|
|
389
|
-
nodes,
|
|
390
|
-
edgeCount: asArray(model.edges).length,
|
|
391
|
-
on: asArray(model.on).map(handler => String(handler.event)),
|
|
392
|
-
view: 'outline',
|
|
393
|
-
hint: "Tek düğüm için process_definition_get view:'part', part:'definition.nodes[id=<düğüm>]'; değişiklik için process_definition_patch (yol /nodes[id=<düğüm>]/…)."
|
|
394
|
-
};
|
|
395
|
-
}
|
|
@@ -329,7 +329,7 @@ export function profileFindings(profile, input) {
|
|
|
329
329
|
target: stepIds.join(', '),
|
|
330
330
|
message: type === 'download'
|
|
331
331
|
? "mobil uygulamada 'download' tarayıcı indirmesi yapmaz: adres dönen yanıt Linking.openURL ile açılır, ikili gövde (JSON değil) önbelleğe yazılıp paylaşım sayfasında (expo-sharing) açılır"
|
|
332
|
-
: "mobil uygulamada 'setcookie'
|
|
332
|
+
: "mobil uygulamada 'setcookie' çerez yazmaz, cihaz deposuna (storage, expo-sqlite/kv-store) eşlenir — okuyan ifadeler aynı çalışır"
|
|
333
333
|
});
|
|
334
334
|
}
|
|
335
335
|
return findings;
|
|
@@ -7,7 +7,7 @@ import { MOBILE_DROPPABLE_TYPES } from '../mobileComponentCatalog.js';
|
|
|
7
7
|
*/
|
|
8
8
|
export const RUNTIME_NORMAL_MARGIN = 4;
|
|
9
9
|
export const RUNTIME_NORMAL_PADDING = 10;
|
|
10
|
-
export const FLUSH_SPACING_TYPES = ['safe-area', 'scroll-view', 'app-bar', 'tooltip'];
|
|
10
|
+
export const FLUSH_SPACING_TYPES = ['safe-area', 'scroll-view', 'app-bar', 'tooltip', 'view'];
|
|
11
11
|
export const HIDE_SPACING_TYPES = ['auth-layout', 'modal', 'drawer'];
|
|
12
12
|
export const NO_PADDING_TYPES = ['auth-layout', 'modal', 'drawer'];
|
|
13
13
|
export const SHELL_ROOT_TYPES = ['layout', 'layout-shell'];
|
package/dist/knowledge/policy.js
CHANGED
|
@@ -1,27 +1,13 @@
|
|
|
1
1
|
import { logStep } from '../observability/trace.js';
|
|
2
2
|
export class PolicyBlockError extends Error {
|
|
3
3
|
findings;
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* `canOverride` kaçış cümlesini seçer. Her tool `policyOverride` girdisini
|
|
7
|
-
* TAŞIMAZ (row_*, datasource_*, folder_*, project_*, translation_*,
|
|
8
|
-
* external_component_*): oralarda "aynı çağrıyı policyOverride ile
|
|
9
|
-
* tekrarlayın" demek olmayan bir alana yönlendirmekti ve çağıran aynı
|
|
10
|
-
* isteği ikinci kez gönderip aynı duvara çarpıyordu (S-12, 2026-09-19).
|
|
11
|
-
* Girdiyi taşıyan tool'larda da mutlak kapılar vardır (BPM-001/014/018
|
|
12
|
-
* ortam ve imza kapıları): orada da bu dal seçilir, o yüzden cümle "bu
|
|
13
|
-
* çağrı" der.
|
|
14
|
-
*/
|
|
15
|
-
constructor(findings, canOverride = true) {
|
|
4
|
+
constructor(findings) {
|
|
16
5
|
super([
|
|
17
6
|
'Politika kontrolü isteği durdurdu (istek platforma gönderilmedi):',
|
|
18
7
|
...findings.map(finding => `- [${finding.ruleId}] ${finding.message}${finding.guide ? ` (rehber: ${finding.guide})` : ''}`),
|
|
19
|
-
|
|
20
|
-
? "Bilinçli bir istisnaysa aynı çağrıyı policyOverride: true ile tekrarlayın; kural yanlışsa zeyrek-mcp/docs/08-kural-envanteri.md'ye işleyin."
|
|
21
|
-
: "Bu çağrı policyOverride kabul etmez: çağrıyı kuralı sağlayacak biçimde değiştirin; kural yanlışsa zeyrek-mcp/docs/08-kural-envanteri.md'ye işleyin."
|
|
8
|
+
"Bilinçli bir istisnaysa aynı çağrıyı policyOverride: true ile tekrarlayın; kural yanlışsa zeyrek-mcp/docs/08-kural-envanteri.md'ye işleyin."
|
|
22
9
|
].join('\n'));
|
|
23
10
|
this.findings = findings;
|
|
24
|
-
this.canOverride = canOverride;
|
|
25
11
|
this.name = 'PolicyBlockError';
|
|
26
12
|
}
|
|
27
13
|
}
|
|
@@ -49,11 +35,11 @@ export function evaluatePolicy(config, rules, module, definition, context, polic
|
|
|
49
35
|
logStep('politika', `${module}/${context.operation}${context.workflowKind ? ` (${context.workflowKind})` : ''} · ${applicable.length} kural denendi · ${findings.length === 0 ? 'bulgu yok' : `${findings.length} bulgu`}${policyOverride ? ' · policyOverride açık' : ''}`, findings.map(finding => `[${finding.ruleId}] ${finding.severity}: ${finding.message}`));
|
|
50
36
|
return findings;
|
|
51
37
|
}
|
|
52
|
-
export function enforcePolicy(findings
|
|
38
|
+
export function enforcePolicy(findings) {
|
|
53
39
|
const blocking = findings.filter(finding => finding.severity === 'block');
|
|
54
40
|
if (blocking.length > 0) {
|
|
55
41
|
logStep('politika ✕', `${blocking.length} block bulgusu isteği durdurdu — platforma HİÇBİR istek gitmedi`, blocking.map(finding => `[${finding.ruleId}] ${finding.message}`));
|
|
56
|
-
throw new PolicyBlockError(blocking
|
|
42
|
+
throw new PolicyBlockError(blocking);
|
|
57
43
|
}
|
|
58
44
|
return findings;
|
|
59
45
|
}
|
|
@@ -182,7 +182,7 @@ export const processNodeSchemas = [
|
|
|
182
182
|
{ type: 'start', purpose: 'Sürecin giriş noktası; tanımda üst düzeyde tam bir tane', required: ['id', 'type', 'description'], fields: { ...commonFields, trigger: 'row-event | manual | api | schedule | sub-process | message | signal', entity: 'row-event için entity slug', operation: 'create | update | delete', condition: 'Jint (row, previousRow)' }, example: { id: 'baslangic', type: 'start', description: 'Satır oluşunca başlar.', trigger: 'row-event', entity: 'gorevler', operation: 'create' } },
|
|
183
183
|
{ type: 'user-task', purpose: 'İnsan görevi; kutuya düşer', required: ['id', 'type', 'description', 'assignee'], fields: { ...commonFields, resultKey: 'sonucun adı: motor görev sonucunu { outcome, action, completedBy, payload } olarak vars.tasks.<resultKey> altına yazar (yoksa id snake_case yazılır: ik-kaydi → vars.tasks.ik_kaydi; eski ifadeler için kebab-case id altına da yazılır). Her user-task düğümüne snake_case verin (teslimat_kontrol) — kebab-case/slug değil: tire kabul edilmez, aynı tipte benzersizdir. Geçit vars.tasks.teslimat_kontrol.action === "sorunlu" diye okur; yazılmamış bir ad (vars.tasks.teslimatKontrol) undefined döner', form: '{ dtoId } görev formunun DTO kimliği (dto_list) — { pageId } sayfa formu, { formKey } dış form anahtarı. SLUG KABUL EDİLMEZ: dtoSlug yazmak sessizce düşer (BPM-021)', assignee: 'atama sözlüğü (ör. "subject-field:atanan_id", "role:finans")', mode: 'claim (varsayılan) | individual', join: 'all | any | force-complete (individual)', actions: '[{ id, label, completes, emits, evidence }]', completeOn: '{ trigger: row-event, operation, condition }', sla: '"P2D" ya da [{ name, duration, onBreach }]', requestInfo: 'bool', allowReassign: 'bool', external: 'bool — dış kullanıcı görevi', revisionBound: 'bool — bölge yeniden başlarsa eski görev superseded', undoWindow: 'ISO süre', assessment: '{ questionBank { entity, where, questionField, optionsField, answerField }, count, passScore (1..count, BPM-020), attempts, random, completeAction } — okuma kanıtından önce sınav' }, example: { id: 'gorevi-yap', type: 'user-task', resultKey: 'gorevi_yap', description: 'Atanan görevi yapar.', assignee: 'subject-field:atanan_id', sla: 'P3D' } },
|
|
184
184
|
{ type: 'approval', purpose: 'Onay görevi ve politika kararı', required: ['id', 'type', 'description', 'assignee'], fields: { ...commonFields, resultKey: 'kararın adı: motor sonucu vars.approvals.<resultKey> altına yazar (yoksa id snake_case yazılır: yonetici-onayi → vars.approvals.yonetici_onayi). Her approval düğümüne snake_case verin (yonetici_onayi) — kebab-case/slug değil: tire kabul edilmez, aynı tipte benzersizdir', form: '{ dtoId } görev formunun DTO kimliği (dto_list) — { pageId } sayfa formu, { formKey } dış form anahtarı. SLUG KABUL EDİLMEZ: dtoSlug yazmak sessizce düşer (BPM-021)', assignee: 'atama sözlüğü', policy: 'sequential | all | any | quorum(n) | majority | weighted(0.6)', rejectPolicy: 'any-reject | quorum(n) | majority', onReject: 'end | back-to:<düğüm> | restart', commentRequired: 'bool ya da Jint ("outcome === \'rejected\'")', selfApproval: 'escalate | skip | allow', weights: '{ "role:x": 2 }', veto: '["role:yk-baskani"]', abstain: 'bool', countAs: 'vars yolu' }, example: { id: 'kontrol-onay', type: 'approval', resultKey: 'kontrol_onay', description: 'Birim yöneticisi onaylar.', assignee: 'unit-manager of subject-field:atanan_id', policy: 'any', onReject: 'back-to:iade' } },
|
|
185
|
-
{ type: 'service', purpose: 'Workflow, bağlayıcı, dış motor ya da AI çağrısı (yan etkili iş)', required: ['id', 'type', 'description'], fields: { ...commonFields, workflowId: 'workflow GUID — workflowId | connector | externalEngine | ai alanlarından biri zorunlu
|
|
185
|
+
{ type: 'service', purpose: 'Workflow, bağlayıcı, dış motor ya da AI çağrısı (yan etkili iş)', required: ['id', 'type', 'description'], fields: { ...commonFields, workflowId: 'workflow GUID — workflowId | workflowSlug | connector | externalEngine | ai alanlarından biri zorunlu', connector: '{ name, operation, credentialRef, input }', externalEngine: '{ engine: camunda8 | camunda7 | flowable, processKey, credentialRef, input }', input: '{ ad: "<Jint>" }', output: 'vars yolu ("vars.seviye")', retry: '{ count, backoff, delay }', runAs: 'system ise caution zorunlu (BPM-005)', ai: '{ operation: summarize | classify | extract | suggest-assignee | suggest-decision, labels, schema, files, input, instructions, autonomy: suggest | act-in-adhoc (BPM-019) } — öneri output yoluna yazılır, karar vermez' }, example: { id: 'seviye-hesapla', type: 'service', description: 'Tutardan onay seviyesini hesaplar.', workflowId: '<guid>', input: { tutar: 'row.tutar' }, output: 'vars.seviye' } },
|
|
186
186
|
{ type: 'notify', purpose: 'Bildirim (kutu, e-posta outbox)', required: ['id', 'type', 'description', 'to'], fields: { ...commonFields, to: 'atama sözlüğü', channels: '["inbox", "email"]', template: '{ subject, body } — {{row.x}} yer tutucuları', ackRequired: 'bool' }, example: { id: 'bildir', type: 'notify', description: 'Yöneticiye bildirim.', to: 'unit-manager of subject-field:atanan_id', channels: ['inbox'] } },
|
|
187
187
|
{ type: 'gateway', purpose: 'Dallanma ve birleşme', required: ['id', 'type', 'description', 'kind'], fields: { ...commonFields, kind: 'exclusive | parallel | inclusive (koşulu tutan her dal; birleşmede hâlâ ulaşabilecek dallar beklenir) | event-based (yalnız wait/timer düğümlerine gider; ilk gelen olay kazanır, diğer bekleyişler iptal)', default: 'exclusive/inclusive için hiçbir koşul tutmazsa gidilen hedef' }, example: { id: 'butce-karari', type: 'gateway', kind: 'exclusive', description: 'Bütçe uygun mu?', default: 'reddedildi' } },
|
|
188
188
|
{ type: 'timer', purpose: 'Süre ya da tarih bekleme', required: ['id', 'type', 'description'], fields: { ...commonFields, duration: 'ISO süre', until: 'Jint tarih ifadesi', calendar: 'iş takvimi slug' }, example: { id: 'bekle', type: 'timer', description: 'Bir gün bekler.', duration: 'P1D' } },
|
|
@@ -1,39 +1,17 @@
|
|
|
1
1
|
export const reservedTenantTables = [
|
|
2
|
-
'access_assignments',
|
|
3
|
-
'access_decision_logs',
|
|
4
|
-
'access_grants',
|
|
5
|
-
'access_permissions',
|
|
6
|
-
'access_policies',
|
|
7
|
-
'access_resources',
|
|
8
|
-
'ai_usage',
|
|
9
|
-
'app_refresh_tokens',
|
|
10
2
|
'applications',
|
|
11
|
-
'assignment_pools',
|
|
12
3
|
'audit_trail_values',
|
|
13
4
|
'audit_trails',
|
|
14
|
-
'authority_limits',
|
|
15
5
|
'branches',
|
|
16
|
-
'business_calendars',
|
|
17
6
|
'caches',
|
|
18
|
-
'case_definition_versions',
|
|
19
|
-
'case_definitions',
|
|
20
|
-
'case_instance_events',
|
|
21
|
-
'case_instances',
|
|
22
|
-
'case_plan_items',
|
|
23
|
-
'component_bundle_versions',
|
|
24
7
|
'component_definition_blocks',
|
|
25
8
|
'component_definition_events',
|
|
26
9
|
'component_definition_properties',
|
|
27
10
|
'component_definition_property_options',
|
|
28
11
|
'component_definition_validations',
|
|
29
12
|
'components',
|
|
30
|
-
'connector_credentials',
|
|
31
|
-
'data_job_changes',
|
|
32
|
-
'data_jobs',
|
|
33
13
|
'data_transfer_objects',
|
|
34
14
|
'datasources',
|
|
35
|
-
'decision_versions',
|
|
36
|
-
'decisions',
|
|
37
15
|
'design_component_blocks',
|
|
38
16
|
'design_component_events',
|
|
39
17
|
'design_component_properties',
|
|
@@ -56,15 +34,11 @@ export const reservedTenantTables = [
|
|
|
56
34
|
'folder_middlewares',
|
|
57
35
|
'folder_roles',
|
|
58
36
|
'folders',
|
|
59
|
-
'global_functions',
|
|
60
37
|
'layout_events',
|
|
61
38
|
'layouts',
|
|
62
|
-
'microfunction_runtimes',
|
|
63
|
-
'microfunctions',
|
|
64
39
|
'microservice_middlewares',
|
|
65
40
|
'microservice_roles',
|
|
66
41
|
'microservices',
|
|
67
|
-
'module_installations',
|
|
68
42
|
'ms_source_entities',
|
|
69
43
|
'ms_source_entity_fields',
|
|
70
44
|
'ms_source_entity_filters',
|
|
@@ -72,79 +46,26 @@ export const reservedTenantTables = [
|
|
|
72
46
|
'ms_source_entity_limits',
|
|
73
47
|
'ms_source_entity_sorts',
|
|
74
48
|
'ms_type_options',
|
|
75
|
-
'organization_position_closure',
|
|
76
|
-
'organization_positions',
|
|
77
|
-
'organization_unit_closure',
|
|
78
|
-
'organization_units',
|
|
79
49
|
'page_events',
|
|
80
50
|
'page_middlewares',
|
|
81
51
|
'page_roles',
|
|
82
52
|
'pages',
|
|
83
53
|
'permissions',
|
|
84
|
-
'process_ai_suggestions',
|
|
85
|
-
'process_assessment_attempts',
|
|
86
|
-
'process_batch_operations',
|
|
87
|
-
'process_comments',
|
|
88
|
-
'process_definition_approval_members',
|
|
89
|
-
'process_definition_assignees',
|
|
90
|
-
'process_definition_edges',
|
|
91
|
-
'process_definition_event_handlers',
|
|
92
|
-
'process_definition_expression_references',
|
|
93
|
-
'process_definition_field_usages',
|
|
94
|
-
'process_definition_forms',
|
|
95
|
-
'process_definition_node_actions',
|
|
96
|
-
'process_definition_node_channels',
|
|
97
|
-
'process_definition_node_templates',
|
|
98
|
-
'process_definition_nodes',
|
|
99
|
-
'process_definition_overrides',
|
|
100
|
-
'process_definition_service_inputs',
|
|
101
|
-
'process_definition_sla_breach_actions',
|
|
102
|
-
'process_definition_sla_counters',
|
|
103
|
-
'process_definition_versions',
|
|
104
|
-
'process_definition_write_backs',
|
|
105
|
-
'process_definitions',
|
|
106
|
-
'process_delegations',
|
|
107
|
-
'process_event_sources',
|
|
108
|
-
'process_handovers',
|
|
109
|
-
'process_instance_archives',
|
|
110
|
-
'process_instance_events',
|
|
111
|
-
'process_instances',
|
|
112
|
-
'process_legal_holds',
|
|
113
|
-
'process_mail_sources',
|
|
114
|
-
'process_message_buffer',
|
|
115
|
-
'process_model_comments',
|
|
116
|
-
'process_notification_preferences',
|
|
117
|
-
'process_notifications',
|
|
118
|
-
'process_processed_events',
|
|
119
|
-
'process_publish_requests',
|
|
120
|
-
'process_signatures',
|
|
121
|
-
'process_task_action_tokens',
|
|
122
|
-
'process_task_candidates',
|
|
123
|
-
'process_tasks',
|
|
124
|
-
'process_test_scenarios',
|
|
125
|
-
'process_timers',
|
|
126
|
-
'process_watchers',
|
|
127
|
-
'process_webhook_subscriptions',
|
|
128
54
|
'projects',
|
|
129
55
|
'queries',
|
|
130
|
-
'queued_event_receipts',
|
|
131
56
|
'queued_events',
|
|
132
57
|
'role_permissions',
|
|
133
58
|
'roles',
|
|
134
59
|
'step_rule_condition_rules',
|
|
135
60
|
'step_rules',
|
|
136
61
|
'steps',
|
|
137
|
-
'translations',
|
|
138
62
|
'ui_flow_step_argument_iterates',
|
|
139
63
|
'ui_flow_step_argument_parameters',
|
|
140
64
|
'ui_flow_step_argument_rules',
|
|
141
65
|
'ui_flow_step_arguments',
|
|
142
66
|
'ui_flow_step_branches',
|
|
143
67
|
'ui_flow_steps',
|
|
144
|
-
'user_capacities',
|
|
145
|
-
'user_positions',
|
|
146
68
|
'user_roles',
|
|
147
|
-
'user_skills',
|
|
148
69
|
'users',
|
|
149
70
|
'variables',
|
|
150
71
|
'view_fields',
|