@appaflytech/zeyrek-ai-mcp 0.0.35 → 0.0.37
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 +15 -0
- package/README.md +5 -5
- package/dist/config.js +37 -0
- package/dist/index.js +2 -0
- package/dist/knowledge/access.js +802 -0
- package/dist/knowledge/backendConstraints.js +18 -1
- package/dist/knowledge/case.js +41 -0
- package/dist/knowledge/componentCatalog.js +655 -424
- package/dist/knowledge/componentEvents.js +140 -23
- package/dist/knowledge/connectDataBind.js +843 -0
- package/dist/knowledge/connectDataDefinition.js +344 -0
- package/dist/knowledge/connectDataExecute.js +93 -0
- package/dist/knowledge/connectDataRules.js +128 -0
- package/dist/knowledge/decision.js +121 -0
- package/dist/knowledge/expressionPrelude.js +59 -0
- package/dist/knowledge/layoutSummary.js +140 -2
- package/dist/knowledge/microserviceParameters.js +58 -0
- package/dist/knowledge/mining.js +94 -0
- package/dist/knowledge/mobileComponentCatalog.js +864 -0
- package/dist/knowledge/mobileComponentEvents.js +239 -0
- package/dist/knowledge/mobileStore.js +321 -0
- package/dist/knowledge/normalize.js +235 -84
- package/dist/knowledge/outlines.js +36 -0
- package/dist/knowledge/platform/lint.js +385 -0
- package/dist/knowledge/platform/mobile.js +142 -0
- package/dist/knowledge/platform/mobileLayoutLint.js +324 -0
- package/dist/knowledge/platform/mobileRules.js +231 -0
- package/dist/knowledge/platform/mobileSpacing.js +82 -0
- package/dist/knowledge/platform/mobileTabs.js +108 -0
- package/dist/knowledge/platform/nativeBoxModel.js +44 -0
- package/dist/knowledge/platform/profile.js +25 -0
- package/dist/knowledge/platform/resolve.js +122 -0
- package/dist/knowledge/platform/web.js +39 -0
- package/dist/knowledge/policy.js +18 -4
- package/dist/knowledge/process.js +510 -0
- package/dist/knowledge/reservedTables.js +79 -0
- package/dist/knowledge/rowFilter.js +43 -0
- package/dist/knowledge/rules.js +423 -37
- package/dist/knowledge/schemaGuard.js +11 -0
- package/dist/knowledge/styleResolve.js +53 -19
- package/dist/knowledge/styleResolveNative.js +527 -0
- package/dist/knowledge/themeResolve.js +4 -4
- package/dist/knowledge/themeSchema.js +1 -2
- package/dist/observability/trace.js +6 -3
- package/dist/platform/argumentAliases.js +128 -0
- package/dist/platform/bodyFile.js +103 -0
- package/dist/platform/capture/actions.js +398 -0
- package/dist/platform/capture/browser.js +1 -0
- package/dist/platform/capture/capture.js +683 -0
- package/dist/platform/capture/console-log.js +122 -0
- package/dist/platform/capture/index.js +11 -0
- package/dist/platform/capture/readiness.js +103 -0
- package/dist/platform/capture/summary.js +77 -0
- package/dist/platform/capture/target.js +5 -0
- package/dist/platform/capture/targets/studio-mobile.js +15 -0
- package/dist/platform/capture/targets/studio-web.js +5 -0
- package/dist/platform/diagnostics.js +10 -4
- package/dist/platform/domSummary.js +1 -1
- package/dist/platform/errors.js +163 -10
- package/dist/platform/http.js +29 -8
- package/dist/platform/impersonation.js +45 -0
- package/dist/platform/jsonArray.js +24 -0
- package/dist/platform/responses.js +39 -5
- package/dist/platform/schemaReadMemory.js +60 -0
- package/dist/platform/secrets.js +19 -1
- package/dist/platform/strictArguments.js +68 -12
- package/dist/platform/tokenVault.js +187 -4
- package/dist/resources/examples/bpm-gorev-kontrol.json +294 -0
- package/dist/resources/examples/bpm-iso-dokuman.json +228 -0
- package/dist/resources/examples/bpm-satinalma.json +376 -0
- package/dist/resources/examples/connect-data-convert-verify.json +107 -0
- package/dist/resources/examples/connect-data-dropdown-roles.json +66 -0
- package/dist/resources/examples/connect-data-edit-m2m.json +73 -0
- package/dist/resources/examples/connect-data-query-params.json +50 -0
- package/dist/resources/examples/connect-data-table-entity.json +147 -0
- package/dist/resources/examples/connect-data-workflow-microservice.json +65 -0
- package/dist/resources/examples/middleware-authenticate.json +1 -1
- package/dist/resources/examples/mobile-app-shell-drawer.json +244 -0
- package/dist/resources/examples/mobile-app-shell-stack.json +157 -0
- package/dist/resources/examples/mobile-app-shell-tab.json +208 -0
- package/dist/resources/examples/mobile-form-screen.json +365 -0
- package/dist/resources/examples/mobile-list-detail-form.json +703 -0
- package/dist/resources/examples/page-detail-profile.json +2 -1
- package/dist/resources/examples/page-dynamic-form.json +3 -2
- package/dist/resources/examples/page-flex-sections.json +1 -1
- package/dist/resources/examples/page-html-embed.json +1 -1
- package/dist/resources/examples/workflow-basic.json +8 -2
- package/dist/resources/guides/access.md +810 -0
- package/dist/resources/guides/bpm.md +691 -0
- package/dist/resources/guides/case.md +153 -0
- package/dist/resources/guides/component.md +93 -6
- package/dist/resources/guides/decision.md +185 -0
- package/dist/resources/guides/entity.md +50 -8
- package/dist/resources/guides/expressions.md +14 -5
- package/dist/resources/guides/functions.md +1 -1
- package/dist/resources/guides/getting-started.md +38 -1
- package/dist/resources/guides/layout.md +11 -7
- package/dist/resources/guides/merge.md +37 -3
- package/dist/resources/guides/microservice.md +87 -2
- package/dist/resources/guides/middleware.md +68 -4
- package/dist/resources/guides/mobile-layout.md +193 -0
- package/dist/resources/guides/mobile-publish.md +124 -0
- package/dist/resources/guides/mobile.md +549 -0
- package/dist/resources/guides/page.md +463 -83
- package/dist/resources/guides/theme.md +8 -3
- package/dist/resources/guides/translation.md +1 -1
- package/dist/resources/guides/workflow.md +58 -1
- package/dist/resources/read.js +41 -0
- package/dist/resources/rules.js +11 -5
- package/dist/resources/schema-fingerprint.json +7 -5
- package/dist/resources/schemas/AccessExplanationDto.json +144 -0
- package/dist/resources/schemas/AccessMatrixDto.json +170 -0
- package/dist/resources/schemas/AccessPermissionDto.json +57 -0
- package/dist/resources/schemas/AccessPolicyDto.json +223 -0
- package/dist/resources/schemas/AccessResourceDto.json +86 -0
- package/dist/resources/schemas/AppSessionDto.json +53 -0
- package/dist/resources/schemas/ConnectDataDescribeDto.json +344 -0
- package/dist/resources/schemas/ConnectDataRequestModel.json +202 -0
- package/dist/resources/schemas/ConnectDataResultDto.json +421 -0
- package/dist/resources/schemas/ConnectorCredentialDto.json +70 -0
- package/dist/resources/schemas/ConvertConnectDataToMicroserviceCommand.json +37 -0
- package/dist/resources/schemas/CreateAccessPolicyCommand.json +209 -0
- package/dist/resources/schemas/CreateDecisionCommand.json +221 -0
- package/dist/resources/schemas/CreateEntityCommand.json +118 -0
- package/dist/resources/schemas/CreateMicroserviceCommand.json +13 -1
- package/dist/resources/schemas/CreateProcessDefinitionCommand.json +1337 -0
- package/dist/resources/schemas/CreateQueryCommand.json +4 -0
- package/dist/resources/schemas/CreateWorkflowCommand.json +146 -1
- package/dist/resources/schemas/DataJobDto.json +6 -1
- package/dist/resources/schemas/DecisionDto.json +302 -0
- package/dist/resources/schemas/DetachConnectDataMicroserviceCommand.json +28 -0
- package/dist/resources/schemas/ExplainAccessQuery.json +33 -0
- package/dist/resources/schemas/GenerateProcessDocumentCommand.json +116 -0
- package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +25 -1
- package/dist/resources/schemas/MicroserviceDto.json +15 -3
- package/dist/resources/schemas/OrganizationProjectDto.json +335 -0
- package/dist/resources/schemas/OrganizationSchemaDto.json +196 -0
- package/dist/resources/schemas/OrganizationSchemaVersionDto.json +207 -0
- package/dist/resources/schemas/PatchProcessDefinitionCommand.json +76 -0
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +10 -1
- package/dist/resources/schemas/PreviewWorkflowCommand.json +25 -1
- package/dist/resources/schemas/ProcessDefinitionDto.json +1480 -0
- package/dist/resources/schemas/ProcessSimulationDto.json +96 -0
- package/dist/resources/schemas/SaveConnectorCredentialCommand.json +90 -0
- package/dist/resources/schemas/SaveProcessEventSourceCommand.json +61 -0
- package/dist/resources/schemas/SaveProcessMailSourceCommand.json +89 -0
- package/dist/resources/schemas/SignProcessTaskCommand.json +73 -0
- package/dist/resources/schemas/SimulateProcessDefinitionQuery.json +92 -0
- package/dist/resources/schemas/StartMobileBuildCommand.json +54 -0
- package/dist/resources/schemas/StepDto.json +25 -1
- package/dist/resources/schemas/UpdateAccessPolicyCommand.json +209 -0
- package/dist/resources/schemas/UpdateDecisionCommand.json +216 -0
- package/dist/resources/schemas/UpdateEntityCommand.json +118 -0
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +13 -1
- package/dist/resources/schemas/UpdateProcessDefinitionCommand.json +1357 -0
- package/dist/resources/schemas/UpdateQueryCommand.json +4 -0
- package/dist/resources/schemas/UpdateViewCommand.json +0 -2
- package/dist/resources/schemas/UpdateWorkflowCommand.json +146 -1
- package/dist/resources/schemas/UpsertMobileStoreSettingsCommand.json +274 -0
- package/dist/resources/schemas/ValidateProcessDefinitionQuery.json +1339 -0
- package/dist/server.js +31 -1
- package/dist/tools/access.js +369 -2
- package/dist/tools/accessOperations.js +135 -0
- package/dist/tools/accessPolicies.js +170 -0
- package/dist/tools/accessRuntime.js +203 -0
- package/dist/tools/applications.js +60 -3
- package/dist/tools/bpm.js +343 -0
- package/dist/tools/bpmGovernance.js +266 -0
- package/dist/tools/bpmOperations.js +230 -0
- package/dist/tools/bpmReporting.js +154 -0
- package/dist/tools/bpmRouting.js +150 -0
- package/dist/tools/bpmRuntime.js +396 -0
- package/dist/tools/case.js +178 -0
- package/dist/tools/caseRuntime.js +89 -0
- package/dist/tools/common.js +10 -1
- package/dist/tools/components.js +118 -14
- package/dist/tools/connectData.js +450 -0
- package/dist/tools/connectors.js +193 -0
- package/dist/tools/datasources.js +3 -3
- package/dist/tools/decisions.js +206 -0
- package/dist/tools/dependencies.js +1 -1
- package/dist/tools/deployments.js +38 -3
- package/dist/tools/designSchemaPatch.js +34 -9
- package/dist/tools/dtos.js +36 -5
- package/dist/tools/entities.js +79 -12
- package/dist/tools/externalComponents.js +26 -5
- package/dist/tools/flows.js +119 -17
- package/dist/tools/folders.js +1 -1
- package/dist/tools/imports.js +5 -2
- package/dist/tools/layouts.js +50 -17
- package/dist/tools/merges.js +2 -2
- package/dist/tools/microservices.js +77 -25
- package/dist/tools/mobile.js +280 -0
- package/dist/tools/mobileStore.js +556 -0
- package/dist/tools/modules.js +48 -0
- package/dist/tools/organizationStructure.js +137 -0
- package/dist/tools/pages.js +465 -98
- package/dist/tools/platformInfo.js +28 -8
- package/dist/tools/profileWrite.js +92 -0
- package/dist/tools/projects.js +71 -9
- package/dist/tools/rows.js +69 -13
- package/dist/tools/schemaOps.js +61 -1
- package/dist/tools/screenWrite.js +36 -7
- package/dist/tools/screens.js +95 -5
- package/dist/tools/templates.js +26 -1
- package/dist/tools/translations.js +1 -1
- package/dist/tools/variables.js +11 -5
- package/dist/tools/workflows.js +10 -5
- package/package.json +2 -2
- package/dist/platform/screenshot.js +0 -1162
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export const MAX_MOBILE_TABS = 5;
|
|
2
|
+
const STYLES = new Set(['default', 'floating', 'custom']);
|
|
3
|
+
function record(value) {
|
|
4
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
|
|
5
|
+
}
|
|
6
|
+
function text(value) {
|
|
7
|
+
return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;
|
|
8
|
+
}
|
|
9
|
+
/** Öğenin sayfa id'si: `{ page }` ya da düz metin (`items: ['id']`). */
|
|
10
|
+
function entryPage(entry) {
|
|
11
|
+
const item = record(entry);
|
|
12
|
+
return item ? text(item.page) : text(entry);
|
|
13
|
+
}
|
|
14
|
+
/** `Application.properties.mobile.tabs` — ham değer, doğrulanmamış. */
|
|
15
|
+
export function readMobileTabs(properties) {
|
|
16
|
+
return record(record(properties)?.mobile)?.tabs;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Ham sekme ayarını çizilebilir biçime getirir; çizilecek çubuk yoksa `null` (yığın).
|
|
20
|
+
*
|
|
21
|
+
* - Nesne değilse, `enabled !== true` ise ya da geçerli öğe kalmadıysa → `null`.
|
|
22
|
+
* - `style` bilinmiyorsa `default`; `showLabels` boolean değilse `true`.
|
|
23
|
+
* - Öğe `{ page }` ya da düz sayfa id'sidir; sayfası yoksa düşer; `pages` verildiyse orada olmayan
|
|
24
|
+
* sayfa düşer; tekrar eden sayfa (ilki kalır) atılır; `MAX_MOBILE_TABS`'tan sonrası kırpılır.
|
|
25
|
+
* `label`/`icon` boş metinse yazılmaz.
|
|
26
|
+
* - Görünüm alanı yoktur: çubuk temadan çizilir; eski kayıtların `appearance`'ı okunmaz.
|
|
27
|
+
* - `customWidgetId` yalnız `custom` türde ve metinse yazılır.
|
|
28
|
+
*/
|
|
29
|
+
export function normalizeMobileTabs(tabs, pages) {
|
|
30
|
+
const source = record(tabs);
|
|
31
|
+
if (!source || source.enabled !== true)
|
|
32
|
+
return null;
|
|
33
|
+
const known = pages ? new Set(pages.map(page => page.id)) : undefined;
|
|
34
|
+
const seen = new Set();
|
|
35
|
+
const items = [];
|
|
36
|
+
for (const entry of Array.isArray(source.items) ? source.items : []) {
|
|
37
|
+
const item = record(entry);
|
|
38
|
+
const page = entryPage(entry);
|
|
39
|
+
if (!page || seen.has(page) || (known && !known.has(page)))
|
|
40
|
+
continue;
|
|
41
|
+
seen.add(page);
|
|
42
|
+
const label = text(item?.label);
|
|
43
|
+
const icon = text(item?.icon);
|
|
44
|
+
items.push({ page, ...(label ? { label } : {}), ...(icon ? { icon } : {}) });
|
|
45
|
+
if (items.length === MAX_MOBILE_TABS)
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
if (items.length === 0)
|
|
49
|
+
return null;
|
|
50
|
+
const style = (typeof source.style === 'string' && STYLES.has(source.style) ? source.style : 'default');
|
|
51
|
+
const customWidgetId = style === 'custom' ? text(source.customWidgetId) : undefined;
|
|
52
|
+
return {
|
|
53
|
+
enabled: true,
|
|
54
|
+
style,
|
|
55
|
+
items,
|
|
56
|
+
...(customWidgetId ? { customWidgetId } : {}),
|
|
57
|
+
showLabels: typeof source.showLabels === 'boolean' ? source.showLabels : true
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* MOB-007 denetimi: ham ayarın normalizasyonda neyi kaybedeceğini ve tutarsızlıklarını söyler.
|
|
62
|
+
* Yazım yine platforma gider (D3); bulgular yalnız uyarıdır.
|
|
63
|
+
*/
|
|
64
|
+
export function mobileTabsProblems(tabs, context = {}) {
|
|
65
|
+
if (tabs === undefined || tabs === null)
|
|
66
|
+
return [];
|
|
67
|
+
const source = record(tabs);
|
|
68
|
+
if (!source)
|
|
69
|
+
return [`properties.mobile.tabs nesne olmalı (gelen: ${Array.isArray(tabs) ? 'dizi' : typeof tabs}) — sekme çubuğu çizilmez, uygulama yığınla açılır`];
|
|
70
|
+
const problems = [];
|
|
71
|
+
const rawItems = Array.isArray(source.items) ? source.items : undefined;
|
|
72
|
+
if (source.enabled !== undefined && typeof source.enabled !== 'boolean')
|
|
73
|
+
problems.push(`enabled boolean olmalı (gelen: ${JSON.stringify(source.enabled)}) — true olmayan her değer sekmeleri kapatır`);
|
|
74
|
+
if (source.style !== undefined && !(typeof source.style === 'string' && STYLES.has(source.style)))
|
|
75
|
+
problems.push(`style '${String(source.style)}' tanınmıyor (default | floating | custom) — 'default' çizilir`);
|
|
76
|
+
if (source.items !== undefined && !rawItems)
|
|
77
|
+
problems.push('items dizi olmalı — hiçbir sekme çizilmez');
|
|
78
|
+
const items = rawItems ?? [];
|
|
79
|
+
const pageIds = items.map(entryPage);
|
|
80
|
+
if (source.enabled === true && items.length === 0)
|
|
81
|
+
problems.push("enabled:true ama items boş — çubuk çizilmez; en az bir sayfa ekleyin ya da enabled:false yazın");
|
|
82
|
+
if (items.length > MAX_MOBILE_TABS)
|
|
83
|
+
problems.push(`${items.length} sekme var, en çok ${MAX_MOBILE_TABS} çizilir — fazlası kırpılır (${pageIds.slice(MAX_MOBILE_TABS).filter(Boolean).join(', ')})`);
|
|
84
|
+
const missingPage = pageIds.filter(id => !id).length;
|
|
85
|
+
if (missingPage > 0)
|
|
86
|
+
problems.push(`${missingPage} öğede page (sayfa id'si) yok — o öğeler düşer`);
|
|
87
|
+
const duplicates = pageIds.filter((id, index) => id && pageIds.indexOf(id) !== index);
|
|
88
|
+
if (duplicates.length > 0)
|
|
89
|
+
problems.push(`aynı sayfa birden çok sekmede: ${[...new Set(duplicates)].join(', ')} — tekrarlar atılır`);
|
|
90
|
+
if (context.pages) {
|
|
91
|
+
const known = new Set(context.pages.map(page => page.id));
|
|
92
|
+
const unknown = pageIds.filter((id) => Boolean(id) && !known.has(id));
|
|
93
|
+
if (unknown.length > 0)
|
|
94
|
+
problems.push(`var olmayan sayfa: ${[...new Set(unknown)].join(', ')} — page_list ile id'leri doğrulayın; bu öğeler düşer (item.page slug değil sayfa id'sidir)`);
|
|
95
|
+
}
|
|
96
|
+
const normalized = normalizeMobileTabs(tabs, context.pages ?? null);
|
|
97
|
+
if (normalized && context.homepageId && normalized.items[0]?.page !== context.homepageId) {
|
|
98
|
+
problems.push(`açılış sayfası (${context.homepageId}) ilk sekme değil — uygulama açılış sayfasıyla başlar ama çubukta başka sekme seçili görünür; açılış sayfasını items'ın başına alın`);
|
|
99
|
+
}
|
|
100
|
+
if (normalized?.style === 'custom') {
|
|
101
|
+
const widgetId = normalized.customWidgetId;
|
|
102
|
+
if (!widgetId)
|
|
103
|
+
problems.push("style:'custom' ama customWidgetId yok — özel sekme çubuğu widget'ı seçilmeli (component_list kind:'widget')");
|
|
104
|
+
else if (context.widgetIds && !context.widgetIds.has(widgetId))
|
|
105
|
+
problems.push(`customWidgetId '${widgetId}' bu mobil uygulamanın widget'ı değil — çubuk yerine uyarı çizilir`);
|
|
106
|
+
}
|
|
107
|
+
return problems;
|
|
108
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { MOBILE_DROPPABLE_TYPES } from '../mobileComponentCatalog.js';
|
|
2
|
+
/**
|
|
3
|
+
* Mobil runtime'ın kutu modelinin aynası (MOB-019): bir düğümün sol dış boşluğu ve çocuklarını içeri iten sol
|
|
4
|
+
* iç boşluğu. Kaynak `@ng-apps/screen-builder` `spacing.ts` (`resolveSpacing`, sabitler, `HIDE_SPACING_TYPES`),
|
|
5
|
+
* `constants.ts` (`NO_PADDING_TYPES`) ve `ng-apps-ui-native` `renderer.functions.ts` (`nodeSpacingStyle`,
|
|
6
|
+
* `FLUSH_SPACING_TYPES`). Ayna bayatlarsa `test/native-inset-parity.test.ts` kırmızıya düşer.
|
|
7
|
+
*/
|
|
8
|
+
export const RUNTIME_NORMAL_MARGIN = 4;
|
|
9
|
+
export const RUNTIME_NORMAL_PADDING = 10;
|
|
10
|
+
export const FLUSH_SPACING_TYPES = ['safe-area', 'scroll-view', 'app-bar', 'tooltip', 'view'];
|
|
11
|
+
export const HIDE_SPACING_TYPES = ['auth-layout', 'modal', 'drawer'];
|
|
12
|
+
export const NO_PADDING_TYPES = ['auth-layout', 'modal', 'drawer'];
|
|
13
|
+
export const SHELL_ROOT_TYPES = ['layout', 'layout-shell'];
|
|
14
|
+
/** `widthType` yazılmasa da tam genişlik çizilen tipler (`renderer.functions.ts` `FULL_WIDTH_TYPES`, MOB-020). */
|
|
15
|
+
export const FULL_WIDTH_TYPES = ['app-bar'];
|
|
16
|
+
/** Düğümün sol dış boşluğu (dp). `isWrapper`, katmanlar ve kabuk kökü dış boşluk almaz. */
|
|
17
|
+
export function nativeMarginLeft(node) {
|
|
18
|
+
const states = (node.states ?? {});
|
|
19
|
+
const type = String(node.type ?? '');
|
|
20
|
+
if (states.isWrapper || HIDE_SPACING_TYPES.includes(type) || states.isShell || SHELL_ROOT_TYPES.includes(type))
|
|
21
|
+
return 0;
|
|
22
|
+
return sideValue(node.appearance, 'margin', FLUSH_SPACING_TYPES.includes(type), RUNTIME_NORMAL_MARGIN);
|
|
23
|
+
}
|
|
24
|
+
/** Bırakılabilir düğümün çocuklarına verdiği sol iç boşluk (dp); `isWrapper` bunu SIFIRLAMAZ (01'de ölçüldü). */
|
|
25
|
+
export function nativePaddingLeft(node) {
|
|
26
|
+
const states = (node.states ?? {});
|
|
27
|
+
const type = String(node.type ?? '');
|
|
28
|
+
const droppable = states.isDroppable ?? MOBILE_DROPPABLE_TYPES.includes(type);
|
|
29
|
+
if (!droppable || NO_PADDING_TYPES.includes(type) || states.isShell || SHELL_ROOT_TYPES.includes(type))
|
|
30
|
+
return 0;
|
|
31
|
+
return sideValue(node.appearance, 'padding', FLUSH_SPACING_TYPES.includes(type), RUNTIME_NORMAL_PADDING);
|
|
32
|
+
}
|
|
33
|
+
/** `resolveSpacing`: tip yoksa (ya da boşsa) `normal`; `custom` kenar değerini, yoksa tek değeri okur. */
|
|
34
|
+
function sideValue(appearance, layer, flush, normal) {
|
|
35
|
+
const written = appearance?.[`${layer}Type`];
|
|
36
|
+
const type = typeof written === 'string' && written !== '' ? written : flush ? 'none' : 'normal';
|
|
37
|
+
if (type === 'normal')
|
|
38
|
+
return normal;
|
|
39
|
+
if (type !== 'custom')
|
|
40
|
+
return 0;
|
|
41
|
+
const values = appearance?.[`${layer}Values`];
|
|
42
|
+
const left = Number(values?.left ?? appearance?.[`${layer}Value`] ?? 0);
|
|
43
|
+
return Number.isFinite(left) ? left : 0;
|
|
44
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Değişken kaydının `storage` alanının alabildiği değerler (`docs/adr/0004-state-saklama-turu.md`):
|
|
3
|
+
* `device` cihaz deposu, `secure` güvenli depo. Alanın yokluğu bellektir — `memory` kayda yazılmaz.
|
|
4
|
+
*/
|
|
5
|
+
export const STATE_STORAGE_KINDS = ['device', 'secure'];
|
|
6
|
+
/**
|
|
7
|
+
* Motorun kendi register ettiği adımlar (`@ng-apps/flow` `flow-engine.ts` initialize) — iki
|
|
8
|
+
* platformda da koşar. `end` ve `query` hiçbir barındırıcıda yoktur (normalizasyon `end`'i atar).
|
|
9
|
+
*/
|
|
10
|
+
export const ENGINE_STEP_TYPES = ['start', 'setter', 'code', 'condition', 'microservice', 'validation', 'flow-trigger', 'function'];
|
|
11
|
+
/**
|
|
12
|
+
* Eski adım tipi → koşan karşılığı. `navigate` ile `redirect`'in argümanı aynıdır; web `navigate`'i
|
|
13
|
+
* register etmez, yeni mobil runtime onu `redirect` takma adı olarak kaydeder — iki platformda da
|
|
14
|
+
* `redirect` kesin üstündür.
|
|
15
|
+
*/
|
|
16
|
+
export const STEP_ALIASES = Object.freeze({ navigate: 'redirect' });
|
|
17
|
+
/** Tipli stil grupları iki platformda da çizilir (web CSS'e, mobil RN stiline derler). */
|
|
18
|
+
export const TYPED_STYLE_GROUPS = ['surfaceStyle', 'typographyStyle', 'sectionStyle', 'headerStyle', 'valueStyle'];
|
|
19
|
+
/** Bulguyu mevcut `layoutWarnings[]` satır biçimine çevirir (`PAGE-010 (uyarı) — …` kalıbı). */
|
|
20
|
+
export function findingLine(finding) {
|
|
21
|
+
const level = finding.severity === 'info' ? 'bilgi' : 'uyarı';
|
|
22
|
+
const target = finding.target ? ` [${finding.target}]` : '';
|
|
23
|
+
const guide = finding.guide ? ` (${finding.guide})` : '';
|
|
24
|
+
return `${finding.code} (${level})${target} — ${finding.message}${guide}`;
|
|
25
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { mobileProfile } from './mobile.js';
|
|
2
|
+
import { webProfile } from './web.js';
|
|
3
|
+
export const APPLICATION_TYPE_TTL_MS = 10 * 60_000;
|
|
4
|
+
const caches = new WeakMap();
|
|
5
|
+
function cacheOf(platform) {
|
|
6
|
+
let cache = caches.get(platform);
|
|
7
|
+
if (!cache) {
|
|
8
|
+
cache = new Map();
|
|
9
|
+
caches.set(platform, cache);
|
|
10
|
+
}
|
|
11
|
+
return cache;
|
|
12
|
+
}
|
|
13
|
+
/** Backend `ApplicationType` JSON'da açıklama metniyle ('web' | 'mobile') döner; eski sayısal biçim de okunur. */
|
|
14
|
+
export function readApplicationPlatform(value) {
|
|
15
|
+
if (value === 1 || (typeof value === 'string' && value.toLowerCase() === 'mobile'))
|
|
16
|
+
return 'mobile';
|
|
17
|
+
if (value === 0 || (typeof value === 'string' && value.toLowerCase() === 'web'))
|
|
18
|
+
return 'web';
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
export function profileFor(platform) {
|
|
22
|
+
return platform === 'mobile' ? mobileProfile : webProfile;
|
|
23
|
+
}
|
|
24
|
+
function factsOf(record) {
|
|
25
|
+
const platform = readApplicationPlatform(record.type);
|
|
26
|
+
const id = typeof record.id === 'string' ? record.id : undefined;
|
|
27
|
+
if (!platform || !id)
|
|
28
|
+
return undefined;
|
|
29
|
+
const homepage = record.homepage && typeof record.homepage === 'object' ? record.homepage.id : undefined;
|
|
30
|
+
const homepageId = typeof record.homepageId === 'string' ? record.homepageId : typeof homepage === 'string' ? homepage : undefined;
|
|
31
|
+
const properties = record.properties && typeof record.properties === 'object' && !Array.isArray(record.properties)
|
|
32
|
+
? record.properties
|
|
33
|
+
: undefined;
|
|
34
|
+
return {
|
|
35
|
+
id,
|
|
36
|
+
platform,
|
|
37
|
+
...(typeof record.slug === 'string' ? { slug: record.slug } : {}),
|
|
38
|
+
...(typeof record.name === 'string' ? { name: record.name } : {}),
|
|
39
|
+
...(typeof record.projectSlug === 'string' ? { projectSlug: record.projectSlug } : {}),
|
|
40
|
+
...(homepageId ? { homepageId } : {}),
|
|
41
|
+
...(properties ? { properties } : {})
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function fresh(entry) {
|
|
45
|
+
return entry !== undefined && Date.now() - entry.at < APPLICATION_TYPE_TTL_MS;
|
|
46
|
+
}
|
|
47
|
+
export async function resolveApplication(platform, applicationId) {
|
|
48
|
+
const cache = cacheOf(platform);
|
|
49
|
+
const cached = cache.get(applicationId);
|
|
50
|
+
if (fresh(cached))
|
|
51
|
+
return cached.facts;
|
|
52
|
+
try {
|
|
53
|
+
const payload = await platform.org('GET', `/applications/${applicationId}`);
|
|
54
|
+
const facts = factsOf(((payload?.data ?? payload) ?? {}));
|
|
55
|
+
if (facts)
|
|
56
|
+
cache.set(applicationId, { facts, at: Date.now() });
|
|
57
|
+
return facts;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export async function resolveProfile(platform, applicationId) {
|
|
64
|
+
const application = await resolveApplication(platform, applicationId);
|
|
65
|
+
return application
|
|
66
|
+
? { profile: profileFor(application.platform), known: true, application }
|
|
67
|
+
: { profile: webProfile, known: false };
|
|
68
|
+
}
|
|
69
|
+
const SLUG_LOOKUP_PAGE = 50;
|
|
70
|
+
/**
|
|
71
|
+
* `page_screenshot` ve `page_runtime_get` uygulamayı slug ile tanır. Org listesi `searchTerm` ile
|
|
72
|
+
* daraltılır ve slug + proje slug'ı BİREBİR eşleşen kayıt alınır (arama ILIKE'tır, `shop` `shop-2`'yi
|
|
73
|
+
* de getirir). B1'den beri liste tip filtresi verilmeyince iki tipi de döner. Aynı slug'ı çok proje
|
|
74
|
+
* kullanıyorsa (`mobile`, `admin`) aranan kayıt ilk sayfanın dışında kalabilir: sayfa doluysa ve
|
|
75
|
+
* eşleşme yoksa arama proje kimliğiyle tekrarlanır — (proje, slug) tekildir.
|
|
76
|
+
*/
|
|
77
|
+
export async function resolveProfileBySlug(platform, projectSlug, applicationSlug) {
|
|
78
|
+
const cache = cacheOf(platform);
|
|
79
|
+
const key = `slug:${projectSlug}/${applicationSlug}`;
|
|
80
|
+
const cached = cache.get(key);
|
|
81
|
+
if (fresh(cached))
|
|
82
|
+
return { profile: profileFor(cached.facts.platform), known: true, application: cached.facts };
|
|
83
|
+
try {
|
|
84
|
+
const search = async (query) => {
|
|
85
|
+
const payload = await platform.org('GET', '/applications', { query: { searchTerm: applicationSlug, pageLength: SLUG_LOOKUP_PAGE, ...query } });
|
|
86
|
+
return Array.isArray(payload?.data) ? payload.data : [];
|
|
87
|
+
};
|
|
88
|
+
const matchIn = (rows) => rows.find(row => row.slug === applicationSlug && (row.projectSlug === undefined || row.projectSlug === projectSlug));
|
|
89
|
+
const rows = await search({});
|
|
90
|
+
let match = matchIn(rows);
|
|
91
|
+
if (!match && rows.length >= SLUG_LOOKUP_PAGE) {
|
|
92
|
+
const project = await platform.org('GET', `/p/${projectSlug}`);
|
|
93
|
+
const projectId = (project?.data ?? project)?.id;
|
|
94
|
+
if (typeof projectId === 'string')
|
|
95
|
+
match = matchIn(await search({ projectId }));
|
|
96
|
+
}
|
|
97
|
+
const facts = match ? factsOf(match) : undefined;
|
|
98
|
+
if (!facts)
|
|
99
|
+
return { profile: webProfile, known: false };
|
|
100
|
+
cache.set(key, { facts, at: Date.now() });
|
|
101
|
+
return { profile: profileFor(facts.platform), known: true, application: facts };
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return { profile: webProfile, known: false };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/** Yazma araçları uygulamayı değiştirdiğinde (tip, slug, properties) kaydı düşürür. */
|
|
108
|
+
export function forgetApplication(platform, applicationId) {
|
|
109
|
+
const cache = cacheOf(platform);
|
|
110
|
+
if (applicationId === undefined) {
|
|
111
|
+
cache.clear();
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
for (const [key, entry] of cache) {
|
|
115
|
+
if (key === applicationId || entry.facts.id === applicationId)
|
|
116
|
+
cache.delete(key);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Yanıta eklenen alan: tip biliniyorsa `applicationType`, bilinmiyorsa hiçbir şey. */
|
|
120
|
+
export function applicationTypeField(resolved) {
|
|
121
|
+
return resolved.known ? { applicationType: resolved.profile.platform } : {};
|
|
122
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ENGINE_STEP_TYPES, STEP_ALIASES } from './profile.js';
|
|
2
|
+
import { pageContainerNode } from '../normalize.js';
|
|
3
|
+
/**
|
|
4
|
+
* Web profili = gateway'in profil öncesi davranışı. Buradaki her değer bugün kodda bir yerde
|
|
5
|
+
* örtük olarak vardı; `test/platform-profile.test.ts` golden'ı bu profilin çıktıyı değiştirmediğini
|
|
6
|
+
* kilitler. Değer değiştirmek web davranışını değiştirir — golden kırmızıya döner.
|
|
7
|
+
*/
|
|
8
|
+
export const webProfile = Object.freeze({
|
|
9
|
+
platform: 'web',
|
|
10
|
+
catalogType: 'web',
|
|
11
|
+
layout: {
|
|
12
|
+
modes: new Set(['grid', 'flex', 'cssgrid']),
|
|
13
|
+
blocksMeaningful: true,
|
|
14
|
+
rootContainer: pageContainerNode,
|
|
15
|
+
orderBy: 'block-position'
|
|
16
|
+
},
|
|
17
|
+
appearance: {
|
|
18
|
+
ignoredKeys: new Set(),
|
|
19
|
+
sizeUnits: new Set(['px', '%', 'em', 'rem', 'calc'])
|
|
20
|
+
},
|
|
21
|
+
style: { freeStyle: true, hoverStyle: true, resolver: 'css' },
|
|
22
|
+
steps: {
|
|
23
|
+
registered: new Set([...ENGINE_STEP_TYPES, 'alert', 'confirm', 'redirect', 'download', 'storage', 'setcookie', 'share', 'haptic', 'location', 'notification-permission', 'notification-schedule', 'notification-cancel', 'permission', 'open-settings']),
|
|
24
|
+
aliases: STEP_ALIASES,
|
|
25
|
+
infoOnly: new Set()
|
|
26
|
+
},
|
|
27
|
+
shell: {
|
|
28
|
+
components: new Set(['navigations', 'sidebar', 'header']),
|
|
29
|
+
suggestions: {},
|
|
30
|
+
legacyShellNodes: new Set()
|
|
31
|
+
},
|
|
32
|
+
externalComponents: true,
|
|
33
|
+
state: { storageKinds: new Set() },
|
|
34
|
+
capture: {
|
|
35
|
+
target: 'studio-web',
|
|
36
|
+
devices: { desktop: { width: 1280, height: 800, dpr: 1 } },
|
|
37
|
+
defaultDevice: 'desktop'
|
|
38
|
+
}
|
|
39
|
+
});
|
package/dist/knowledge/policy.js
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import { logStep } from '../observability/trace.js';
|
|
2
2
|
export class PolicyBlockError extends Error {
|
|
3
3
|
findings;
|
|
4
|
-
|
|
4
|
+
canOverride;
|
|
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) {
|
|
5
16
|
super([
|
|
6
17
|
'Politika kontrolü isteği durdurdu (istek platforma gönderilmedi):',
|
|
7
18
|
...findings.map(finding => `- [${finding.ruleId}] ${finding.message}${finding.guide ? ` (rehber: ${finding.guide})` : ''}`),
|
|
8
|
-
|
|
19
|
+
canOverride
|
|
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."
|
|
9
22
|
].join('\n'));
|
|
10
23
|
this.findings = findings;
|
|
24
|
+
this.canOverride = canOverride;
|
|
11
25
|
this.name = 'PolicyBlockError';
|
|
12
26
|
}
|
|
13
27
|
}
|
|
@@ -35,11 +49,11 @@ export function evaluatePolicy(config, rules, module, definition, context, polic
|
|
|
35
49
|
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}`));
|
|
36
50
|
return findings;
|
|
37
51
|
}
|
|
38
|
-
export function enforcePolicy(findings) {
|
|
52
|
+
export function enforcePolicy(findings, canOverride = true) {
|
|
39
53
|
const blocking = findings.filter(finding => finding.severity === 'block');
|
|
40
54
|
if (blocking.length > 0) {
|
|
41
55
|
logStep('politika ✕', `${blocking.length} block bulgusu isteği durdurdu — platforma HİÇBİR istek gitmedi`, blocking.map(finding => `[${finding.ruleId}] ${finding.message}`));
|
|
42
|
-
throw new PolicyBlockError(blocking);
|
|
56
|
+
throw new PolicyBlockError(blocking, canOverride);
|
|
43
57
|
}
|
|
44
58
|
return findings;
|
|
45
59
|
}
|