@appaflytech/zeyrek-ai-mcp 0.0.7 → 0.0.9
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 +27 -21
- package/dist/config.js +2 -0
- package/dist/knowledge/backendConstraints.js +3 -0
- package/dist/knowledge/componentCatalog.js +172 -33
- package/dist/knowledge/componentEvents.js +35 -4
- package/dist/knowledge/errorPath.js +1 -1
- package/dist/knowledge/normalize.js +474 -23
- package/dist/knowledge/propTypes.js +5 -4
- package/dist/knowledge/rules.js +113 -6
- package/dist/knowledge/styleResolve.js +52 -5
- package/dist/knowledge/themeResolve.js +936 -0
- package/dist/knowledge/themeRules.js +221 -0
- package/dist/knowledge/themeSchema.js +335 -0
- package/dist/platform/domSummary.js +144 -0
- package/dist/platform/http.js +10 -2
- package/dist/platform/screenshot.js +492 -29
- package/dist/platform/screenshotMemory.js +55 -0
- package/dist/platform/strictArguments.js +32 -0
- package/dist/platform/writeDiff.js +6 -3
- package/dist/resources/examples/layout-app-shell.json +1 -1
- package/dist/resources/examples/page-sign-in.json +1 -1
- package/dist/resources/examples/theme-brand.json +162 -0
- package/dist/resources/guides/component.md +8 -2
- package/dist/resources/guides/expressions.md +6 -0
- package/dist/resources/guides/getting-started.md +6 -0
- package/dist/resources/guides/layout.md +36 -26
- package/dist/resources/guides/microservice.md +160 -6
- package/dist/resources/guides/page.md +165 -59
- package/dist/resources/guides/theme.md +210 -0
- package/dist/resources/guides/translation.md +13 -10
- package/dist/resources/guides/workflow.md +141 -7
- package/dist/resources/schema-fingerprint.json +2 -2
- package/dist/resources/schemas/CreateMicroserviceCommand.json +4 -1
- package/dist/resources/schemas/CreateWorkflowCommand.json +4 -1
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +4 -1
- package/dist/resources/schemas/PreviewWorkflowCommand.json +4 -1
- package/dist/resources/schemas/StepDto.json +4 -1
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +4 -1
- package/dist/resources/schemas/UpdateWorkflowCommand.json +4 -1
- package/dist/server.js +52 -42
- package/dist/tools/components.js +8 -0
- package/dist/tools/designSchemaPatch.js +152 -0
- package/dist/tools/flows.js +24 -21
- package/dist/tools/layouts.js +8 -8
- package/dist/tools/microservices.js +74 -10
- package/dist/tools/pages.js +275 -332
- package/dist/tools/projects.js +66 -9
- package/dist/tools/queries.js +72 -6
- package/dist/tools/schemaOps.js +280 -0
- package/dist/tools/screenWrite.js +2 -1
- package/dist/tools/screens.js +0 -7
- package/dist/tools/themes.js +163 -0
- package/dist/tools/workflows.js +10 -6
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -1,41 +1,44 @@
|
|
|
1
|
-
import { McpServer } from
|
|
2
|
-
import { registerMicroserviceTools } from
|
|
3
|
-
import { registerMicrofunctionTools } from
|
|
4
|
-
import { registerApplicationTools } from
|
|
5
|
-
import { registerDeploymentTools } from
|
|
6
|
-
import { registerDatasourceTools } from
|
|
7
|
-
import { registerAutomationTools } from
|
|
8
|
-
import { registerOrganizationTools } from
|
|
9
|
-
import { registerExternalComponentTools } from
|
|
10
|
-
import { registerComponentTools } from
|
|
11
|
-
import { registerPlatformTools } from
|
|
12
|
-
import { registerTemplateTools } from
|
|
13
|
-
import { registerWorkflowTools } from
|
|
14
|
-
import { registerLayoutTools } from
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { registerMicroserviceTools } from "./tools/microservices.js";
|
|
3
|
+
import { registerMicrofunctionTools } from "./tools/microfunctions.js";
|
|
4
|
+
import { registerApplicationTools } from "./tools/applications.js";
|
|
5
|
+
import { registerDeploymentTools } from "./tools/deployments.js";
|
|
6
|
+
import { registerDatasourceTools } from "./tools/datasources.js";
|
|
7
|
+
import { registerAutomationTools } from "./tools/automations.js";
|
|
8
|
+
import { registerOrganizationTools } from "./tools/organizations.js";
|
|
9
|
+
import { registerExternalComponentTools } from "./tools/externalComponents.js";
|
|
10
|
+
import { registerComponentTools } from "./tools/components.js";
|
|
11
|
+
import { registerPlatformTools } from "./tools/platformInfo.js";
|
|
12
|
+
import { registerTemplateTools } from "./tools/templates.js";
|
|
13
|
+
import { registerWorkflowTools } from "./tools/workflows.js";
|
|
14
|
+
import { registerLayoutTools } from "./tools/layouts.js";
|
|
15
|
+
import { registerDesignSchemaPatchTool } from "./tools/designSchemaPatch.js";
|
|
16
|
+
import { registerAccessTools } from "./tools/access.js";
|
|
17
|
+
import { registerTranslationTools } from "./tools/translations.js";
|
|
18
|
+
import { registerFlowTools } from "./tools/flows.js";
|
|
19
|
+
import { registerKnowledgeResources } from "./resources/knowledge.js";
|
|
20
|
+
import { registerSchemaResources } from "./resources/schemas.js";
|
|
21
|
+
import { registerRuleResources } from "./resources/rules.js";
|
|
22
|
+
import { instrumentServer } from "./observability/trace.js";
|
|
23
|
+
import { rejectUnknownArguments } from "./platform/strictArguments.js";
|
|
24
|
+
import { registerProjectTools } from "./tools/projects.js";
|
|
25
|
+
import { registerEntityTools } from "./tools/entities.js";
|
|
26
|
+
import { registerDependencyTools } from "./tools/dependencies.js";
|
|
27
|
+
import { registerVariableTools } from "./tools/variables.js";
|
|
28
|
+
import { registerFunctionTools } from "./tools/functions.js";
|
|
29
|
+
import { registerFolderTools } from "./tools/folders.js";
|
|
30
|
+
import { registerQueryTools } from "./tools/queries.js";
|
|
31
|
+
import { registerViewTools } from "./tools/views.js";
|
|
32
|
+
import { registerPageTools } from "./tools/pages.js";
|
|
33
|
+
import { registerThemeTools } from "./tools/themes.js";
|
|
34
|
+
import { registerFileTools } from "./tools/files.js";
|
|
35
|
+
import { registerRowTools } from "./tools/rows.js";
|
|
36
|
+
import { registerImportTools } from "./tools/imports.js";
|
|
37
|
+
import { registerEnvironmentTools } from "./tools/environments.js";
|
|
38
|
+
import { registerMergeTools } from "./tools/merges.js";
|
|
39
|
+
import { registerRevisionTools } from "./tools/revisions.js";
|
|
40
|
+
import { registerActivityTools } from "./tools/activities.js";
|
|
41
|
+
import { registerDtoTools } from "./tools/dtos.js";
|
|
39
42
|
const moduleRegistrations = {
|
|
40
43
|
platform: registerPlatformTools,
|
|
41
44
|
project: registerProjectTools,
|
|
@@ -52,10 +55,17 @@ const moduleRegistrations = {
|
|
|
52
55
|
dto: registerDtoTools,
|
|
53
56
|
view: registerViewTools,
|
|
54
57
|
page: registerPageTools,
|
|
55
|
-
|
|
58
|
+
theme: registerThemeTools,
|
|
59
|
+
component: (server, platform) => {
|
|
60
|
+
registerComponentTools(server, platform);
|
|
61
|
+
registerDesignSchemaPatchTool(server, platform, "component");
|
|
62
|
+
},
|
|
56
63
|
externalComponent: registerExternalComponentTools,
|
|
57
64
|
flow: registerFlowTools,
|
|
58
|
-
layout:
|
|
65
|
+
layout: (server, platform) => {
|
|
66
|
+
registerLayoutTools(server, platform);
|
|
67
|
+
registerDesignSchemaPatchTool(server, platform, "layout");
|
|
68
|
+
},
|
|
59
69
|
variable: registerVariableTools,
|
|
60
70
|
function: registerFunctionTools,
|
|
61
71
|
folder: registerFolderTools,
|
|
@@ -69,10 +79,10 @@ const moduleRegistrations = {
|
|
|
69
79
|
environment: registerEnvironmentTools,
|
|
70
80
|
merge: registerMergeTools,
|
|
71
81
|
activity: registerActivityTools,
|
|
72
|
-
revision: registerRevisionTools
|
|
82
|
+
revision: registerRevisionTools,
|
|
73
83
|
};
|
|
74
84
|
export function createGatewayServer(platform) {
|
|
75
|
-
const server = instrumentServer(new McpServer({ name:
|
|
85
|
+
const server = rejectUnknownArguments(instrumentServer(new McpServer({ name: "ngapps", version: "0.1.0" }), platform.config));
|
|
76
86
|
for (const moduleName of platform.config.modules) {
|
|
77
87
|
moduleRegistrations[moduleName](server, platform);
|
|
78
88
|
}
|
package/dist/tools/components.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { guid, projectParam, environmentParam, readOnly, writes, updates, destructive } from './common.js';
|
|
2
2
|
import { normalizeComponentDefaults, componentDefaultsNote, clampBlockSizes, blockSizeNote, normalizeHeightTypes, heightTypeNote, normalizeSizeStrings, sizeStringNote, withNormalization } from '../knowledge/normalize.js';
|
|
3
3
|
import { eventContractsFor, eventPayloadNote } from '../knowledge/componentEvents.js';
|
|
4
|
+
import { componentPresetDefaults, readProjectTheme } from '../knowledge/themeSchema.js';
|
|
4
5
|
import { knowledgeFor, knowledgeNote, APPEARANCE_TOKEN_SETS, STATE_FLAG_NOTES, INTERNAL_ROLES_BY_TYPE } from '../knowledge/componentCatalog.js';
|
|
5
6
|
import { componentUpdateBody, fetchHost, schemaParam, unwrap } from './screens.js';
|
|
6
7
|
import { PlatformApiError } from '../platform/errors.js';
|
|
@@ -160,6 +161,12 @@ export function registerComponentTools(server, platform) {
|
|
|
160
161
|
: [];
|
|
161
162
|
const componentSlug = typeof component.slug === 'string' ? component.slug : undefined;
|
|
162
163
|
const knowledge = knowledgeFor(componentSlug);
|
|
164
|
+
// S-3 — `defaults` HAM katalogdur; Studio'da bırakılan düğüm ise temanın bileşen preseti
|
|
165
|
+
// kaplanmış katalogdan kurulur (`withThemeComponentDefaults`). Tema okunamazsa (uç düşer,
|
|
166
|
+
// yetki yoksa) alan yanıta HİÇ girmez: uydurulmuş bir varsayılan yanlış bilgidir.
|
|
167
|
+
const themeDefaults = componentSlug === undefined
|
|
168
|
+
? undefined
|
|
169
|
+
: componentPresetDefaults(readProjectTheme(await platform.org('GET', `/p/${platform.resolveProject(project)}`).catch(() => undefined)), componentSlug);
|
|
163
170
|
return {
|
|
164
171
|
id: component.id,
|
|
165
172
|
slug: component.slug,
|
|
@@ -188,6 +195,7 @@ export function registerComponentTools(server, platform) {
|
|
|
188
195
|
internalRolesNote: "Bu komponentin İÇ kontrolleri dışarıdan adreslenebilir: page_screenshot actions hedefine '<elementId>__<rol>' yazın (ör. 'tbl_vacancy__pager-next'). Kimlikler runtime'ın data-element-id özniteliğidir; ikinci bir mekanizma yoktur."
|
|
189
196
|
}
|
|
190
197
|
: {}),
|
|
198
|
+
...(themeDefaults ? { themeDefaults } : {}),
|
|
191
199
|
appearanceValues: APPEARANCE_TOKEN_SETS,
|
|
192
200
|
stateFlags: STATE_FLAG_NOTES,
|
|
193
201
|
validations: definition.validations,
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { orphanedFlowWarnings, orphanedFlowPlan, orphanedFlowMessage, staleSetterWarnings, normalizeSchemaOps, validationNote, componentDefaultsNote, replacePropNote, flexSizeWarnings, nestedRepeaterNodes, nestedRepeaterMessage, stringStyleNodes, stringStyleWarning, inertFlexPropNodes, inertFlexPropWarning, verticalGapWarnings, withNormalization, FLEX_LAYOUT_PROP_NAMES } from '../knowledge/normalize.js';
|
|
2
|
+
import { opsParam, writeViewParam, outlineWriteResponse, unknownEventOps, collectTypes, simulateLayoutOps, removeNodeFromTree, planEventRemovals, planResizes, planPropTypes, assertOpBodies } from './schemaOps.js';
|
|
3
|
+
import { guid, projectParam, environmentParam, updates, microOps } from './common.js';
|
|
4
|
+
import { fetchHost, hostPath } from './screens.js';
|
|
5
|
+
import { assertScreenWriteGuards, screenCatalogNotes } from './screenWrite.js';
|
|
6
|
+
import { schemaOpDrops, withWriteDiff } from '../platform/writeDiff.js';
|
|
7
|
+
import { fetchComponentEventNames } from './components.js';
|
|
8
|
+
import { PlatformApiError } from '../platform/errors.js';
|
|
9
|
+
import { handle } from '../platform/responses.js';
|
|
10
|
+
import { slotWarning } from './layouts.js';
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
const HOSTS = {
|
|
13
|
+
layout: {
|
|
14
|
+
tool: 'layout_schema_patch',
|
|
15
|
+
readTool: 'layout_schema_get',
|
|
16
|
+
tree: 'views',
|
|
17
|
+
kind: 'layout',
|
|
18
|
+
codes: { gap: 'LAY-003 (uyarı)', flexMismatch: 'LAY-007 (uyarı)', flexInvalid: 'LAY-008 (uyarı)' },
|
|
19
|
+
title: "Layout şemasına micro-op uygula",
|
|
20
|
+
description: "page_schema_patch'in layout karşılığı: micro-op'ları platformun PATCH /layouts/{app}/{id}/schema ucuna TEK istekle yazar; sunucu sayfa ile AYNI op sözlüğünü ve doğrulama kapsamını kullanır (dokunulan düğümler tam doğrulanır, geri kalan ağaç yapısal). İstek atomiktir: bir op reddedilirse hiçbiri yazılmaz. Op sözlüğü page_schema_patch ile birebir aynıdır; farklar: kök ekleme 'root' parent'ına gider (page_container yoktur), remove_event target:'page' layout düzeyi olayları hedefler, baseVersion yoktur (son yazan kazanır — hedefleri layout_schema_get ile okuyun). Slot'u silen ya da ikinci slot ekleyen yama LAY-002/LAY-006 uyarısı alır. Layout'un adı, parametreleri ve düz JSON Patch değişiklikleri için layout_patch; tam ağaç için layout_update."
|
|
21
|
+
},
|
|
22
|
+
component: {
|
|
23
|
+
tool: 'component_schema_patch',
|
|
24
|
+
readTool: 'component_get',
|
|
25
|
+
tree: 'schema',
|
|
26
|
+
kind: 'widget',
|
|
27
|
+
codes: { gap: 'PAGE-010 (uyarı)', flexMismatch: 'PAGE-017 (uyarı)', flexInvalid: 'PAGE-018 (uyarı)' },
|
|
28
|
+
title: 'Widget şemasına micro-op uygula',
|
|
29
|
+
description: "page_schema_patch'in widget karşılığı: widget kaydının (kind:'widget') kendi ağacına micro-op'ları platformun PATCH /components/{app}/{id}/schema ucuna TEK istekle yazar; sunucu sayfa ile AYNI op sözlüğünü ve doğrulama kapsamını kullanır. İstek atomiktir: bir op reddedilirse hiçbiri yazılmaz. Op sözlüğü page_schema_patch ile aynıdır; farklar: kök ekleme 'root' parent'ına gider, widget'ın düzey olayı olmadığı için remove_event yalnız komponent hedefler, baseVersion yoktur. id widget kaydının id'sidir (component_list / component_get). component_update tam gövde PUT'tur ve slug alır; ağaçta hedefli değişiklik için bu aracı kullanın."
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Layout ve widget ağaçlarının micro-op yazması. Sayfa hattıyla (`page_schema_patch`) aynı istek
|
|
34
|
+
* öncesi kapılar koşar; sayfaya özgü olanlar (page_container koruması, kökten page_container'a
|
|
35
|
+
* yönlendirme, baseVersion) düşer. Kayıt her yamada BİR kez okunur: PAGE-008, G-21 ve boyut/tip
|
|
36
|
+
* planlaması okunan ağaca bakar, platformda sürüm koşulu olmadığı için okuma bir kilit değildir.
|
|
37
|
+
*/
|
|
38
|
+
export function registerDesignSchemaPatchTool(server, platform, host) {
|
|
39
|
+
const config = platform.config;
|
|
40
|
+
const spec = HOSTS[host];
|
|
41
|
+
server.registerTool(spec.tool, {
|
|
42
|
+
title: spec.title,
|
|
43
|
+
description: spec.description,
|
|
44
|
+
inputSchema: {
|
|
45
|
+
project: projectParam,
|
|
46
|
+
environment: environmentParam,
|
|
47
|
+
applicationId: guid,
|
|
48
|
+
id: guid.describe(host === 'layout' ? "Layout id'si" : "Widget kaydının id'si (slug değil)"),
|
|
49
|
+
ops: opsParam.optional(),
|
|
50
|
+
operations: opsParam.optional().describe("'ops' ile aynı alan (eşanlamlı)"),
|
|
51
|
+
allowFlowDeletion: z.boolean().optional().describe(`true: bu yama bir akışı referanssız bırakacaksa yine de uygulanır. Varsayılan false — platform ${host === 'layout' ? 'layout' : 'widget'} kaydında da referanssız akışı KALICI siler ve gateway isteği önden reddeder (G-21).`),
|
|
52
|
+
view: writeViewParam
|
|
53
|
+
},
|
|
54
|
+
annotations: updates
|
|
55
|
+
}, handle(config, async ({ project, environment, applicationId, id, ops, operations, allowFlowDeletion, view }) => {
|
|
56
|
+
const allOps = microOps(spec.tool, ops, operations).map(op => op);
|
|
57
|
+
const removeEventOps = allOps.filter(entry => entry.op === 'remove_event');
|
|
58
|
+
const resizeOps = allOps.filter(entry => entry.op === 'resize_component');
|
|
59
|
+
const propTypeOps = allOps.filter(entry => entry.op === 'set_prop_type');
|
|
60
|
+
const opRecords = allOps.filter(entry => !['remove_event', 'resize_component', 'set_prop_type'].includes(String(entry.op)));
|
|
61
|
+
const normalized = normalizeSchemaOps(opRecords);
|
|
62
|
+
assertOpBodies(opRecords, propTypeOps);
|
|
63
|
+
const record = await fetchHost(platform, host, project, environment, applicationId, id);
|
|
64
|
+
// Platform ucu kaydın türüne bakmaz: sıradan bir komponentin id'si verilirse kataloğundaki
|
|
65
|
+
// tanımın yanına bir şema yazılırdı.
|
|
66
|
+
if (host === 'component' && record.kind !== 'widget' && !record.widgetType) {
|
|
67
|
+
throw new PlatformApiError(`component_schema_patch yalnız widget kaydına yazar; '${String(record.slug ?? id)}' bir widget değil (kind: ${String(record.kind ?? 'yok')}). Komponent kaydını component_update ile güncelleyin.`, 400);
|
|
68
|
+
}
|
|
69
|
+
const nodes = (record[spec.tree] ?? []);
|
|
70
|
+
const events = host === 'layout' ? record.events : undefined;
|
|
71
|
+
if (opRecords.some(entry => entry.op === 'set_event')) {
|
|
72
|
+
const typesByElementId = new Map();
|
|
73
|
+
collectTypes(nodes, typesByElementId);
|
|
74
|
+
collectTypes(opRecords.map(entry => entry.component).filter(Boolean), typesByElementId);
|
|
75
|
+
const eventsBySlug = await fetchComponentEventNames(platform, project, environment, applicationId).catch(() => new Map());
|
|
76
|
+
const unknown = unknownEventOps(opRecords, typesByElementId, eventsBySlug);
|
|
77
|
+
if (unknown.length > 0)
|
|
78
|
+
throw new PlatformApiError(`PAGE-008 — geçersiz olay adı (istek gönderilmedi): ${unknown.join(' · ')}`, 400);
|
|
79
|
+
}
|
|
80
|
+
const deletedFlows = orphanedFlowPlan(nodes, events, [...opRecords, ...removeEventOps]);
|
|
81
|
+
if (deletedFlows.length > 0 && allowFlowDeletion !== true)
|
|
82
|
+
throw new PlatformApiError(orphanedFlowMessage(deletedFlows), 400);
|
|
83
|
+
const added = opRecords.filter(entry => entry.op === 'add_component').map(entry => entry.component);
|
|
84
|
+
assertScreenWriteGuards(spec.kind, { schema: added });
|
|
85
|
+
const catalogNotes = await screenCatalogNotes(platform, project, environment, applicationId, added);
|
|
86
|
+
const flowWarnings = opRecords.some(entry => entry.op === 'remove_component')
|
|
87
|
+
? [...orphanedFlowWarnings(nodes, events, opRecords), ...staleSetterWarnings(Array.isArray(record.flows) ? record.flows : [], opRecords, nodes)]
|
|
88
|
+
: [];
|
|
89
|
+
const simulated = structuredClone(nodes);
|
|
90
|
+
for (const entry of opRecords.filter(entry => entry.op === 'remove_component'))
|
|
91
|
+
removeNodeFromTree(simulated, String(entry.target ?? ''));
|
|
92
|
+
const touched = simulateLayoutOps(simulated, opRecords);
|
|
93
|
+
// Sayfadaki `simulatable` ile aynı küme: iç içe repeater ancak ekleme/taşıma ile doğar, kontrol
|
|
94
|
+
// her yamada koşsaydı kayıtlı ağacında zaten iç içe repeater olan layout hiç yamalanamazdı.
|
|
95
|
+
const simulatable = opRecords.some(entry => ['add_component', 'move_component'].includes(String(entry.op))
|
|
96
|
+
|| (entry.op === 'replace_prop' && FLEX_LAYOUT_PROP_NAMES.has(String(entry.prop ?? ''))));
|
|
97
|
+
const nested = simulatable ? nestedRepeaterNodes(simulated) : [];
|
|
98
|
+
if (nested.length > 0)
|
|
99
|
+
throw new PlatformApiError(nestedRepeaterMessage(nested), 400);
|
|
100
|
+
const reshaped = simulatable || opRecords.some(entry => entry.op === 'remove_component');
|
|
101
|
+
const layoutWarnings = reshaped
|
|
102
|
+
? [
|
|
103
|
+
...verticalGapWarnings(simulated, spec.codes.gap, touched),
|
|
104
|
+
...stringStyleWarning(stringStyleNodes(simulated)),
|
|
105
|
+
...inertFlexPropWarning(inertFlexPropNodes(simulated)),
|
|
106
|
+
...flexSizeWarnings(simulated, spec.codes.flexMismatch, spec.codes.flexInvalid),
|
|
107
|
+
...(host === 'layout' ? slotWarning(simulated) : [])
|
|
108
|
+
]
|
|
109
|
+
: [];
|
|
110
|
+
const removedEvents = planEventRemovals(removeEventOps);
|
|
111
|
+
const resized = resizeOps.length > 0 ? planResizes(nodes, resizeOps, spec.readTool) : { serverOps: [], applied: [], warnings: [] };
|
|
112
|
+
const propTypes = propTypeOps.length > 0 ? planPropTypes(nodes, propTypeOps, spec.readTool) : { serverOps: [], applied: [] };
|
|
113
|
+
const serverOps = [...removeEventOps, ...resized.serverOps, ...propTypes.serverOps, ...opRecords];
|
|
114
|
+
const response = ((await platform.tenant('PATCH', project, `${hostPath(host, applicationId, id)}/schema`, {
|
|
115
|
+
environment,
|
|
116
|
+
body: { ops: serverOps }
|
|
117
|
+
})) ?? {});
|
|
118
|
+
if (view !== 'full')
|
|
119
|
+
outlineWriteResponse(response);
|
|
120
|
+
if (removedEvents.length > 0)
|
|
121
|
+
response.removedEvents = removedEvents;
|
|
122
|
+
if (propTypes.applied.length > 0)
|
|
123
|
+
response.propTypes = propTypes.applied;
|
|
124
|
+
if (resized.applied.length > 0)
|
|
125
|
+
response.resized = resized.applied;
|
|
126
|
+
if (resized.warnings.length > 0)
|
|
127
|
+
response.resizeWarnings = resized.warnings;
|
|
128
|
+
if (deletedFlows.length > 0)
|
|
129
|
+
response.deletedFlows = deletedFlows;
|
|
130
|
+
if (flowWarnings.length > 0)
|
|
131
|
+
response.flowWarnings = flowWarnings;
|
|
132
|
+
if (layoutWarnings.length > 0)
|
|
133
|
+
response.layoutWarnings = layoutWarnings;
|
|
134
|
+
const contentOps = opRecords.filter(entry => entry.op === 'add_component' || entry.op === 'replace_prop');
|
|
135
|
+
let opDrops = [];
|
|
136
|
+
if (contentOps.length > 0) {
|
|
137
|
+
try {
|
|
138
|
+
const saved = await fetchHost(platform, host, project, environment, applicationId, id);
|
|
139
|
+
opDrops = schemaOpDrops(saved[spec.tree], contentOps);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
opDrops = [];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return withWriteDiff(withNormalization(response, [
|
|
146
|
+
...componentDefaultsNote(normalized.components),
|
|
147
|
+
...validationNote(normalized.validations),
|
|
148
|
+
...catalogNotes,
|
|
149
|
+
...replacePropNote(normalized.props)
|
|
150
|
+
]), opDrops);
|
|
151
|
+
}));
|
|
152
|
+
}
|
package/dist/tools/flows.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { fetchHost, flowPath, hostParam,
|
|
1
|
+
import { fetchHost, flowPath, hostParam, unwrap } from './screens.js';
|
|
2
2
|
import { guid, projectParam, environmentParam, readOnly, writes, updates, destructive, microOps } from './common.js';
|
|
3
3
|
import { evaluatePolicy, enforcePolicy, attachFindings } from '../knowledge/policy.js';
|
|
4
|
-
import { normalizeFlowSteps, unknownSetterTargetWarnings, withNormalization } from '../knowledge/normalize.js';
|
|
4
|
+
import { normalizeFlowSteps, targetlessSetterWarnings, unknownSetterTargetWarnings, withNormalization } from '../knowledge/normalize.js';
|
|
5
5
|
import { flowBodyWarnings } from '../knowledge/coverage.js';
|
|
6
6
|
import { PlatformApiError } from '../platform/errors.js';
|
|
7
7
|
import { handle } from '../platform/responses.js';
|
|
@@ -42,10 +42,6 @@ function flowSummary(flow) {
|
|
|
42
42
|
errorSteps: Array.isArray(flow.errorSteps) ? flow.errorSteps.length : 0
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
|
-
async function hostEnvelope(platform, host, project, environment, applicationId, hostId) {
|
|
46
|
-
const record = await fetchHost(platform, host, project, environment, applicationId, hostId);
|
|
47
|
-
return { record, envelope: { [host]: hostUpdateBody(host, { ...record, applicationId }) } };
|
|
48
|
-
}
|
|
49
45
|
/**
|
|
50
46
|
* FLOW-024'ün arayacağı düğüm kümesi. Ham kaydın TAMAMI gezilmez: kayıt kendi `flows`'unu da
|
|
51
47
|
* taşıyabilir ve oradaki bayat element id'leri kümeyi kirletip aramayı sessizce boşa çıkarır.
|
|
@@ -243,13 +239,19 @@ export function registerFlowTools(server, platform) {
|
|
|
243
239
|
}));
|
|
244
240
|
server.registerTool('flow_get', {
|
|
245
241
|
title: 'Akış getir',
|
|
246
|
-
description:
|
|
242
|
+
description: "Tek akışı adımlarıyla getirir; yeni akış yazarken en iyi şablon budur. Hedefi silinmiş (element'siz) setter iteratee'si varsa yanıttaki flowWarnings söyler — o adım koşar ama hiçbir şeye yazmaz.",
|
|
247
243
|
inputSchema: { project: projectParam, environment: environmentParam, host: hostParam, applicationId: guid, hostId: guid, flowId: flowIdParam },
|
|
248
244
|
annotations: readOnly
|
|
249
|
-
}, handle(config, ({ project, environment, host, applicationId, hostId, flowId }) =>
|
|
245
|
+
}, handle(config, async ({ project, environment, host, applicationId, hostId, flowId }) => {
|
|
246
|
+
const response = await platform.tenant('GET', project, flowPath(host, applicationId, hostId, flowId), { environment });
|
|
247
|
+
const warnings = targetlessSetterWarnings(response);
|
|
248
|
+
if (warnings.length === 0 || !response || typeof response !== 'object' || Array.isArray(response))
|
|
249
|
+
return response;
|
|
250
|
+
return { ...response, flowWarnings: warnings };
|
|
251
|
+
}));
|
|
250
252
|
server.registerTool('flow_create', {
|
|
251
253
|
title: 'Akış oluştur',
|
|
252
|
-
description: "Sayfa/layout/komponent için olay akışı oluşturur.
|
|
254
|
+
description: "Sayfa/layout/komponent için olay akışı oluşturur. İstek yalnız akışı yazar, barındırıcının şemasına dokunmaz; gateway barındırıcıyı yalnız setter hedeflerini denetlemek için okur (FLOW-024). Akışı bir komponent olayına bağlamak ayrı adımdır ve akış kaydedildikten SONRA yapılır: set_event {target, event, eventValue: <flow id>} — sayfada page_schema_patch, layout'ta layout_schema_patch, widget'ta component_schema_patch.",
|
|
253
255
|
inputSchema: {
|
|
254
256
|
project: projectParam,
|
|
255
257
|
environment: environmentParam,
|
|
@@ -265,7 +267,7 @@ export function registerFlowTools(server, platform) {
|
|
|
265
267
|
},
|
|
266
268
|
annotations: writes
|
|
267
269
|
}, handle(config, async ({ project, environment, host, applicationId, hostId, name, slug, steps, errorSteps, flowId, policyOverride }) => {
|
|
268
|
-
const
|
|
270
|
+
const hostRecord = await fetchHost(platform, host, project, environment, applicationId, hostId);
|
|
269
271
|
const resolvedFlowId = flowId ?? randomUUID();
|
|
270
272
|
const flow = {
|
|
271
273
|
id: resolvedFlowId,
|
|
@@ -283,7 +285,10 @@ export function registerFlowTools(server, platform) {
|
|
|
283
285
|
...flowBodyWarnings(steps),
|
|
284
286
|
...unknownSetterTargetWarnings(steps, errorSteps ?? [], hostNodes(hostRecord))
|
|
285
287
|
];
|
|
286
|
-
|
|
288
|
+
// Gövde yalnız akıştır (designer-partial-update K1): barındırıcı zarfı platformda hâlâ isteğe bağlı
|
|
289
|
+
// ama gönderilirse okunan tam kaydı yeniden yazar, açık Studio designer'ının kayıtlı tabanını
|
|
290
|
+
// eskitir. Kayıt yalnız FLOW-024 hedef araması için okunur.
|
|
291
|
+
await platform.tenant('POST', project, flowPath(host, applicationId, hostId), { environment, body: { flow } });
|
|
287
292
|
// Diff YALNIZ çağıranın yazdığı alanları kapsar; `id` ve barındırıcı bağı (`pageId` vb.)
|
|
288
293
|
// gövdeye gateway koyar, kullanıcının düzeltebileceği bir şey değildir.
|
|
289
294
|
const drops = await flowWriteDrops(platform, host, project, environment, applicationId, hostId, resolvedFlowId, { name: flow.name, slug: flow.slug, steps: flow.steps, errorSteps: flow.errorSteps });
|
|
@@ -292,12 +297,12 @@ export function registerFlowTools(server, platform) {
|
|
|
292
297
|
hostId,
|
|
293
298
|
flow: { id: resolvedFlowId, name, slug, steps: steps.length },
|
|
294
299
|
...(parameterWarnings.length > 0 ? { parameterWarnings } : {}),
|
|
295
|
-
hint: "Akışı bir olaya bağlamak için: page_schema_patch ops:[{op:'set_event', target:<elementId>, event:'<component_get events listesindeki ad>', eventValue:<flow id>}]. Olay adları komponente özeldir ve 'on' ÖNEKİ ALMAZ (button → 'click', form → 'submit', table → 'mount'/'select'/'sort'…); uydurma ad 200 döner ama bağ sessizce ölü kalır — gateway PAGE-008 ile yakalar."
|
|
300
|
+
hint: "Akışı bir olaya bağlamak için: page_schema_patch (layout'ta layout_schema_patch, widget'ta component_schema_patch) ops:[{op:'set_event', target:<elementId>, event:'<component_get events listesindeki ad>', eventValue:<flow id>}]. Olay adları komponente özeldir ve 'on' ÖNEKİ ALMAZ (button → 'click', form → 'submit', table → 'mount'/'select'/'sort'…); uydurma ad 200 döner ama bağ sessizce ölü kalır — gateway PAGE-008 ile yakalar."
|
|
296
301
|
}, normalized), drops), findings);
|
|
297
302
|
}));
|
|
298
303
|
server.registerTool('flow_update', {
|
|
299
304
|
title: 'Akış güncelle',
|
|
300
|
-
description: 'Akışın adını/adımlarını değiştirir. Gövde replace\'tir: verilen steps listesi akışın yeni tam hâlidir.
|
|
305
|
+
description: 'Akışın adını/adımlarını değiştirir. Gövde replace\'tir: verilen steps listesi akışın yeni tam hâlidir. Yalnız akış yazılır; barındırıcının şeması değişmez.',
|
|
301
306
|
inputSchema: {
|
|
302
307
|
project: projectParam,
|
|
303
308
|
environment: environmentParam,
|
|
@@ -316,7 +321,7 @@ export function registerFlowTools(server, platform) {
|
|
|
316
321
|
const current = unwrap(await platform.tenant('GET', project, flowPath(host, applicationId, hostId, flowId), { environment }));
|
|
317
322
|
if (!current.id)
|
|
318
323
|
throw new PlatformApiError(`'${flowId}' id'li akış bulunamadı; flow_list ile doğrulayın.`);
|
|
319
|
-
const
|
|
324
|
+
const hostRecord = await fetchHost(platform, host, project, environment, applicationId, hostId);
|
|
320
325
|
const flow = {
|
|
321
326
|
id: flowId,
|
|
322
327
|
name: name ?? current.name,
|
|
@@ -336,7 +341,7 @@ export function registerFlowTools(server, platform) {
|
|
|
336
341
|
...flowBodyWarnings(flow.steps),
|
|
337
342
|
...unknownSetterTargetWarnings(flow.steps, flow.errorSteps, hostNodes(hostRecord))
|
|
338
343
|
];
|
|
339
|
-
await platform.tenant('PUT', project, flowPath(host, applicationId, hostId, flowId), { environment, body: { flow
|
|
344
|
+
await platform.tenant('PUT', project, flowPath(host, applicationId, hostId, flowId), { environment, body: { flow } });
|
|
340
345
|
// Kısmi güncellemede yalnız GÖNDERİLEN alanlar karşılaştırılır; verilmeyen alan için
|
|
341
346
|
// "düştü" demek yanlış alarm olurdu.
|
|
342
347
|
const drops = await flowWriteDrops(platform, host, project, environment, applicationId, hostId, flowId, {
|
|
@@ -370,7 +375,7 @@ export function registerFlowTools(server, platform) {
|
|
|
370
375
|
const document = structuredClone(current);
|
|
371
376
|
const resolved = resolvePatchOperations(document, operations, 'flow_get');
|
|
372
377
|
const patched = fastJsonPatch.applyPatch(document, resolved.operations, true, false).newDocument;
|
|
373
|
-
const
|
|
378
|
+
const hostRecord = await fetchHost(platform, host, project, environment, applicationId, hostId);
|
|
374
379
|
const flow = {
|
|
375
380
|
...patched,
|
|
376
381
|
id: flowId,
|
|
@@ -386,8 +391,7 @@ export function registerFlowTools(server, platform) {
|
|
|
386
391
|
...flowBodyWarnings(flow.steps),
|
|
387
392
|
...unknownSetterTargetWarnings(flow.steps, flow.errorSteps, hostNodes(hostRecord))
|
|
388
393
|
];
|
|
389
|
-
// Gövde değil FARK gönderilir
|
|
390
|
-
// PATCH ucu akışı tek başına yazar. Net diff okunan kayıt ile son hâl arasından hesaplanır.
|
|
394
|
+
// Gövde değil FARK gönderilir; platform PATCH ucu akışı tek başına yazar. Net diff okunan kayıt ile son hâl arasından hesaplanır.
|
|
391
395
|
const netOps = fastJsonPatch.compare(current, flow);
|
|
392
396
|
const saved = await platform.tenant('PATCH', project, flowPath(host, applicationId, hostId, flowId), {
|
|
393
397
|
environment,
|
|
@@ -407,12 +411,11 @@ export function registerFlowTools(server, platform) {
|
|
|
407
411
|
}));
|
|
408
412
|
server.registerTool('flow_delete', {
|
|
409
413
|
title: 'Akış sil',
|
|
410
|
-
description: "Akışı siler.
|
|
414
|
+
description: "Akışı siler; gövde yalnız akış id'sidir ve barındırıcının şemasına dokunmaz, yani olay bağı kendiliğinden KALKMAZ. Doğru sıra: önce bağı remove_event ile kaldırın (sayfada page_schema_patch, layout'ta layout_schema_patch, widget'ta component_schema_patch). Bağı kalmayan akışı platform o yamada zaten kalıcı siler (yama allowFlowDeletion:true ister); ardından flow_delete no-op'tur. Önce flow_delete çağırırsanız şemada ölü bağ kalır.",
|
|
411
415
|
inputSchema: { project: projectParam, environment: environmentParam, host: hostParam, applicationId: guid, hostId: guid, flowId: flowIdParam },
|
|
412
416
|
annotations: destructive
|
|
413
417
|
}, handle(config, async ({ project, environment, host, applicationId, hostId, flowId }) => {
|
|
414
|
-
|
|
415
|
-
await platform.tenant('DELETE', project, flowPath(host, applicationId, hostId, flowId), { environment, body: { id: flowId, ...envelope } });
|
|
418
|
+
await platform.tenant('DELETE', project, flowPath(host, applicationId, hostId, flowId), { environment, body: { id: flowId } });
|
|
416
419
|
return { deleted: flowId, host, hostId };
|
|
417
420
|
}));
|
|
418
421
|
}
|
package/dist/tools/layouts.js
CHANGED
|
@@ -2,7 +2,7 @@ import { guid, projectParam, environmentParam, pagingParams, readOnly, writes, u
|
|
|
2
2
|
import { resolvePatchOperations } from '../knowledge/outlines.js';
|
|
3
3
|
import { patchResult, baseVersionOf } from '../platform/patch.js';
|
|
4
4
|
import fastJsonPatch from 'fast-json-patch';
|
|
5
|
-
import { normalizeComponentDefaults, componentDefaultsNote, flexSizeWarnings, verticalGapWarnings, withNormalization } from '../knowledge/normalize.js';
|
|
5
|
+
import { normalizeComponentDefaults, componentDefaultsNote, flexSizeWarnings, spacingLayerWarnings, verticalGapWarnings, withNormalization } from '../knowledge/normalize.js';
|
|
6
6
|
import { fetchHost, layoutUpdateBody, schemaParam, eventsParam, modeParam, summarize, findNode } from './screens.js';
|
|
7
7
|
import { assertScreenWriteGuards, screenCatalogNotes } from './screenWrite.js';
|
|
8
8
|
import { applyPropTypesToSchema, isSetPropTypeOp, setPropTypeErrors } from '../knowledge/propTypes.js';
|
|
@@ -12,7 +12,7 @@ import { handle } from '../platform/responses.js';
|
|
|
12
12
|
import { z } from 'zod';
|
|
13
13
|
const patchOperationsParam = z.array(z.record(z.unknown())).min(1)
|
|
14
14
|
.describe("JSON Patch listesi (RFC 6902): { op, path, value }. Yol seçici alabilir — '/views/0/children[elementId=baslik]/props/content/data'.");
|
|
15
|
-
const viewsParam = schemaParam.describe("Layout'un komponent ağacı. DİKKAT: layout'ta şema alanının adı 'schema' değil 'views'tir
|
|
15
|
+
const viewsParam = schemaParam.describe("Layout'un komponent ağacı. DİKKAT: layout'ta şema alanının adı 'schema' değil 'views'tir; ağaçta hedefli değişiklik için tam ağaç yerine layout_schema_patch micro-op'larını kullanın. İçinde MUTLAKA bir { type: 'slot' } komponenti olmalı — sayfa içeriği YALNIZ slot'un içine render edilir, slot'suz layout'a bağlanan sayfalar boş görünür. 2026-09-08'den beri views, page_schema_patch'in doğrulama duvarından geçer: tanınmayan prop adı ve geçersiz enum değeri 422 ile REDDEDİLİR (kabul edilen değer listesiyle) ve hiçbir şey kaydedilmez — eskiden sessizce kaydediliyordu (P1-2).");
|
|
16
16
|
function countSlots(nodes) {
|
|
17
17
|
if (!Array.isArray(nodes))
|
|
18
18
|
return 0;
|
|
@@ -23,7 +23,7 @@ function countSlots(nodes) {
|
|
|
23
23
|
return total + (record.type === 'slot' ? 1 : 0) + countSlots(record.children);
|
|
24
24
|
}, 0);
|
|
25
25
|
}
|
|
26
|
-
function slotWarning(views) {
|
|
26
|
+
export function slotWarning(views) {
|
|
27
27
|
const slots = countSlots(views);
|
|
28
28
|
if (slots === 0) {
|
|
29
29
|
return ["LAY-002: layout'ta 'slot' tipli komponent YOK — Studio ve runtime, sayfa şemasını yalnız layout'taki slot'un içine yerleştirir (page.mappers: layout varsa render şeması layout views'üdür); bu layout'a bağlanan her sayfanın içeriği görünmez olur. views'e bir { type: 'slot' } komponenti ekleyin ve page_state.layoutSlots ile doğrulayın."];
|
|
@@ -49,7 +49,7 @@ export function registerLayoutTools(server, platform) {
|
|
|
49
49
|
}, handle(config, ({ project, environment, applicationId, id }) => platform.tenant('GET', project, `/layouts/${applicationId}/${id}`, { environment })));
|
|
50
50
|
server.registerTool('layout_schema_get', {
|
|
51
51
|
title: "Layout komponent ağacını oku",
|
|
52
|
-
description: "Layout'un komponent ağacını (views) okur — page_schema_get'in layout karşılığı.
|
|
52
|
+
description: "Layout'un komponent ağacını (views) okur — page_schema_get'in layout karşılığı. Ağaçta hedefli değişiklik için layout_schema_patch (sayfa ile aynı micro-op sözlüğü, PATCH /layouts/{app}/{id}/schema). Ad/parametre/olay alanlarında ya da düz JSON Patch yolu gerektiğinde layout_patch — o araç buradaki updatedAt'i expectedUpdatedAt olarak kabul eder. Tam ağacı kendiniz yazacaksanız layout_update.",
|
|
53
53
|
inputSchema: {
|
|
54
54
|
project: projectParam,
|
|
55
55
|
environment: environmentParam,
|
|
@@ -93,7 +93,7 @@ export function registerLayoutTools(server, platform) {
|
|
|
93
93
|
assertScreenWriteGuards('layout', { schema: views, events });
|
|
94
94
|
const fixed = normalizeComponentDefaults(views);
|
|
95
95
|
const catalogNotes = await screenCatalogNotes(platform, project, environment, applicationId, views);
|
|
96
|
-
const gaps = [...verticalGapWarnings(views ?? [], 'LAY-003 (uyarı)'), ...flexSizeWarnings(views ?? [], 'LAY-007 (uyarı)', 'LAY-008 (uyarı)')];
|
|
96
|
+
const gaps = [...verticalGapWarnings(views ?? [], 'LAY-003 (uyarı)'), ...flexSizeWarnings(views ?? [], 'LAY-007 (uyarı)', 'LAY-008 (uyarı)'), ...spacingLayerWarnings(views ?? [], 'LAY-010 (uyarı)', 'LAY-011 (uyarı)')];
|
|
97
97
|
const response = await platform.tenant('POST', project, `/layouts/${applicationId}`, {
|
|
98
98
|
environment,
|
|
99
99
|
body: { name, views: views ?? [], events: events ?? [], parameters: parameters ?? null }
|
|
@@ -126,7 +126,7 @@ export function registerLayoutTools(server, platform) {
|
|
|
126
126
|
const catalogNotes = await screenCatalogNotes(platform, project, environment, applicationId, overrides.views);
|
|
127
127
|
const body = layoutUpdateBody({ ...current, applicationId }, overrides);
|
|
128
128
|
await platform.tenant('PUT', project, `/layouts/${applicationId}/${id}`, { environment, body });
|
|
129
|
-
const gaps = overrides.views === undefined ? [] : [...verticalGapWarnings(body.views, 'LAY-003 (uyarı)'), ...flexSizeWarnings(body.views, 'LAY-007 (uyarı)', 'LAY-008 (uyarı)')];
|
|
129
|
+
const gaps = overrides.views === undefined ? [] : [...verticalGapWarnings(body.views, 'LAY-003 (uyarı)'), ...flexSizeWarnings(body.views, 'LAY-007 (uyarı)', 'LAY-008 (uyarı)'), ...spacingLayerWarnings(body.views, 'LAY-010 (uyarı)', 'LAY-011 (uyarı)')];
|
|
130
130
|
const summary = { id, changed: Object.keys(overrides), preserved: { viewNodes: body.views.length } };
|
|
131
131
|
if (gaps.length > 0)
|
|
132
132
|
summary.layoutWarnings = gaps;
|
|
@@ -134,7 +134,7 @@ export function registerLayoutTools(server, platform) {
|
|
|
134
134
|
}));
|
|
135
135
|
server.registerTool('layout_patch', {
|
|
136
136
|
title: "Layout'a patch uygula",
|
|
137
|
-
description: "
|
|
137
|
+
description: "RFC 6902 JSON Patch ile hedefli değişiklik: gateway layout'u çeker, JSON Patch'i ve kendi normalizasyonlarını uygular, doğrulamadan geçirir ve FARKI platformun PATCH /layouts/{app}/{id} ucuna `{ baseVersion, ops }` olarak yazar — tam gövde PUT'u ATILMAZ (09-04 Y-25). Ağaçta düğüm ekleme/silme/taşıma, prop, olay ve boyut değişikliği için önce layout_schema_patch'i düşünün: sayfa ile aynı micro-op sözlüğüdür ve dokunulan düğümleri platform doğrular; bu araç ad/parametre/olay alanları ve düz yol gerektiren durumlar içindir. Yol İNDEKS yerine SEÇİCİ alabilir: '/views/0/children[elementId=baslik]/props/content/data'. Sürüm kontrolü platformda: okunan kaydın `version` değeri `baseVersion` olarak gider, araya başka bir yazma girdiyse 409 döner ve HİÇBİR op uygulanmaz. expectedUpdatedAt verirseniz gateway ayrıca istek gitmeden önce yerel kontrol yapar. Ayrıca 'set_prop_type' micro-op'unu tanır ({target, prop, propType: 'static'|'code'|'translation', ref?, data?}); JSON Patch ile aynı listede karışık verilebilir, micro-op'lar önce uygulanır. Yalnız etiket çeviriye bağlanacaksa aynı op layout_schema_patch'te platformun kendi op'u olarak çalışır.",
|
|
138
138
|
inputSchema: {
|
|
139
139
|
project: projectParam,
|
|
140
140
|
environment: environmentParam,
|
|
@@ -193,7 +193,7 @@ export function registerLayoutTools(server, platform) {
|
|
|
193
193
|
body: { baseVersion: baseVersionOf(document, 'layout_get'), ops: netOps }
|
|
194
194
|
});
|
|
195
195
|
const written = patchResult(saved, finalDocument);
|
|
196
|
-
const gaps = [...verticalGapWarnings(body.views, 'LAY-003 (uyarı)'), ...flexSizeWarnings(body.views, 'LAY-007 (uyarı)', 'LAY-008 (uyarı)')];
|
|
196
|
+
const gaps = [...verticalGapWarnings(body.views, 'LAY-003 (uyarı)'), ...flexSizeWarnings(body.views, 'LAY-007 (uyarı)', 'LAY-008 (uyarı)'), ...spacingLayerWarnings(body.views, 'LAY-010 (uyarı)', 'LAY-011 (uyarı)')];
|
|
197
197
|
const summary = {
|
|
198
198
|
id,
|
|
199
199
|
applied: patchOps.length,
|