@appaflytech/zeyrek-ai-mcp 0.0.28 → 0.0.30

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.
Files changed (201) hide show
  1. package/.env.example +15 -0
  2. package/README.md +5 -5
  3. package/dist/config.js +37 -0
  4. package/dist/index.js +2 -0
  5. package/dist/knowledge/access.js +802 -0
  6. package/dist/knowledge/backendConstraints.js +18 -1
  7. package/dist/knowledge/case.js +41 -0
  8. package/dist/knowledge/componentCatalog.js +494 -34
  9. package/dist/knowledge/componentEvents.js +132 -7
  10. package/dist/knowledge/connectDataBind.js +819 -0
  11. package/dist/knowledge/connectDataDefinition.js +341 -0
  12. package/dist/knowledge/connectDataExecute.js +93 -0
  13. package/dist/knowledge/connectDataRules.js +128 -0
  14. package/dist/knowledge/decision.js +121 -0
  15. package/dist/knowledge/expressionPrelude.js +59 -0
  16. package/dist/knowledge/layoutSummary.js +140 -2
  17. package/dist/knowledge/microserviceParameters.js +58 -0
  18. package/dist/knowledge/mining.js +94 -0
  19. package/dist/knowledge/mobileComponentCatalog.js +859 -0
  20. package/dist/knowledge/mobileComponentEvents.js +239 -0
  21. package/dist/knowledge/normalize.js +236 -67
  22. package/dist/knowledge/outlines.js +36 -0
  23. package/dist/knowledge/platform/lint.js +385 -0
  24. package/dist/knowledge/platform/mobile.js +142 -0
  25. package/dist/knowledge/platform/mobileLayoutLint.js +324 -0
  26. package/dist/knowledge/platform/mobileRules.js +231 -0
  27. package/dist/knowledge/platform/mobileSpacing.js +82 -0
  28. package/dist/knowledge/platform/mobileTabs.js +108 -0
  29. package/dist/knowledge/platform/nativeBoxModel.js +44 -0
  30. package/dist/knowledge/platform/profile.js +25 -0
  31. package/dist/knowledge/platform/resolve.js +122 -0
  32. package/dist/knowledge/platform/web.js +39 -0
  33. package/dist/knowledge/policy.js +18 -4
  34. package/dist/knowledge/process.js +510 -0
  35. package/dist/knowledge/reservedTables.js +79 -0
  36. package/dist/knowledge/rowFilter.js +43 -0
  37. package/dist/knowledge/rules.js +319 -21
  38. package/dist/knowledge/schemaGuard.js +11 -0
  39. package/dist/knowledge/styleResolve.js +50 -4
  40. package/dist/knowledge/styleResolveNative.js +527 -0
  41. package/dist/knowledge/themeResolve.js +3 -3
  42. package/dist/observability/trace.js +6 -3
  43. package/dist/platform/argumentAliases.js +128 -0
  44. package/dist/platform/bodyFile.js +103 -0
  45. package/dist/platform/capture/actions.js +333 -0
  46. package/dist/platform/capture/browser.js +1 -0
  47. package/dist/platform/{screenshot.js → capture/capture.js} +105 -519
  48. package/dist/platform/capture/console-log.js +122 -0
  49. package/dist/platform/capture/index.js +11 -0
  50. package/dist/platform/capture/readiness.js +103 -0
  51. package/dist/platform/capture/summary.js +77 -0
  52. package/dist/platform/capture/target.js +5 -0
  53. package/dist/platform/capture/targets/studio-mobile.js +15 -0
  54. package/dist/platform/capture/targets/studio-web.js +5 -0
  55. package/dist/platform/diagnostics.js +10 -4
  56. package/dist/platform/domSummary.js +1 -1
  57. package/dist/platform/errors.js +162 -10
  58. package/dist/platform/http.js +29 -8
  59. package/dist/platform/impersonation.js +45 -0
  60. package/dist/platform/jsonArray.js +24 -0
  61. package/dist/platform/responses.js +39 -5
  62. package/dist/platform/schemaReadMemory.js +60 -0
  63. package/dist/platform/secrets.js +17 -1
  64. package/dist/platform/strictArguments.js +68 -12
  65. package/dist/platform/tokenVault.js +187 -4
  66. package/dist/resources/examples/bpm-gorev-kontrol.json +294 -0
  67. package/dist/resources/examples/bpm-iso-dokuman.json +228 -0
  68. package/dist/resources/examples/bpm-satinalma.json +376 -0
  69. package/dist/resources/examples/connect-data-convert-verify.json +107 -0
  70. package/dist/resources/examples/connect-data-dropdown-roles.json +66 -0
  71. package/dist/resources/examples/connect-data-edit-m2m.json +73 -0
  72. package/dist/resources/examples/connect-data-query-params.json +50 -0
  73. package/dist/resources/examples/connect-data-table-entity.json +147 -0
  74. package/dist/resources/examples/connect-data-workflow-microservice.json +65 -0
  75. package/dist/resources/examples/mobile-app-shell-drawer.json +243 -0
  76. package/dist/resources/examples/mobile-app-shell-stack.json +157 -0
  77. package/dist/resources/examples/mobile-app-shell-tab.json +208 -0
  78. package/dist/resources/examples/mobile-form-screen.json +365 -0
  79. package/dist/resources/examples/mobile-list-detail-form.json +672 -0
  80. package/dist/resources/examples/page-detail-profile.json +2 -1
  81. package/dist/resources/examples/page-dynamic-form.json +3 -2
  82. package/dist/resources/examples/page-flex-sections.json +1 -1
  83. package/dist/resources/examples/page-html-embed.json +1 -1
  84. package/dist/resources/examples/workflow-basic.json +8 -2
  85. package/dist/resources/guides/access.md +796 -0
  86. package/dist/resources/guides/bpm.md +686 -0
  87. package/dist/resources/guides/case.md +153 -0
  88. package/dist/resources/guides/component.md +91 -4
  89. package/dist/resources/guides/decision.md +185 -0
  90. package/dist/resources/guides/entity.md +50 -8
  91. package/dist/resources/guides/expressions.md +14 -5
  92. package/dist/resources/guides/functions.md +1 -1
  93. package/dist/resources/guides/getting-started.md +38 -1
  94. package/dist/resources/guides/layout.md +11 -7
  95. package/dist/resources/guides/microservice.md +81 -2
  96. package/dist/resources/guides/middleware.md +44 -2
  97. package/dist/resources/guides/mobile-layout.md +193 -0
  98. package/dist/resources/guides/mobile.md +495 -0
  99. package/dist/resources/guides/page.md +454 -75
  100. package/dist/resources/guides/theme.md +8 -2
  101. package/dist/resources/guides/translation.md +1 -1
  102. package/dist/resources/guides/workflow.md +58 -1
  103. package/dist/resources/read.js +41 -0
  104. package/dist/resources/rules.js +11 -5
  105. package/dist/resources/schema-fingerprint.json +7 -5
  106. package/dist/resources/schemas/AccessExplanationDto.json +144 -0
  107. package/dist/resources/schemas/AccessMatrixDto.json +170 -0
  108. package/dist/resources/schemas/AccessPermissionDto.json +57 -0
  109. package/dist/resources/schemas/AccessPolicyDto.json +223 -0
  110. package/dist/resources/schemas/AccessResourceDto.json +86 -0
  111. package/dist/resources/schemas/AppSessionDto.json +53 -0
  112. package/dist/resources/schemas/ConnectDataDescribeDto.json +344 -0
  113. package/dist/resources/schemas/ConnectDataRequestModel.json +202 -0
  114. package/dist/resources/schemas/ConnectDataResultDto.json +421 -0
  115. package/dist/resources/schemas/ConnectorCredentialDto.json +70 -0
  116. package/dist/resources/schemas/ConvertConnectDataToMicroserviceCommand.json +37 -0
  117. package/dist/resources/schemas/CreateAccessPolicyCommand.json +209 -0
  118. package/dist/resources/schemas/CreateDecisionCommand.json +221 -0
  119. package/dist/resources/schemas/CreateEntityCommand.json +118 -0
  120. package/dist/resources/schemas/CreateMicroserviceCommand.json +13 -1
  121. package/dist/resources/schemas/CreateProcessDefinitionCommand.json +1337 -0
  122. package/dist/resources/schemas/CreateQueryCommand.json +4 -0
  123. package/dist/resources/schemas/CreateWorkflowCommand.json +143 -1
  124. package/dist/resources/schemas/DataJobDto.json +6 -1
  125. package/dist/resources/schemas/DecisionDto.json +302 -0
  126. package/dist/resources/schemas/DetachConnectDataMicroserviceCommand.json +28 -0
  127. package/dist/resources/schemas/ExplainAccessQuery.json +33 -0
  128. package/dist/resources/schemas/GenerateProcessDocumentCommand.json +116 -0
  129. package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +21 -1
  130. package/dist/resources/schemas/MicroserviceDto.json +15 -3
  131. package/dist/resources/schemas/OrganizationProjectDto.json +335 -0
  132. package/dist/resources/schemas/OrganizationSchemaDto.json +196 -0
  133. package/dist/resources/schemas/OrganizationSchemaVersionDto.json +207 -0
  134. package/dist/resources/schemas/PatchProcessDefinitionCommand.json +76 -0
  135. package/dist/resources/schemas/PreviewMicroserviceCommand.json +10 -1
  136. package/dist/resources/schemas/PreviewWorkflowCommand.json +22 -1
  137. package/dist/resources/schemas/ProcessDefinitionDto.json +1480 -0
  138. package/dist/resources/schemas/ProcessSimulationDto.json +96 -0
  139. package/dist/resources/schemas/SaveConnectorCredentialCommand.json +90 -0
  140. package/dist/resources/schemas/SaveProcessEventSourceCommand.json +61 -0
  141. package/dist/resources/schemas/SaveProcessMailSourceCommand.json +89 -0
  142. package/dist/resources/schemas/SignProcessTaskCommand.json +73 -0
  143. package/dist/resources/schemas/SimulateProcessDefinitionQuery.json +92 -0
  144. package/dist/resources/schemas/StepDto.json +22 -1
  145. package/dist/resources/schemas/UpdateAccessPolicyCommand.json +209 -0
  146. package/dist/resources/schemas/UpdateDecisionCommand.json +216 -0
  147. package/dist/resources/schemas/UpdateEntityCommand.json +118 -0
  148. package/dist/resources/schemas/UpdateMicroserviceCommand.json +13 -1
  149. package/dist/resources/schemas/UpdateProcessDefinitionCommand.json +1357 -0
  150. package/dist/resources/schemas/UpdateQueryCommand.json +4 -0
  151. package/dist/resources/schemas/UpdateViewCommand.json +0 -2
  152. package/dist/resources/schemas/UpdateWorkflowCommand.json +143 -1
  153. package/dist/resources/schemas/ValidateProcessDefinitionQuery.json +1339 -0
  154. package/dist/server.js +27 -1
  155. package/dist/tools/access.js +369 -2
  156. package/dist/tools/accessOperations.js +135 -0
  157. package/dist/tools/accessPolicies.js +170 -0
  158. package/dist/tools/accessRuntime.js +203 -0
  159. package/dist/tools/applications.js +60 -3
  160. package/dist/tools/bpm.js +343 -0
  161. package/dist/tools/bpmGovernance.js +266 -0
  162. package/dist/tools/bpmOperations.js +230 -0
  163. package/dist/tools/bpmReporting.js +154 -0
  164. package/dist/tools/bpmRouting.js +150 -0
  165. package/dist/tools/bpmRuntime.js +396 -0
  166. package/dist/tools/case.js +178 -0
  167. package/dist/tools/caseRuntime.js +89 -0
  168. package/dist/tools/common.js +7 -0
  169. package/dist/tools/components.js +118 -14
  170. package/dist/tools/connectData.js +449 -0
  171. package/dist/tools/connectors.js +193 -0
  172. package/dist/tools/datasources.js +3 -3
  173. package/dist/tools/decisions.js +206 -0
  174. package/dist/tools/dependencies.js +1 -1
  175. package/dist/tools/deployments.js +2 -2
  176. package/dist/tools/designSchemaPatch.js +34 -9
  177. package/dist/tools/dtos.js +36 -5
  178. package/dist/tools/entities.js +79 -12
  179. package/dist/tools/externalComponents.js +26 -5
  180. package/dist/tools/flows.js +122 -14
  181. package/dist/tools/folders.js +1 -1
  182. package/dist/tools/imports.js +5 -2
  183. package/dist/tools/layouts.js +50 -17
  184. package/dist/tools/merges.js +1 -1
  185. package/dist/tools/microservices.js +77 -25
  186. package/dist/tools/mobile.js +221 -0
  187. package/dist/tools/modules.js +48 -0
  188. package/dist/tools/organizationStructure.js +137 -0
  189. package/dist/tools/pages.js +465 -98
  190. package/dist/tools/platformInfo.js +27 -8
  191. package/dist/tools/profileWrite.js +92 -0
  192. package/dist/tools/projects.js +71 -9
  193. package/dist/tools/rows.js +69 -13
  194. package/dist/tools/schemaOps.js +61 -1
  195. package/dist/tools/screenWrite.js +37 -8
  196. package/dist/tools/screens.js +95 -5
  197. package/dist/tools/templates.js +26 -1
  198. package/dist/tools/translations.js +1 -1
  199. package/dist/tools/variables.js +11 -5
  200. package/dist/tools/workflows.js +10 -5
  201. package/package.json +2 -2
@@ -0,0 +1,89 @@
1
+ import { guid, projectParam, environmentParam, pagingParams, readOnly, writes } from './common.js';
2
+ import { identityHeaders } from '../platform/tokenVault.js';
3
+ import { PlatformApiError } from '../platform/errors.js';
4
+ import { assertProcessNotProduction } from './bpm.js';
5
+ import { handle } from '../platform/responses.js';
6
+ import { z } from 'zod';
7
+ const asUserParam = z.string().min(1).optional()
8
+ .describe("Uygulama kullanıcısının kimliği (ham JWT ya da access_session_create'in tokenRefs'teki tok_… referansı). Vaka başlatan ve plan öğesini değiştiren bu kişi olur; verilmezse gateway'in kendi kullanıcısı.");
9
+ const expectFailureParam = z.boolean().optional()
10
+ .describe('true: bu çağrıda hata BEKLENİYOR (kasıtlı negatif test: sentry sağlanmadan enable 422). Ölçüm plansız hata saymaz.');
11
+ const planItemOperations = ['enable', 'start', 'complete', 'disable'];
12
+ const caseInstanceOperations = [...planItemOperations, 'add-discretionary', 'update-case-file'];
13
+ export function registerCaseRuntimeTools(server, platform) {
14
+ const config = platform.config;
15
+ server.registerTool('case_execute', {
16
+ title: 'Vaka başlat',
17
+ description: "Yayındaki vaka tanımından vaka başlatır (POST bpm/cases/{slug}/start): subjectRowId iş satırı, caseFile başlangıç değerleri (tanımdaki varsayılanların üstüne yazılır). Yanıt vaka + planItems + availableActions. process.start izni ister. İnsan görevleri görev kutusuna kind 'case-task' olarak düşer ve process_task_update ile tamamlanır. production hedefi durur (BPM-001).",
18
+ inputSchema: {
19
+ project: projectParam,
20
+ environment: environmentParam,
21
+ slug: z.string().min(1).max(100),
22
+ applicationId: guid.optional(),
23
+ subjectRowId: z.string().max(64).optional(),
24
+ caseFile: z.record(z.unknown()).optional().describe('vaka dosyası öğe id → değer'),
25
+ asUser: asUserParam
26
+ },
27
+ annotations: writes
28
+ }, handle(config, async ({ project, environment, slug, applicationId, subjectRowId, caseFile, asUser }) => {
29
+ assertProcessNotProduction('case_execute', environment, config);
30
+ return platform.tenant('POST', project, `/bpm/cases/${encodeURIComponent(slug)}/start`, {
31
+ environment,
32
+ body: { applicationId, subjectRowId, caseFile },
33
+ headers: identityHeaders(asUser, undefined, undefined)
34
+ });
35
+ }));
36
+ server.registerTool('case_instance_list', {
37
+ title: 'Vakaları listele',
38
+ description: "Vakaları listeler (GET bpm/case-instances; process.view-all ister): definitionId ve state (active | completed | terminated) süzgeci. Tek vakanın plan öğeleri, defteri ve availableActions için case_instance_get.",
39
+ inputSchema: {
40
+ project: projectParam,
41
+ environment: environmentParam,
42
+ definitionId: guid.optional(),
43
+ state: z.enum(['active', 'completed', 'terminated']).optional(),
44
+ ...pagingParams
45
+ },
46
+ annotations: readOnly
47
+ }, handle(config, ({ project, environment, ...query }) => platform.tenant('GET', project, '/bpm/case-instances', { environment, query })));
48
+ server.registerTool('case_instance_get', {
49
+ title: 'Vakayı getir',
50
+ description: "Vakayı getirir (GET bpm/case-instances/{id}): state, caseFile, planItems[] (id — eylemlerdeki planItemId budur —, itemId, type, state, occurrence, taskId), events[] (vaka defteri) ve availableActions[] { action: start | complete | disable | discretionary, itemId, planItemId }. Katılımcı (başlatan, atanan, tamamlayan) ya da process.view-all görür. case_instance_update'ten önce okuyun: planItemId planItems[].id ya da availableActions[].planItemId'dir.",
51
+ inputSchema: { project: projectParam, environment: environmentParam, id: guid, asUser: asUserParam },
52
+ annotations: readOnly
53
+ }, handle(config, ({ project, environment, id, asUser }) => platform.tenant('GET', project, `/bpm/case-instances/${id}`, { environment, headers: identityHeaders(asUser, undefined, undefined) })));
54
+ server.registerTool('case_instance_update', {
55
+ title: 'Vakada plan öğesi eylemi',
56
+ description: "Vaka eylemlerinin tek kapısı: operation enable | start | complete | disable (planItemId ZORUNLU: case_instance_get planItems[].id ya da availableActions[].planItemId — enable availableActions'ta hiç yoktur, kimliği planItems[].id'den okuyun; POST …/plan-items/{planItemId}/{operation}) | add-discretionary (itemDefinitionId: isteğe bağlı plan öğesinin tanımdaki id'si; POST …/discretionary) | update-case-file (itemId ve value ZORUNLU, silmek için value: null; PUT …/case-file — yerleşimi yeniden çalıştırır, ifPart'lar yeniden değerlendirilir). Hatalar: giriş sentry'si sağlanmadan enable 422 CaseSentryNotSatisfied (lint değil, çalışma zamanı: availableActions enable listelemez); yanlış durumdaki öğe ya da kapanmış vaka 409 InstanceStateTransitionNotAllowed; human-task görev ucundan (process_task_update) tamamlanır. production hedefi durur (BPM-001).",
57
+ inputSchema: {
58
+ project: projectParam,
59
+ environment: environmentParam,
60
+ id: guid,
61
+ operation: z.enum(caseInstanceOperations),
62
+ planItemId: guid.optional().describe('enable | start | complete | disable için case_instance_get planItems[].id (ya da availableActions[].planItemId)'),
63
+ itemDefinitionId: z.string().max(100).optional().describe('add-discretionary için tanımdaki plan öğesi id'),
64
+ itemId: z.string().max(100).optional().describe('update-case-file için vaka dosyası öğe id'),
65
+ value: z.unknown().optional().describe('update-case-file için yeni değer (herhangi bir JSON)'),
66
+ asUser: asUserParam,
67
+ expectFailure: expectFailureParam
68
+ },
69
+ annotations: writes
70
+ }, handle(config, async ({ project, environment, id, operation, planItemId, itemDefinitionId, itemId, value, asUser }) => {
71
+ assertProcessNotProduction('case_instance_update', environment, config);
72
+ const headers = identityHeaders(asUser, undefined, undefined);
73
+ if (operation === 'add-discretionary') {
74
+ if (!itemDefinitionId)
75
+ throw new PlatformApiError("case_instance_update: 'add-discretionary' itemDefinitionId ister (istek gönderilmedi).", 400);
76
+ return platform.tenant('POST', project, `/bpm/case-instances/${id}/discretionary`, { environment, body: { itemDefinitionId }, headers });
77
+ }
78
+ if (operation === 'update-case-file') {
79
+ if (!itemId)
80
+ throw new PlatformApiError("case_instance_update: 'update-case-file' itemId ister (istek gönderilmedi).", 400);
81
+ if (value === undefined)
82
+ throw new PlatformApiError("case_instance_update: 'update-case-file' value ister — verilmeyen değer öğeyi siler; silmek istiyorsanız value: null gönderin (istek gönderilmedi).", 400);
83
+ return platform.tenant('PUT', project, `/bpm/case-instances/${id}/case-file`, { environment, body: { itemId, value }, headers });
84
+ }
85
+ if (!planItemId)
86
+ throw new PlatformApiError(`case_instance_update: '${operation}' planItemId ister — case_instance_get planItems[].id ya da availableActions[].planItemId (istek gönderilmedi).`, 400);
87
+ return platform.tenant('POST', project, `/bpm/case-instances/${id}/plan-items/${planItemId}/${operation}`, { environment, headers });
88
+ }));
89
+ }
@@ -28,6 +28,13 @@ export const environmentParam = z.string().min(1).optional()
28
28
  .describe('Environment adı (X-Environment); boşsa DEFAULT_ENVIRONMENT kullanılır');
29
29
  export const languageParam = z.string().min(1).optional()
30
30
  .describe("İstek dili (ISO 639-1, ör. 'en'); X-Data-Language olarak gider. Çok dilli alanlar bu dilde okunur/yazılır, workflow'da context.language ve ham sorguda {{language}} bu değeri alır. Verilmezse platform Accept-Language'a, o da yoksa projenin varsayılan diline düşer. Bölgeli değer ('tr-TR') kabul edilir ve gateway indirger.");
31
+ /**
32
+ * 38/M-1: kompleks + enforce projede runtime araçları uygulama oturumu istiyordu ve oturum yalnız
33
+ * parolayla açılıyordu. Platform production dışında gateway'in kimliği doğrulanmış isteğine bu başlıkla
34
+ * özne kurar (`AppSessionMiddleware`); denetimler `platform/impersonation.ts`'tedir.
35
+ */
36
+ export const asUserIdParam = z.string().uuid().optional()
37
+ .describe("Parolasız kullanıcı gözü: users satır id'si (user_list). İstek gateway kimliğiyle ve 'impersonated-user-id' başlığıyla gider; platform özneyi bu kullanıcı olarak kurar — kompleks projede politika, satır kapsamı ve alan maskesi o kullanıcınındır, parola ve oturum gerekmez. Yalnız development ya da dal: production'da platform başlığı düşürür, runtime araçları isteği göndermeden reddeder. asUser ve anonymous ile birlikte verilemez; projede olmayan id reddedilir (platform onu sessizce yok sayıp gateway kimliğiyle yürütürdü).");
31
38
  export const definitionParam = z.record(z.unknown())
32
39
  .describe('API komut gövdesi birebir geçirilir; şablon için ilgili *_get çıktısını ya da ngapps://schemas kaynağını kullanın');
33
40
  /**
@@ -1,25 +1,81 @@
1
1
  import { guid, projectParam, environmentParam, readOnly, writes, updates, destructive } from './common.js';
2
- import { normalizeComponentDefaults, componentDefaultsNote, clampBlockSizes, blockSizeNote, normalizeHeightTypes, heightTypeNote, normalizeSizeStrings, sizeStringNote, withNormalization } from '../knowledge/normalize.js';
2
+ import { normalizeComponentDefaults, componentDefaultsNote, clampBlockSizes, blockSizeNote, normalizeHeightTypes, heightTypeNote, normalizeSizeStrings, sizeStringNote, normalizeDroppableStates, withNormalization } from '../knowledge/normalize.js';
3
3
  import { eventContractsFor, eventPayloadNote } from '../knowledge/componentEvents.js';
4
4
  import { componentPresetDefaults, readProjectTheme } from '../knowledge/themeSchema.js';
5
5
  import { knowledgeFor, knowledgeNote, APPEARANCE_TOKEN_SETS, STATE_FLAG_NOTES, INTERNAL_ROLES_BY_TYPE } from '../knowledge/componentCatalog.js';
6
+ import { MOBILE_STATE_FLAG_NOTES, mobileComponentKnowledge } from '../knowledge/mobileComponentCatalog.js';
7
+ import { mobileComponentEventContracts } from '../knowledge/mobileComponentEvents.js';
6
8
  import { componentUpdateBody, fetchHost, schemaParam, unwrap } from './screens.js';
7
9
  import { PlatformApiError } from '../platform/errors.js';
8
10
  import { handle } from '../platform/responses.js';
11
+ import { applicationTypeField, resolveProfile } from '../knowledge/platform/resolve.js';
12
+ import { mobileComponentNotes } from '../knowledge/platform/mobileRules.js';
13
+ import { randomUUID } from 'node:crypto';
9
14
  import { z } from 'zod';
10
- const typeParam = z.enum(['web', 'mobile']).optional().describe('Hedef platform; varsayılan web');
15
+ const typeParam = z.enum(['web', 'mobile']).optional().describe('Hedef platform (ComponentType); verilmezse uygulamanın tipi — mobil uygulamada mobile');
11
16
  const kindParam = z.enum(['component', 'widget']).optional()
12
17
  .describe("component: sayfaya konan tekil eleman. widget: kendi şeması olan kapsayıcı (container/modal/drawer)");
13
18
  const widgetTypeParam = z.enum(['container', 'modal', 'drawer']).optional()
14
19
  .describe("kind:'widget' iken zorunlu");
15
- async function listComponents(platform, project, environment, applicationId, scope) {
20
+ /**
21
+ * Uç `type` verilmezse WEB kataloğunu döner (`GetComponentsQuery` `Type ?? Web`); mobil uygulamanın
22
+ * paleti, doğrulayıcısı ve widget'ları `type=mobile` satırlarıdır. Profil mobil derse sorgu tipi
23
+ * taşır; web'de sorgu profil öncesiyle aynıdır (G1 kilidi).
24
+ */
25
+ export async function listComponents(platform, project, environment, applicationId, scope) {
16
26
  const path = scope === 'all' ? `/components/${applicationId}/all` : `/components/${applicationId}`;
27
+ const catalogType = scope === 'all' ? 'web' : (await resolveProfile(platform, applicationId)).profile.catalogType;
17
28
  const response = await platform.tenant('GET', project, path, {
18
29
  environment,
19
- query: scope === 'all' ? undefined : { pageIndex: 0, pageLength: 999 }
30
+ query: scope === 'all' ? undefined : { pageIndex: 0, pageLength: 999, ...(catalogType === 'mobile' ? { type: 'mobile' } : {}) }
20
31
  });
21
32
  return response?.data ?? [];
22
33
  }
34
+ /**
35
+ * CMP-002 (ARC-081) — runtime widget'ın kökünü yalnız `widget-area` (container) ya da `modal`/`drawer`
36
+ * tipinden tanır (`runtime-compose.ts` `getRuntimeWidgetRootNode`); düz `container` kökle kaydedilen
37
+ * widget her yüzeyde boş çizilir. Tipli kök yoksa düğümler Studio'nun `createWidgetRootNode`'u
38
+ * (`widget.functions.ts`) ile aynı şekilde bir köke sarılır: prop'lar uygulamanın kataloğundaki kök
39
+ * tipinin `definition.defaults`'ı, yükseklik `fixed`, kök bırakılabilir.
40
+ */
41
+ function wrapWidgetRoot(schema, widgetType, components) {
42
+ const rootType = widgetType === 'container' ? 'widget-area' : widgetType;
43
+ // Runtime istenen tipin kökü yoksa öteki tipli köklere de düşer (`legacyRoot()`); tip değiştiren
44
+ // güncellemenin eski kökü ikinci kez sarılmaz.
45
+ const hasRoot = schema.some(node => node?.kind === 'component' && ['widget-area', 'modal', 'drawer'].includes(String(node.type)));
46
+ if (hasRoot)
47
+ return { schema, notes: [] };
48
+ const definition = (components.find(component => component.slug === rootType)?.definition ?? {});
49
+ const desktopBlock = Array.isArray(definition.blocks)
50
+ ? definition.blocks.find(block => block?.breakpoint === 1024)
51
+ : undefined;
52
+ const elementId = `${rootType}${randomUUID().slice(0, 4)}`;
53
+ const root = {
54
+ id: randomUUID(),
55
+ elementId,
56
+ name: widgetType === 'container' ? 'container' : elementId,
57
+ widgetType,
58
+ kind: 'component',
59
+ type: rootType,
60
+ children: schema,
61
+ events: [],
62
+ props: { ...(definition.defaults ?? {}) },
63
+ blocks: desktopBlock ? [{ breakpoint: 1024, size: desktopBlock.size, position: { x: 0, y: 0 } }] : [],
64
+ validations: [],
65
+ appearance: { heightType: 'fixed' },
66
+ states: { isDroppable: true },
67
+ stateBindings: []
68
+ };
69
+ return {
70
+ schema: [root],
71
+ notes: [`CMP-002: widget şemasında '${rootType}' kökü yoktu; ${schema.length} düğüm '${elementId}' köküne sarıldı (Studio'nun kurduğu şekil). Runtime widget'ı yalnız widget-area/modal/drawer kökünden çizer.`]
72
+ };
73
+ }
74
+ /** Uygulamanın kayıtlı bileşen slug'ları (mobil profilin MOB-003 denetimi). */
75
+ export async function fetchCatalogSlugs(platform, project, environment, applicationId) {
76
+ const components = await listComponents(platform, project, environment, applicationId);
77
+ return new Set(components.map(component => String(component.slug ?? '')).filter(slug => slug.length > 0));
78
+ }
23
79
  /**
24
80
  * Yerleşim normalizasyonlarının ikisi de aynı katalog listesinden beslenir; tek okumada
25
81
  * çıkarılır ki yazma yolları fazladan istek atmasın. Uygulamanın kendi sözlüğü okunur
@@ -34,16 +90,33 @@ async function listComponents(platform, project, environment, applicationId, sco
34
90
  export async function fetchComponentLayoutRules(platform, project, environment, applicationId) {
35
91
  return componentLayoutRules(await listComponents(platform, project, environment, applicationId));
36
92
  }
93
+ /**
94
+ * Uygulamanın komponent sözlüğü, TEK okumada. Katalog gövdesi büyüktür (101 kayıt ≈ yüzlerce KB):
95
+ * hem TB-123 doğrulaması hem yerleşim normalizasyonu aynı listeden beslenir, iki istek atılmaz.
96
+ */
97
+ export async function fetchCatalogComponents(platform, project, environment, applicationId) {
98
+ return listComponents(platform, project, environment, applicationId);
99
+ }
100
+ /** Katalog listesi elde varken yerleşim kurallarını uygular (ikinci okuma yapmaz). */
101
+ export function applyCatalogLayoutRulesFrom(components, nodes) {
102
+ const rules = componentLayoutRules(components);
103
+ return { clamped: clampBlockSizes(nodes, rules.maxSizes), heights: normalizeHeightTypes(nodes, rules.autoHeights), sizes: normalizeSizeStrings(nodes), states: normalizeDroppableStates(nodes, rules.droppable) };
104
+ }
37
105
  /** Katalog listesini zaten okumuş çağıranlar (component_update) ikinci istek atmasın diye ayrı. */
38
106
  export function componentLayoutRules(components) {
39
107
  const maxSizes = new Map();
40
108
  const autoHeights = new Map();
109
+ const droppable = new Map();
41
110
  for (const component of components) {
42
111
  const slug = typeof component.slug === 'string' ? component.slug : undefined;
43
112
  if (!slug)
44
113
  continue;
45
114
  if (typeof component.isDefaultAutoHeight === 'boolean')
46
115
  autoHeights.set(slug, component.isDefaultAutoHeight);
116
+ // Kap bilgisi sözlükten gelir; düğümün `states.isDroppable`ı onu izler (Studio paleti de
117
+ // aynı alanı katalogdan yazar). `true` gören tip kap sayılır.
118
+ if (typeof component.isDroppable === 'boolean')
119
+ droppable.set(slug, component.isDroppable);
47
120
  const blocks = (component.definition ?? {}).blocks;
48
121
  if (!Array.isArray(blocks))
49
122
  continue;
@@ -58,7 +131,7 @@ export function componentLayoutRules(components) {
58
131
  });
59
132
  }
60
133
  }
61
- return { maxSizes, autoHeights };
134
+ return { maxSizes, autoHeights, droppable };
62
135
  }
63
136
  /**
64
137
  * Katalog okuması başarısız olsa da yazma isteği gitmeli, ama iki normalizasyonun düşüş davranışı
@@ -69,14 +142,21 @@ export function componentLayoutRules(components) {
69
142
  * varsayılanını (`fixed`, `DesignComponentManagementSchema.cs:24`) kabul etmek demektir; en fazla
70
143
  * sekiz tipte (auth-layout/html/image/layout/qrcode/table/text-editor/video) fazladan yükseklik
71
144
  * üretir, atlamak ise her tipte içerik kırpar.
145
+ * - `states.isDroppable` atlanır — katalog okunamadığında hangi tipin kap olduğu bilinmez ve
146
+ * uydurulmaz; düğüm bugünkü hâliyle yazılır.
72
147
  */
73
148
  export async function applyCatalogLayoutRules(platform, project, environment, applicationId, nodes) {
74
149
  try {
75
150
  const rules = await fetchComponentLayoutRules(platform, project, environment, applicationId);
76
- return { clamped: clampBlockSizes(nodes, rules.maxSizes), heights: normalizeHeightTypes(nodes, rules.autoHeights), sizes: normalizeSizeStrings(nodes) };
151
+ return {
152
+ clamped: clampBlockSizes(nodes, rules.maxSizes),
153
+ heights: normalizeHeightTypes(nodes, rules.autoHeights),
154
+ sizes: normalizeSizeStrings(nodes),
155
+ states: normalizeDroppableStates(nodes, rules.droppable)
156
+ };
77
157
  }
78
158
  catch {
79
- return { clamped: [], heights: normalizeHeightTypes(nodes, new Map()), sizes: normalizeSizeStrings(nodes) };
159
+ return { clamped: [], heights: normalizeHeightTypes(nodes, new Map()), sizes: normalizeSizeStrings(nodes), states: [] };
80
160
  }
81
161
  }
82
162
  /**
@@ -116,6 +196,7 @@ export function registerComponentTools(server, platform) {
116
196
  }, handle(config, async ({ project, environment, applicationId, scope, includeHidden }) => {
117
197
  const components = await listComponents(platform, project, environment, applicationId, scope);
118
198
  return {
199
+ ...applicationTypeField(await resolveProfile(platform, applicationId)),
119
200
  components: components
120
201
  .filter(component => includeHidden === true || component.isHide !== true)
121
202
  .map(component => ({
@@ -161,6 +242,15 @@ export function registerComponentTools(server, platform) {
161
242
  : [];
162
243
  const componentSlug = typeof component.slug === 'string' ? component.slug : undefined;
163
244
  const knowledge = knowledgeFor(componentSlug);
245
+ // Mobil uygulamada kayıt mobil kataloğun satırıdır (`listComponents` type=mobile); davranış
246
+ // notları web runtime'ından gelir (`knowledge` — mobil şema web sınıfını genişletir), bileşenin
247
+ // mobil farkları `mobileKnowledge`'ta, bütün mobil bileşenlere geçen notlar `mobileNotes`'ta (G4).
248
+ // Web ikizi olmayan bileşende (`app-bar`, `tooltip`…) bilgi yalnız `mobileKnowledge`'tadır; olay
249
+ // yükleri de önce mobil sözlükten okunur (`mobileComponentEvents.ts`).
250
+ const mobile = (await resolveProfile(platform, applicationId)).profile.platform === 'mobile';
251
+ const mobileKnowledge = mobile && componentSlug !== undefined && Object.hasOwn(mobileComponentKnowledge, componentSlug)
252
+ ? mobileComponentKnowledge[componentSlug]
253
+ : undefined;
164
254
  // S-3 — `defaults` HAM katalogdur; Studio'da bırakılan düğüm ise temanın bileşen preseti
165
255
  // kaplanmış katalogdan kurulur (`withThemeComponentDefaults`). Tema okunamazsa (uç düşer,
166
256
  // yetki yoksa) alan yanıta HİÇ girmez: uydurulmuş bir varsayılan yanlış bilgidir.
@@ -177,7 +267,7 @@ export function registerComponentTools(server, platform) {
177
267
  isDroppable: component.isDroppable,
178
268
  props: definition.props,
179
269
  defaults: definition.defaults,
180
- events: eventContractsFor(componentSlug, eventNames),
270
+ events: eventContractsFor(componentSlug, eventNames, mobile ? mobileComponentEventContracts : undefined),
181
271
  eventPayloadNote,
182
272
  ...(knowledge
183
273
  ? {
@@ -188,7 +278,7 @@ export function registerComponentTools(server, platform) {
188
278
  },
189
279
  ...(knowledge.guide ? { guide: knowledge.guide } : {})
190
280
  }
191
- : { knowledgeNote }),
281
+ : mobileKnowledge ? {} : { knowledgeNote }),
192
282
  ...(componentSlug && INTERNAL_ROLES_BY_TYPE[componentSlug]
193
283
  ? {
194
284
  internalRoles: INTERNAL_ROLES_BY_TYPE[componentSlug],
@@ -196,10 +286,12 @@ export function registerComponentTools(server, platform) {
196
286
  }
197
287
  : {}),
198
288
  ...(themeDefaults ? { themeDefaults } : {}),
289
+ ...(mobile ? { platform: 'mobile', ...(mobileKnowledge ? { mobileKnowledge } : {}), mobileNotes: mobileComponentNotes(componentSlug) } : {}),
199
290
  appearanceValues: APPEARANCE_TOKEN_SETS,
200
- stateFlags: STATE_FLAG_NOTES,
291
+ stateFlags: mobile ? { ...STATE_FLAG_NOTES, ...MOBILE_STATE_FLAG_NOTES } : STATE_FLAG_NOTES,
201
292
  validations: definition.validations,
202
- sizes: definition.blocks
293
+ sizes: definition.blocks,
294
+ ...(definition.connectData ? { connectData: definition.connectData } : { connectDataNote: "Bu komponentin veri kaynağına bağlanabilir prop kaydı yok (ya da katalog henüz eşitlenmedi): connect_data_bind bu tipte CD-001 döner." })
203
295
  };
204
296
  }));
205
297
  server.registerTool('component_create', {
@@ -230,21 +322,27 @@ export function registerComponentTools(server, platform) {
230
322
  if (body.kind === 'widget' && !body.widgetType) {
231
323
  throw new PlatformApiError("kind:'widget' için widgetType (container | modal | drawer) zorunludur.");
232
324
  }
325
+ const wrapped = body.kind === 'widget' && body.widgetType && (body.schema ?? []).length > 0
326
+ ? wrapWidgetRoot(body.schema ?? [], body.widgetType, await listComponents(platform, project, environment, applicationId).catch(() => []))
327
+ : { schema: body.schema, notes: [] };
328
+ body.schema = wrapped.schema;
233
329
  const fixed = normalizeComponentDefaults(body.schema);
234
330
  const catalog = (body.schema ?? []).length > 0
235
331
  ? await applyCatalogLayoutRules(platform, project, environment, applicationId, body.schema)
236
332
  : { clamped: [], heights: [], sizes: [] };
333
+ // Mobil uygulamanın widget'ı mobil katalog satırıdır; tip verilmezse uygulamanın tipi.
334
+ const defaultType = body.type ?? (await resolveProfile(platform, applicationId)).profile.catalogType;
237
335
  return platform.tenant('POST', project, `/components/${applicationId}`, {
238
336
  environment,
239
337
  body: {
240
338
  kind: 'component',
241
- type: 'web',
339
+ type: defaultType,
242
340
  categories: [],
243
341
  definition: {},
244
342
  schema: [],
245
343
  ...Object.fromEntries(Object.entries(body).filter(([, value]) => value !== undefined))
246
344
  }
247
- }).then(response => withNormalization(response, [...componentDefaultsNote(fixed), ...blockSizeNote(catalog.clamped), ...heightTypeNote(catalog.heights), ...sizeStringNote(catalog.sizes)]));
345
+ }).then(response => withNormalization(response, [...wrapped.notes, ...componentDefaultsNote(fixed), ...blockSizeNote(catalog.clamped), ...heightTypeNote(catalog.heights), ...sizeStringNote(catalog.sizes)]));
248
346
  }));
249
347
  server.registerTool('component_update', {
250
348
  title: 'Komponent güncelle',
@@ -279,6 +377,12 @@ export function registerComponentTools(server, platform) {
279
377
  ? await fetchHost(platform, 'component', project, environment, applicationId, String(current.id))
280
378
  : current;
281
379
  const overrides = Object.fromEntries(Object.entries(changes).filter(([, value]) => value !== undefined));
380
+ const widgetType = changes.widgetType ?? detailed.widgetType;
381
+ const wrapped = detailed.kind === 'widget' && typeof widgetType === 'string' && changes.schema !== undefined && changes.schema.length > 0
382
+ ? wrapWidgetRoot(changes.schema, widgetType, components)
383
+ : { schema: changes.schema, notes: [] };
384
+ if (overrides.schema !== undefined)
385
+ overrides.schema = wrapped.schema;
282
386
  const fixed = normalizeComponentDefaults(overrides.schema);
283
387
  const rules = componentLayoutRules(components);
284
388
  const clamped = overrides.schema === undefined ? [] : clampBlockSizes(overrides.schema, rules.maxSizes);
@@ -286,7 +390,7 @@ export function registerComponentTools(server, platform) {
286
390
  const sizes = overrides.schema === undefined ? [] : normalizeSizeStrings(overrides.schema);
287
391
  const body = componentUpdateBody({ ...detailed, applicationId }, overrides);
288
392
  await platform.tenant('PUT', project, `/components/${applicationId}/${slug}`, { environment, body });
289
- return withNormalization({ slug, changed: Object.keys(overrides), preserved: { schemaNodes: body.schema.length } }, [...componentDefaultsNote(fixed), ...blockSizeNote(clamped), ...heightTypeNote(heights), ...sizeStringNote(sizes)]);
393
+ return withNormalization({ slug, changed: Object.keys(overrides), preserved: { schemaNodes: body.schema.length } }, [...wrapped.notes, ...componentDefaultsNote(fixed), ...blockSizeNote(clamped), ...heightTypeNote(heights), ...sizeStringNote(sizes)]);
290
394
  }));
291
395
  server.registerTool('component_delete', {
292
396
  title: 'Komponent sil',