@appaflytech/zeyrek-ai-mcp 0.0.30 → 0.0.32
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 +0 -15
- package/README.md +5 -5
- package/dist/config.js +0 -37
- package/dist/index.js +0 -2
- package/dist/knowledge/backendConstraints.js +1 -18
- package/dist/knowledge/boxSections.js +184 -0
- package/dist/knowledge/componentCatalog.js +232 -562
- package/dist/knowledge/componentEvents.js +21 -141
- package/dist/knowledge/layoutSummary.js +2 -140
- package/dist/knowledge/normalize.js +67 -236
- package/dist/knowledge/outlines.js +0 -36
- package/dist/knowledge/policy.js +4 -18
- package/dist/knowledge/reservedTables.js +0 -79
- package/dist/knowledge/rules.js +21 -319
- package/dist/knowledge/schemaGuard.js +0 -11
- package/dist/knowledge/styleResolve.js +38 -55
- package/dist/knowledge/themeResolve.js +3 -3
- package/dist/observability/trace.js +3 -6
- package/dist/platform/diagnostics.js +4 -10
- package/dist/platform/domSummary.js +1 -1
- package/dist/platform/errors.js +10 -162
- package/dist/platform/http.js +8 -29
- package/dist/platform/responses.js +5 -39
- package/dist/platform/{capture/capture.js → screenshot.js} +519 -105
- package/dist/platform/secrets.js +1 -17
- package/dist/platform/strictArguments.js +12 -68
- package/dist/platform/tokenVault.js +4 -187
- package/dist/resources/examples/layout-app-shell.json +707 -229
- package/dist/resources/examples/page-detail-profile.json +1 -2
- package/dist/resources/examples/page-dynamic-form.json +2 -3
- package/dist/resources/examples/page-flex-sections.json +1 -1
- package/dist/resources/examples/page-html-embed.json +1 -1
- package/dist/resources/examples/workflow-basic.json +2 -8
- package/dist/resources/guides/component.md +4 -91
- package/dist/resources/guides/entity.md +8 -50
- package/dist/resources/guides/expressions.md +5 -14
- package/dist/resources/guides/functions.md +1 -1
- package/dist/resources/guides/getting-started.md +1 -38
- package/dist/resources/guides/layout.md +58 -55
- package/dist/resources/guides/microservice.md +2 -81
- package/dist/resources/guides/middleware.md +2 -44
- package/dist/resources/guides/page.md +75 -454
- package/dist/resources/guides/theme.md +2 -8
- package/dist/resources/guides/translation.md +1 -1
- package/dist/resources/guides/workflow.md +1 -58
- package/dist/resources/rules.js +5 -11
- package/dist/resources/schema-fingerprint.json +5 -7
- package/dist/resources/schemas/CreateEntityCommand.json +0 -118
- package/dist/resources/schemas/CreateMicroserviceCommand.json +1 -13
- package/dist/resources/schemas/CreateQueryCommand.json +0 -4
- package/dist/resources/schemas/CreateWorkflowCommand.json +1 -143
- package/dist/resources/schemas/DataJobDto.json +1 -6
- package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +1 -21
- package/dist/resources/schemas/MicroserviceDto.json +3 -15
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +1 -10
- package/dist/resources/schemas/PreviewWorkflowCommand.json +1 -22
- package/dist/resources/schemas/StepDto.json +1 -22
- package/dist/resources/schemas/UpdateEntityCommand.json +0 -118
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +1 -13
- package/dist/resources/schemas/UpdateQueryCommand.json +0 -4
- package/dist/resources/schemas/UpdateViewCommand.json +2 -0
- package/dist/resources/schemas/UpdateWorkflowCommand.json +1 -143
- package/dist/server.js +1 -27
- package/dist/tools/access.js +2 -369
- package/dist/tools/applications.js +3 -60
- package/dist/tools/common.js +0 -7
- package/dist/tools/components.js +14 -118
- package/dist/tools/datasources.js +3 -3
- package/dist/tools/dependencies.js +1 -1
- package/dist/tools/deployments.js +2 -2
- package/dist/tools/designSchemaPatch.js +18 -34
- package/dist/tools/dtos.js +5 -36
- package/dist/tools/entities.js +12 -79
- package/dist/tools/externalComponents.js +5 -26
- package/dist/tools/flows.js +14 -122
- package/dist/tools/folders.js +1 -1
- package/dist/tools/imports.js +2 -5
- package/dist/tools/layouts.js +17 -50
- package/dist/tools/merges.js +1 -1
- package/dist/tools/microservices.js +25 -77
- package/dist/tools/pages.js +112 -465
- package/dist/tools/platformInfo.js +8 -27
- package/dist/tools/projects.js +9 -71
- package/dist/tools/rows.js +13 -69
- package/dist/tools/schemaOps.js +1 -61
- package/dist/tools/screenWrite.js +8 -37
- package/dist/tools/screens.js +5 -95
- package/dist/tools/templates.js +1 -26
- package/dist/tools/translations.js +1 -1
- package/dist/tools/variables.js +5 -11
- package/dist/tools/workflows.js +5 -10
- package/package.json +2 -2
- package/dist/knowledge/access.js +0 -802
- package/dist/knowledge/case.js +0 -41
- package/dist/knowledge/connectDataBind.js +0 -819
- package/dist/knowledge/connectDataDefinition.js +0 -341
- package/dist/knowledge/connectDataExecute.js +0 -93
- package/dist/knowledge/connectDataRules.js +0 -128
- package/dist/knowledge/decision.js +0 -121
- package/dist/knowledge/expressionPrelude.js +0 -59
- package/dist/knowledge/microserviceParameters.js +0 -58
- package/dist/knowledge/mining.js +0 -94
- package/dist/knowledge/mobileComponentCatalog.js +0 -859
- package/dist/knowledge/mobileComponentEvents.js +0 -239
- package/dist/knowledge/platform/lint.js +0 -385
- package/dist/knowledge/platform/mobile.js +0 -142
- package/dist/knowledge/platform/mobileLayoutLint.js +0 -324
- package/dist/knowledge/platform/mobileRules.js +0 -231
- package/dist/knowledge/platform/mobileSpacing.js +0 -82
- package/dist/knowledge/platform/mobileTabs.js +0 -108
- package/dist/knowledge/platform/nativeBoxModel.js +0 -44
- package/dist/knowledge/platform/profile.js +0 -25
- package/dist/knowledge/platform/resolve.js +0 -122
- package/dist/knowledge/platform/web.js +0 -39
- package/dist/knowledge/process.js +0 -510
- package/dist/knowledge/rowFilter.js +0 -43
- package/dist/knowledge/styleResolveNative.js +0 -527
- package/dist/platform/argumentAliases.js +0 -128
- package/dist/platform/bodyFile.js +0 -103
- package/dist/platform/capture/actions.js +0 -333
- package/dist/platform/capture/browser.js +0 -1
- package/dist/platform/capture/console-log.js +0 -122
- package/dist/platform/capture/index.js +0 -11
- package/dist/platform/capture/readiness.js +0 -103
- package/dist/platform/capture/summary.js +0 -77
- package/dist/platform/capture/target.js +0 -5
- package/dist/platform/capture/targets/studio-mobile.js +0 -15
- package/dist/platform/capture/targets/studio-web.js +0 -5
- package/dist/platform/impersonation.js +0 -45
- package/dist/platform/jsonArray.js +0 -24
- package/dist/platform/schemaReadMemory.js +0 -60
- package/dist/resources/examples/bpm-gorev-kontrol.json +0 -294
- package/dist/resources/examples/bpm-iso-dokuman.json +0 -228
- package/dist/resources/examples/bpm-satinalma.json +0 -376
- package/dist/resources/examples/connect-data-convert-verify.json +0 -107
- package/dist/resources/examples/connect-data-dropdown-roles.json +0 -66
- package/dist/resources/examples/connect-data-edit-m2m.json +0 -73
- package/dist/resources/examples/connect-data-query-params.json +0 -50
- package/dist/resources/examples/connect-data-table-entity.json +0 -147
- package/dist/resources/examples/connect-data-workflow-microservice.json +0 -65
- package/dist/resources/examples/mobile-app-shell-drawer.json +0 -243
- package/dist/resources/examples/mobile-app-shell-stack.json +0 -157
- package/dist/resources/examples/mobile-app-shell-tab.json +0 -208
- package/dist/resources/examples/mobile-form-screen.json +0 -365
- package/dist/resources/examples/mobile-list-detail-form.json +0 -672
- package/dist/resources/guides/access.md +0 -796
- package/dist/resources/guides/bpm.md +0 -686
- package/dist/resources/guides/case.md +0 -153
- package/dist/resources/guides/decision.md +0 -185
- package/dist/resources/guides/mobile-layout.md +0 -193
- package/dist/resources/guides/mobile.md +0 -495
- package/dist/resources/read.js +0 -41
- package/dist/resources/schemas/AccessExplanationDto.json +0 -144
- package/dist/resources/schemas/AccessMatrixDto.json +0 -170
- package/dist/resources/schemas/AccessPermissionDto.json +0 -57
- package/dist/resources/schemas/AccessPolicyDto.json +0 -223
- package/dist/resources/schemas/AccessResourceDto.json +0 -86
- package/dist/resources/schemas/AppSessionDto.json +0 -53
- package/dist/resources/schemas/ConnectDataDescribeDto.json +0 -344
- package/dist/resources/schemas/ConnectDataRequestModel.json +0 -202
- package/dist/resources/schemas/ConnectDataResultDto.json +0 -421
- package/dist/resources/schemas/ConnectorCredentialDto.json +0 -70
- package/dist/resources/schemas/ConvertConnectDataToMicroserviceCommand.json +0 -37
- package/dist/resources/schemas/CreateAccessPolicyCommand.json +0 -209
- package/dist/resources/schemas/CreateDecisionCommand.json +0 -221
- package/dist/resources/schemas/CreateProcessDefinitionCommand.json +0 -1337
- package/dist/resources/schemas/DecisionDto.json +0 -302
- package/dist/resources/schemas/DetachConnectDataMicroserviceCommand.json +0 -28
- package/dist/resources/schemas/ExplainAccessQuery.json +0 -33
- package/dist/resources/schemas/GenerateProcessDocumentCommand.json +0 -116
- package/dist/resources/schemas/OrganizationProjectDto.json +0 -335
- package/dist/resources/schemas/OrganizationSchemaDto.json +0 -196
- package/dist/resources/schemas/OrganizationSchemaVersionDto.json +0 -207
- package/dist/resources/schemas/PatchProcessDefinitionCommand.json +0 -76
- package/dist/resources/schemas/ProcessDefinitionDto.json +0 -1480
- package/dist/resources/schemas/ProcessSimulationDto.json +0 -96
- package/dist/resources/schemas/SaveConnectorCredentialCommand.json +0 -90
- package/dist/resources/schemas/SaveProcessEventSourceCommand.json +0 -61
- package/dist/resources/schemas/SaveProcessMailSourceCommand.json +0 -89
- package/dist/resources/schemas/SignProcessTaskCommand.json +0 -73
- package/dist/resources/schemas/SimulateProcessDefinitionQuery.json +0 -92
- package/dist/resources/schemas/UpdateAccessPolicyCommand.json +0 -209
- package/dist/resources/schemas/UpdateDecisionCommand.json +0 -216
- package/dist/resources/schemas/UpdateProcessDefinitionCommand.json +0 -1357
- package/dist/resources/schemas/ValidateProcessDefinitionQuery.json +0 -1339
- package/dist/tools/accessOperations.js +0 -135
- package/dist/tools/accessPolicies.js +0 -170
- package/dist/tools/accessRuntime.js +0 -203
- package/dist/tools/bpm.js +0 -343
- package/dist/tools/bpmGovernance.js +0 -266
- package/dist/tools/bpmOperations.js +0 -230
- package/dist/tools/bpmReporting.js +0 -154
- package/dist/tools/bpmRouting.js +0 -150
- package/dist/tools/bpmRuntime.js +0 -396
- package/dist/tools/case.js +0 -178
- package/dist/tools/caseRuntime.js +0 -89
- package/dist/tools/connectData.js +0 -449
- package/dist/tools/connectors.js +0 -193
- package/dist/tools/decisions.js +0 -206
- package/dist/tools/mobile.js +0 -221
- package/dist/tools/modules.js +0 -48
- package/dist/tools/organizationStructure.js +0 -137
- package/dist/tools/profileWrite.js +0 -92
|
@@ -1,527 +0,0 @@
|
|
|
1
|
-
import { TRANSFORM_RANGES, rawProp, resolveNodeStyleLayers, transformValue } from './styleResolve.js';
|
|
2
|
-
import { mergeTypeScale, resolveTheme } from './themeResolve.js';
|
|
3
|
-
/* ---- css-value.ts ---- */
|
|
4
|
-
const warn = (context, message) => {
|
|
5
|
-
context?.warnings?.push(message);
|
|
6
|
-
return null;
|
|
7
|
-
};
|
|
8
|
-
export function parseLength(value, context) {
|
|
9
|
-
if (value === undefined || value === null || value === '')
|
|
10
|
-
return null;
|
|
11
|
-
if (typeof value === 'number')
|
|
12
|
-
return Number.isFinite(value) ? value : null;
|
|
13
|
-
const text = String(value).trim();
|
|
14
|
-
if (!text)
|
|
15
|
-
return null;
|
|
16
|
-
const numeric = Number(text);
|
|
17
|
-
if (Number.isFinite(numeric))
|
|
18
|
-
return numeric;
|
|
19
|
-
if (text.endsWith('%')) {
|
|
20
|
-
const percent = Number(text.slice(0, -1));
|
|
21
|
-
return Number.isFinite(percent) ? `${percent}%` : null;
|
|
22
|
-
}
|
|
23
|
-
const unit = /^(-?[\d.]+)(px|em|rem)$/.exec(text);
|
|
24
|
-
if (unit) {
|
|
25
|
-
const amount = Number(unit[1]);
|
|
26
|
-
if (!Number.isFinite(amount))
|
|
27
|
-
return null;
|
|
28
|
-
if (unit[2] === 'px')
|
|
29
|
-
return amount;
|
|
30
|
-
const base = unit[2] === 'em' ? context?.base ?? context?.root : context?.root;
|
|
31
|
-
if (base === undefined)
|
|
32
|
-
return warn(context, `${text}: em/rem tabanı yok, değer atlandı`);
|
|
33
|
-
return Math.round(amount * base * 1000) / 1000;
|
|
34
|
-
}
|
|
35
|
-
return warn(context, `${text}: React Native'de karşılığı olmayan uzunluk`);
|
|
36
|
-
}
|
|
37
|
-
export function parsePanelLength(value, context) {
|
|
38
|
-
if (typeof value === 'number' && value === 0)
|
|
39
|
-
return null;
|
|
40
|
-
return parseLength(value, context);
|
|
41
|
-
}
|
|
42
|
-
export function parseFontFamily(value) {
|
|
43
|
-
if (value === undefined || value === null || value === '')
|
|
44
|
-
return null;
|
|
45
|
-
const first = String(value).split(',')[0].trim().replace(/^["']|["']$/g, '');
|
|
46
|
-
return first || null;
|
|
47
|
-
}
|
|
48
|
-
const GENERIC_FONT_FAMILIES = new Set([
|
|
49
|
-
'serif', 'sans-serif', 'monospace', 'cursive', 'fantasy', 'system-ui',
|
|
50
|
-
'ui-serif', 'ui-sans-serif', 'ui-monospace', 'ui-rounded', 'emoji', 'math', 'fangsong'
|
|
51
|
-
]);
|
|
52
|
-
/** CSS generik ailesi mi (`sans-serif`, `monospace`…) — tırnaklanırsa aile adı sanılır. */
|
|
53
|
-
export function isGenericFontFamily(name) {
|
|
54
|
-
return GENERIC_FONT_FAMILIES.has(name.trim().toLowerCase());
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Yığının yedek generiği: son generik ad, yoksa `sans-serif`. Temanın yığını `"Figtree",
|
|
58
|
-
* sans-serif` biçimindedir; tek ad yazılan `typographyStyle` yedeğini buradan miras alır (ZM-10).
|
|
59
|
-
*/
|
|
60
|
-
export function fontFallback(stack) {
|
|
61
|
-
const generic = String(stack ?? '').split(',').map(part => part.trim().replace(/^["']|["']$/g, '')).filter(isGenericFontFamily).pop();
|
|
62
|
-
return generic ?? 'sans-serif';
|
|
63
|
-
}
|
|
64
|
-
/** Yığının yalın ilk adı (tırnaksız); yükleyicinin istediği ad budur (ZM-10, f-05). */
|
|
65
|
-
export function firstFontFamily(value) {
|
|
66
|
-
return parseFontFamily(value) ?? '';
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Font adı platforma göre çözülür (ZM-10, K3). Frontend'de bu WEB/cihaz diye ikiye ayrılır
|
|
70
|
-
* (`font-family.ts` / `font-family.native.ts`, Metro `.native`'i seçer) ama bu ayna TEK koldur:
|
|
71
|
-
* `test/style-resolve-native.test.ts` frontend'in `theme-native.ts`'ini düz Node `import()` ile
|
|
72
|
-
* okur ve Node/Vite çözümü platform uzantısını (`.native.ts`) hiç görmez — parite testinin
|
|
73
|
-
* kıyasladığı gerçek davranış bu yüzden HER ZAMAN web kolu (`font-family.ts`); cihazdaki yalın-ad
|
|
74
|
-
* davranışı yalnız Metro bundle'ında oluşur ve bu aynanın kapsamı dışındadır (g-02 parity fix).
|
|
75
|
-
* Tek ad generik yedeksiz kalırsa RN web'de font yüklenemediğinde tarayıcı varsayılanı (Times)
|
|
76
|
-
* çizilir; bu yüzden tek ad tırnaklanıp temanın generiğiyle yığına çevrilir, yazarın kendi yığını
|
|
77
|
-
* (virgüllü) aynen geçer.
|
|
78
|
-
*/
|
|
79
|
-
export function resolveFontFamily(value, fallback) {
|
|
80
|
-
const text = value.trim();
|
|
81
|
-
if (text === '' || text.includes(','))
|
|
82
|
-
return text;
|
|
83
|
-
const name = firstFontFamily(text);
|
|
84
|
-
if (isGenericFontFamily(name))
|
|
85
|
-
return name;
|
|
86
|
-
return `"${name}", ${fallback}`;
|
|
87
|
-
}
|
|
88
|
-
export function parseLineHeight(value, fontSize, context) {
|
|
89
|
-
if (value === undefined || value === null || value === '')
|
|
90
|
-
return null;
|
|
91
|
-
const text = String(value).trim();
|
|
92
|
-
const numeric = Number(text);
|
|
93
|
-
const base = fontSize ?? context?.base ?? context?.root;
|
|
94
|
-
if (Number.isFinite(numeric)) {
|
|
95
|
-
if (numeric <= 0)
|
|
96
|
-
return null;
|
|
97
|
-
const ratio = numeric >= 4 ? numeric / 100 : numeric;
|
|
98
|
-
if (base === undefined)
|
|
99
|
-
return warn(context, `lineHeight ${text}: punto bilinmiyor, atlandı`);
|
|
100
|
-
return Math.round(ratio * base * 1000) / 1000;
|
|
101
|
-
}
|
|
102
|
-
if (text.endsWith('%')) {
|
|
103
|
-
const percent = Number(text.slice(0, -1));
|
|
104
|
-
if (!Number.isFinite(percent) || base === undefined)
|
|
105
|
-
return warn(context, `lineHeight ${text}: punto bilinmiyor, atlandı`);
|
|
106
|
-
return Math.round((percent / 100) * base * 1000) / 1000;
|
|
107
|
-
}
|
|
108
|
-
const length = parseLength(text, context);
|
|
109
|
-
return typeof length === 'number' ? length : null;
|
|
110
|
-
}
|
|
111
|
-
export function parseOpacity(value) {
|
|
112
|
-
if (value === undefined || value === null || value === '')
|
|
113
|
-
return null;
|
|
114
|
-
const amount = Number(value);
|
|
115
|
-
if (!Number.isFinite(amount) || amount < 0 || amount >= 100)
|
|
116
|
-
return null;
|
|
117
|
-
return Math.round((amount / 100) * 1000) / 1000;
|
|
118
|
-
}
|
|
119
|
-
export function parseBorderShorthand(value, context) {
|
|
120
|
-
if (value === undefined || value === null || value === '')
|
|
121
|
-
return null;
|
|
122
|
-
const text = String(value).trim();
|
|
123
|
-
if (!text || text === 'none')
|
|
124
|
-
return { width: 0, style: 'solid' };
|
|
125
|
-
const parts = text.split(/\s+(?![^(]*\))/);
|
|
126
|
-
const width = parseLength(parts[0], context);
|
|
127
|
-
if (typeof width !== 'number')
|
|
128
|
-
return warn(context, `${text}: kenarlık genişliği çözülemedi`);
|
|
129
|
-
const style = parts.find(part => /^(solid|dashed|dotted)$/.test(part)) ?? 'solid';
|
|
130
|
-
const color = parts.find(part => part !== parts[0] && !/^(solid|dashed|dotted)$/.test(part));
|
|
131
|
-
return { width, style, ...(color ? { color } : {}) };
|
|
132
|
-
}
|
|
133
|
-
/* ---- theme-native.ts ---- */
|
|
134
|
-
const camelize = (name) => name.replace(/^--ng-/, '').replace(/-([a-z0-9])/g, (_, character) => character.toUpperCase());
|
|
135
|
-
const hexToRgb = (hex) => {
|
|
136
|
-
const match = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());
|
|
137
|
-
if (!match)
|
|
138
|
-
return null;
|
|
139
|
-
const digits = match[1].length === 3 ? match[1].split('').map(digit => digit + digit).join('') : match[1];
|
|
140
|
-
const value = parseInt(digits, 16);
|
|
141
|
-
return [(value >> 16) & 255, (value >> 8) & 255, value & 255];
|
|
142
|
-
};
|
|
143
|
-
const toHex = (channel) => Math.round(Math.max(0, Math.min(255, channel))).toString(16).padStart(2, '0');
|
|
144
|
-
const NAMED_COLORS = { white: '#ffffff', black: '#000000' };
|
|
145
|
-
const resolveColorMix = (value) => {
|
|
146
|
-
const match = /^color-mix\(\s*in\s+srgb\s*,\s*([^,]+?)\s+([\d.]+)%\s*,\s*([^)]+?)\s*\)$/i.exec(value.trim());
|
|
147
|
-
if (!match)
|
|
148
|
-
return value;
|
|
149
|
-
const [, rawFrom = '', percent = '0', rawTo = ''] = match;
|
|
150
|
-
const from = hexToRgb(NAMED_COLORS[rawFrom.trim()] ?? rawFrom);
|
|
151
|
-
const to = hexToRgb(NAMED_COLORS[rawTo.trim()] ?? rawTo);
|
|
152
|
-
if (!from || !to)
|
|
153
|
-
return rawFrom.trim();
|
|
154
|
-
const weight = Number(percent) / 100;
|
|
155
|
-
const mixed = from.map((channel, index) => channel * weight + to[index] * (1 - weight));
|
|
156
|
-
return `#${mixed.map(toHex).join('')}`;
|
|
157
|
-
};
|
|
158
|
-
const CALC_UNIT = /^(-?[\d.]+)([a-z%]*)$/;
|
|
159
|
-
const evaluateCalc = (value) => {
|
|
160
|
-
let result = value;
|
|
161
|
-
while (true) {
|
|
162
|
-
const match = /calc\(([^()]*)\)/.exec(result);
|
|
163
|
-
if (!match)
|
|
164
|
-
return result;
|
|
165
|
-
const [left, operator = '', right] = match[1].trim().split(/\s+/);
|
|
166
|
-
const leftParts = CALC_UNIT.exec(left ?? '');
|
|
167
|
-
const rightAmount = Number(right);
|
|
168
|
-
if (!leftParts || !Number.isFinite(rightAmount) || !'*/'.includes(operator)) {
|
|
169
|
-
result = result.replace(match[0], match[1].trim());
|
|
170
|
-
return result;
|
|
171
|
-
}
|
|
172
|
-
const amount = operator === '*' ? Number(leftParts[1]) * rightAmount : Number(leftParts[1]) / rightAmount;
|
|
173
|
-
result = result.replace(match[0], `${Math.round(amount * 1000) / 1000}${leftParts[2]}`);
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
const resolveVars = (raw) => {
|
|
177
|
-
const resolved = {};
|
|
178
|
-
const expand = (value, seen) => {
|
|
179
|
-
const expanded = value.replace(/var\((--[a-z0-9-]+)(?:\s*,\s*([^)]+))?\)/g, (whole, name, fallback) => {
|
|
180
|
-
if (seen.has(name))
|
|
181
|
-
return whole;
|
|
182
|
-
const target = raw[name];
|
|
183
|
-
if (target === undefined)
|
|
184
|
-
return fallback?.trim() ?? whole;
|
|
185
|
-
return expand(target, new Set([...seen, name]));
|
|
186
|
-
});
|
|
187
|
-
return resolveColorMix(evaluateCalc(expanded));
|
|
188
|
-
};
|
|
189
|
-
for (const [name, value] of Object.entries(raw))
|
|
190
|
-
resolved[name] = expand(value, new Set([name]));
|
|
191
|
-
return resolved;
|
|
192
|
-
};
|
|
193
|
-
const px = (value, fallback) => {
|
|
194
|
-
if (!value)
|
|
195
|
-
return fallback;
|
|
196
|
-
const amount = Number(String(value).replace(/px$/, ''));
|
|
197
|
-
return Number.isFinite(amount) ? amount : fallback;
|
|
198
|
-
};
|
|
199
|
-
export function parseShadow(css) {
|
|
200
|
-
if (!css || css === 'none')
|
|
201
|
-
return {};
|
|
202
|
-
const color = /rgba?\(([^)]+)\)/.exec(css);
|
|
203
|
-
const lengths = css.replace(/rgba?\([^)]+\)/, '').trim().split(/\s+/)
|
|
204
|
-
.map(part => Number(part.replace(/px$/, '')))
|
|
205
|
-
.filter(part => Number.isFinite(part));
|
|
206
|
-
const [offsetX = 0, offsetY = 0, blur = 0] = lengths;
|
|
207
|
-
const channels = color?.[1].split(',').map(part => Number(part.trim())) ?? [];
|
|
208
|
-
const [red = 0, green = 0, blue = 0, alpha = 1] = channels;
|
|
209
|
-
return {
|
|
210
|
-
shadowColor: `#${toHex(red)}${toHex(green)}${toHex(blue)}`,
|
|
211
|
-
shadowOffset: { width: offsetX, height: offsetY },
|
|
212
|
-
shadowOpacity: alpha,
|
|
213
|
-
shadowRadius: blur,
|
|
214
|
-
elevation: Math.round(blur / 2)
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Proje temasının mobil karşılığı. Frontend `resolveThemeNative(overrides, mode = 'light')` ile
|
|
219
|
-
* aynı: mod çağırandan gelir, temanın kendi `mode` alanı okunmaz (runtime da okumuyor).
|
|
220
|
-
*/
|
|
221
|
-
export function resolveThemeNative(theme, mode = 'light') {
|
|
222
|
-
const resolvedTheme = resolveTheme(theme, mode);
|
|
223
|
-
const vars = resolveVars(resolvedTheme.cssVars);
|
|
224
|
-
const tokens = resolvedTheme.tokens;
|
|
225
|
-
const colors = {};
|
|
226
|
-
for (const [name, value] of Object.entries(vars)) {
|
|
227
|
-
if (/^(#|rgb|hsl)/.test(value))
|
|
228
|
-
colors[camelize(name)] = value;
|
|
229
|
-
}
|
|
230
|
-
const fontSize = px(vars['--ng-font-size'], 14);
|
|
231
|
-
const spacingBase = px(vars['--ng-spacing'], 10);
|
|
232
|
-
const spacing = { base: spacingBase };
|
|
233
|
-
for (const [name, value] of Object.entries(vars)) {
|
|
234
|
-
const level = /^--ng-spacing-([a-z]+)$/.exec(name);
|
|
235
|
-
if (level)
|
|
236
|
-
spacing[level[1]] = px(value, spacingBase);
|
|
237
|
-
}
|
|
238
|
-
const scale = {};
|
|
239
|
-
for (const level of Object.keys(mergeTypeScale(tokens.typeScale))) {
|
|
240
|
-
scale[level] = px(vars[`--ng-font-size-${level}`], fontSize);
|
|
241
|
-
const narrow = vars[`--ng-font-size-${level}-mobile`];
|
|
242
|
-
if (narrow)
|
|
243
|
-
scale[`${level}Mobile`] = px(narrow, fontSize);
|
|
244
|
-
}
|
|
245
|
-
const bodyStack = vars['--ng-font'] ?? tokens.fontFamily;
|
|
246
|
-
const headingStack = vars['--ng-font-heading'] ?? bodyStack;
|
|
247
|
-
const fallback = fontFallback(bodyStack);
|
|
248
|
-
return {
|
|
249
|
-
mode,
|
|
250
|
-
vars,
|
|
251
|
-
colors,
|
|
252
|
-
spacing,
|
|
253
|
-
radius: {
|
|
254
|
-
sm: px(vars['--ng-radius-sm'], 2),
|
|
255
|
-
md: px(vars['--ng-radius-md'], 4),
|
|
256
|
-
lg: px(vars['--ng-radius-lg'], 12),
|
|
257
|
-
pill: px(vars['--ng-radius-pill'], 999)
|
|
258
|
-
},
|
|
259
|
-
font: {
|
|
260
|
-
family: resolveFontFamily(bodyStack, fallback),
|
|
261
|
-
headingFamily: resolveFontFamily(headingStack, fallback),
|
|
262
|
-
source: firstFontFamily(bodyStack),
|
|
263
|
-
headingSource: firstFontFamily(headingStack),
|
|
264
|
-
fallback,
|
|
265
|
-
size: fontSize,
|
|
266
|
-
weight: vars['--ng-font-weight'] ?? tokens.fontWeight,
|
|
267
|
-
scale
|
|
268
|
-
},
|
|
269
|
-
shadow: {
|
|
270
|
-
none: {},
|
|
271
|
-
sm: parseShadow(vars['--ng-shadow-sm']),
|
|
272
|
-
md: parseShadow(vars['--ng-shadow-md']),
|
|
273
|
-
lg: parseShadow(vars['--ng-shadow-lg'])
|
|
274
|
-
}
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
/* ---- compose-native-style.ts ---- */
|
|
278
|
-
const TEXT_KEYS = new Set(['color', 'fontFamily', 'fontSize', 'fontStyle', 'fontWeight', 'letterSpacing', 'lineHeight', 'textAlign', 'textDecorationLine', 'textTransform']);
|
|
279
|
-
const RENAMED_KEYS = { background: 'backgroundColor', textDecoration: 'textDecorationLine' };
|
|
280
|
-
const IGNORED_KEYS = new Set(['boxShadow', 'transition', 'cursor', 'boxSizing', 'whiteSpace', 'wordBreak', 'textOverflow', 'backdropFilter', 'filter']);
|
|
281
|
-
const isPlainObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
282
|
-
const isSet = (value) => value !== undefined && value !== null && value !== '' && !(typeof value === 'string' && value.includes('{{'));
|
|
283
|
-
export function resolveThemeToken(value, theme) {
|
|
284
|
-
return value.replace(/var\((--[a-z0-9-]+)(?:\s*,\s*([^)]+))?\)/g, (whole, name, fallback) => theme.vars[name] ?? fallback?.trim() ?? whole);
|
|
285
|
-
}
|
|
286
|
-
const UNRESOLVED_TOKEN = /var\(\s*(--[a-z0-9-]+)\s*\)/;
|
|
287
|
-
/** Frontend `compose-native-style.ts` `asText` aynası: çözülemeyen yedeksiz jeton yazılmaz, uyarıya düşer (K37-c). */
|
|
288
|
-
const asText = (value, theme, warnings, field) => {
|
|
289
|
-
if (!isSet(value))
|
|
290
|
-
return undefined;
|
|
291
|
-
const resolved = resolveThemeToken(String(value), theme);
|
|
292
|
-
const unresolved = UNRESOLVED_TOKEN.exec(resolved);
|
|
293
|
-
if (!unresolved)
|
|
294
|
-
return resolved;
|
|
295
|
-
warnings?.push(`${field ?? 'değer'}: tanımsız tema jetonu ${unresolved[1]}, atlandı`);
|
|
296
|
-
return undefined;
|
|
297
|
-
};
|
|
298
|
-
const composeRadius = (value, shell, theme, context) => {
|
|
299
|
-
if (!isSet(value))
|
|
300
|
-
return;
|
|
301
|
-
const preset = theme.radius[String(value)];
|
|
302
|
-
if (preset !== undefined) {
|
|
303
|
-
shell.borderRadius = preset;
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
const parts = resolveThemeToken(String(value), theme).trim().split(/\s+/);
|
|
307
|
-
if (parts.length === 1) {
|
|
308
|
-
const radius = parsePanelLength(parts[0], context);
|
|
309
|
-
if (typeof radius === 'number')
|
|
310
|
-
shell.borderRadius = radius;
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
const corners = ['borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius'];
|
|
314
|
-
corners.forEach((corner, index) => {
|
|
315
|
-
const radius = parseLength(parts[index] ?? parts[index % parts.length], context);
|
|
316
|
-
if (typeof radius === 'number')
|
|
317
|
-
shell[corner] = radius;
|
|
318
|
-
});
|
|
319
|
-
};
|
|
320
|
-
const composeBorders = (surface, shell, theme, context) => {
|
|
321
|
-
const sides = [
|
|
322
|
-
['borderTop', 'borderTopWidth', 'borderTopColor'],
|
|
323
|
-
['borderRight', 'borderRightWidth', 'borderRightColor'],
|
|
324
|
-
['borderBottom', 'borderBottomWidth', 'borderBottomColor'],
|
|
325
|
-
['borderLeft', 'borderLeftWidth', 'borderLeftColor']
|
|
326
|
-
];
|
|
327
|
-
let wrote = false;
|
|
328
|
-
for (const [field, widthKey, colorKey] of sides) {
|
|
329
|
-
if (!isSet(surface[field]))
|
|
330
|
-
continue;
|
|
331
|
-
const border = parseBorderShorthand(resolveThemeToken(String(surface[field]), theme), context);
|
|
332
|
-
if (!border)
|
|
333
|
-
continue;
|
|
334
|
-
wrote = true;
|
|
335
|
-
shell[widthKey] = border.width;
|
|
336
|
-
if (border.color)
|
|
337
|
-
shell[colorKey] = border.color;
|
|
338
|
-
if (border.style !== 'solid' && !shell.borderStyle)
|
|
339
|
-
shell.borderStyle = border.style;
|
|
340
|
-
}
|
|
341
|
-
if (wrote)
|
|
342
|
-
return;
|
|
343
|
-
const width = Number(surface.borderWidth);
|
|
344
|
-
const color = asText(surface.borderColor, theme, context.warnings, 'surfaceStyle.borderColor');
|
|
345
|
-
const style = asText(surface.borderStyle, theme);
|
|
346
|
-
if (Number.isFinite(width) && isSet(surface.borderWidth)) {
|
|
347
|
-
shell.borderWidth = width;
|
|
348
|
-
if (width > 0) {
|
|
349
|
-
shell.borderColor = color ?? theme.colors.borderPrimary;
|
|
350
|
-
if (style && style !== 'solid')
|
|
351
|
-
shell.borderStyle = style;
|
|
352
|
-
}
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
if (color || style) {
|
|
356
|
-
shell.borderWidth = 1;
|
|
357
|
-
shell.borderColor = color ?? theme.colors.borderPrimary;
|
|
358
|
-
if (style && style !== 'solid')
|
|
359
|
-
shell.borderStyle = style;
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
/** Yüzey grubunun bilinen alanları; kalanı uyarıya yazılır (frontend `SURFACE_KEYS`). MOB-002 de buradan okur. */
|
|
363
|
-
export const SURFACE_KEYS = new Set([
|
|
364
|
-
'background',
|
|
365
|
-
'radius',
|
|
366
|
-
'borderTop',
|
|
367
|
-
'borderRight',
|
|
368
|
-
'borderBottom',
|
|
369
|
-
'borderLeft',
|
|
370
|
-
'shadow',
|
|
371
|
-
'contentOverflow',
|
|
372
|
-
'opacity',
|
|
373
|
-
'rotate',
|
|
374
|
-
'scale',
|
|
375
|
-
'translateX',
|
|
376
|
-
'translateY',
|
|
377
|
-
'borderWidth',
|
|
378
|
-
'borderStyle',
|
|
379
|
-
'borderColor'
|
|
380
|
-
]);
|
|
381
|
-
/**
|
|
382
|
-
* Döndür / ölçekle / kaydır (ADR 0005): web ile aynı sıra ve aralık, RN dizisi. Dolu ama geçersiz
|
|
383
|
-
* değer (birimli metin, aralık dışı) uyarıya yazılır — frontend `composeTransform`.
|
|
384
|
-
*/
|
|
385
|
-
const composeTransform = (surface, shell, warnings) => {
|
|
386
|
-
const read = (field) => {
|
|
387
|
-
const raw = surface[field];
|
|
388
|
-
if (!isSet(raw))
|
|
389
|
-
return undefined;
|
|
390
|
-
const value = transformValue(raw, field);
|
|
391
|
-
if (value === undefined) {
|
|
392
|
-
const [min, max] = TRANSFORM_RANGES[field];
|
|
393
|
-
warnings?.push(`surfaceStyle.${field}: ${String(raw)} geçersiz — ${min}…${max} arası sayı, atlandı`);
|
|
394
|
-
}
|
|
395
|
-
return value;
|
|
396
|
-
};
|
|
397
|
-
const transform = [];
|
|
398
|
-
const x = read('translateX') ?? 0;
|
|
399
|
-
const y = read('translateY') ?? 0;
|
|
400
|
-
if (x !== 0 || y !== 0)
|
|
401
|
-
transform.push({ translateX: x }, { translateY: y });
|
|
402
|
-
const rotate = read('rotate');
|
|
403
|
-
if (rotate !== undefined && rotate !== 0)
|
|
404
|
-
transform.push({ rotate: `${rotate}deg` });
|
|
405
|
-
const scale = read('scale');
|
|
406
|
-
if (scale !== undefined && scale !== 100)
|
|
407
|
-
transform.push({ scale: scale / 100 });
|
|
408
|
-
if (transform.length)
|
|
409
|
-
shell.transform = transform;
|
|
410
|
-
};
|
|
411
|
-
const composeSurface = (surface, shell, theme, context) => {
|
|
412
|
-
const background = asText(surface.background, theme, context.warnings, 'surfaceStyle.background');
|
|
413
|
-
if (background)
|
|
414
|
-
shell.backgroundColor = background;
|
|
415
|
-
composeRadius(surface.radius, shell, theme, context);
|
|
416
|
-
composeBorders(surface, shell, theme, context);
|
|
417
|
-
if (isSet(surface.shadow) && isSet(surface.background) && !background) {
|
|
418
|
-
context.warnings?.push('surfaceStyle.shadow: zemin çözülemedi, gölge çocuklara düşerdi — atlandı');
|
|
419
|
-
}
|
|
420
|
-
else if (isSet(surface.shadow)) {
|
|
421
|
-
const raw = String(surface.shadow);
|
|
422
|
-
const key = raw;
|
|
423
|
-
if (!theme.shadow[key] && (raw.includes(',') || raw.includes('inset'))) {
|
|
424
|
-
context.warnings?.push(`shadow: RN tek katman taşır, ilk katman uygulandı (${raw})`);
|
|
425
|
-
}
|
|
426
|
-
Object.assign(shell, theme.shadow[key] ?? parseShadow(resolveThemeToken(raw, theme)));
|
|
427
|
-
}
|
|
428
|
-
const opacity = parseOpacity(surface.opacity);
|
|
429
|
-
if (opacity !== null)
|
|
430
|
-
shell.opacity = opacity;
|
|
431
|
-
if (isSet(surface.contentOverflow)) {
|
|
432
|
-
const overflow = String(surface.contentOverflow);
|
|
433
|
-
shell.overflow = overflow === 'visible' ? 'visible' : 'hidden';
|
|
434
|
-
if (overflow === 'auto')
|
|
435
|
-
context.warnings?.push('contentOverflow: auto — RN kaydırmayı bileşenin kendisi açar, kutu hidden yapıldı');
|
|
436
|
-
}
|
|
437
|
-
composeTransform(surface, shell, context.warnings);
|
|
438
|
-
for (const [key, value] of Object.entries(surface)) {
|
|
439
|
-
if (!SURFACE_KEYS.has(key) && isSet(value))
|
|
440
|
-
context.warnings?.push(`surfaceStyle.${key}: mobilde karşılığı yok, atlandı`);
|
|
441
|
-
}
|
|
442
|
-
};
|
|
443
|
-
const composeTypography = (typography, text, theme, context) => {
|
|
444
|
-
const color = asText(typography.textColor, theme, context.warnings, 'typographyStyle.textColor');
|
|
445
|
-
if (color)
|
|
446
|
-
text.color = color;
|
|
447
|
-
const family = resolveFontFamily(asText(typography.fontFamily, theme) ?? '', theme.font.fallback);
|
|
448
|
-
if (family)
|
|
449
|
-
text.fontFamily = family;
|
|
450
|
-
const fontSize = parsePanelLength(typeof typography.fontSize === 'string' ? resolveThemeToken(typography.fontSize, theme) : typography.fontSize, context);
|
|
451
|
-
if (typeof fontSize === 'number')
|
|
452
|
-
text.fontSize = fontSize;
|
|
453
|
-
if (isSet(typography.fontWeight))
|
|
454
|
-
text.fontWeight = String(typography.fontWeight);
|
|
455
|
-
if (isSet(typography.fontStyle))
|
|
456
|
-
text.fontStyle = String(typography.fontStyle);
|
|
457
|
-
if (isSet(typography.textDecoration))
|
|
458
|
-
text.textDecorationLine = String(typography.textDecoration);
|
|
459
|
-
if (isSet(typography.textAlign))
|
|
460
|
-
text.textAlign = String(typography.textAlign);
|
|
461
|
-
const letterSpacing = parsePanelLength(typography.letterSpacing, context);
|
|
462
|
-
if (typeof letterSpacing === 'number')
|
|
463
|
-
text.letterSpacing = letterSpacing;
|
|
464
|
-
const lineHeight = parseLineHeight(typography.lineHeight, text.fontSize ?? context.base, context);
|
|
465
|
-
if (lineHeight !== null)
|
|
466
|
-
text.lineHeight = lineHeight;
|
|
467
|
-
};
|
|
468
|
-
const composeFreeStyle = (value, shell, text, theme, context) => {
|
|
469
|
-
if (!isPlainObject(value))
|
|
470
|
-
return;
|
|
471
|
-
for (const [rawKey, rawValue] of Object.entries(value)) {
|
|
472
|
-
if (!isSet(rawValue))
|
|
473
|
-
continue;
|
|
474
|
-
if (rawKey.startsWith('&') || rawKey.startsWith('--') || rawKey.startsWith(':')) {
|
|
475
|
-
context.warnings?.push(`${rawKey}: RN'de alt seçici yok, atlandı`);
|
|
476
|
-
continue;
|
|
477
|
-
}
|
|
478
|
-
const key = RENAMED_KEYS[rawKey] ?? rawKey;
|
|
479
|
-
if (IGNORED_KEYS.has(key))
|
|
480
|
-
continue;
|
|
481
|
-
const target = TEXT_KEYS.has(key) ? text : shell;
|
|
482
|
-
const resolved = typeof rawValue === 'string' ? resolveThemeToken(rawValue, theme) : rawValue;
|
|
483
|
-
if (typeof resolved === 'number') {
|
|
484
|
-
target[key] = resolved;
|
|
485
|
-
continue;
|
|
486
|
-
}
|
|
487
|
-
const length = key === 'fontWeight' || typeof resolved !== 'string' ? null : parseLength(resolved, { ...context, warnings: undefined });
|
|
488
|
-
target[key] = length ?? resolved;
|
|
489
|
-
}
|
|
490
|
-
};
|
|
491
|
-
export function composeNativeStyle(input, theme) {
|
|
492
|
-
const warnings = [];
|
|
493
|
-
const shell = {};
|
|
494
|
-
const text = {};
|
|
495
|
-
const context = { base: theme.font.size, root: theme.font.size, warnings };
|
|
496
|
-
composeFreeStyle(input.themeStyle, shell, text, theme, context);
|
|
497
|
-
if (isPlainObject(input.surfaceStyle))
|
|
498
|
-
composeSurface(input.surfaceStyle, shell, theme, context);
|
|
499
|
-
if (isPlainObject(input.typographyStyle))
|
|
500
|
-
composeTypography(input.typographyStyle, text, theme, context);
|
|
501
|
-
if (isPlainObject(input.hoverStyle) && Object.values(input.hoverStyle).some(isSet)) {
|
|
502
|
-
warnings.push('hoverStyle: dokunmatikte hover durumu yok, atlandı');
|
|
503
|
-
}
|
|
504
|
-
composeFreeStyle(input.style, shell, text, theme, context);
|
|
505
|
-
return { shell, text, warnings };
|
|
506
|
-
}
|
|
507
|
-
/**
|
|
508
|
-
* Bir düğümün mobil çizerdeki stili (`NativeRenderer` → `nativeNodeStyle`, `renderer.functions.ts`). Temanın katmanı
|
|
509
|
-
* (`componentStyles[tip]` ← `$preset`) web'in çözücüsünden gelir ve TABANDIR; panel grupları üstüne, düğümün serbest
|
|
510
|
-
* `style`'ı son söz; `$preset` işareti RN stiline inmez (plans/mobil-plantcare-acigi f-16 — 2026-09-28'e dek çizer bu
|
|
511
|
-
* katmanı okumuyordu, rapor da okumuyordu). İfadeye bağlı prop çalışma anında çözülür, burada yok.
|
|
512
|
-
*/
|
|
513
|
-
export function nodeNativeStyle(node, theme, source) {
|
|
514
|
-
const props = node.props;
|
|
515
|
-
const group = (name) => {
|
|
516
|
-
const value = rawProp(props, name);
|
|
517
|
-
return isPlainObject(value) ? value : null;
|
|
518
|
-
};
|
|
519
|
-
const layers = resolveNodeStyleLayers(rawProp(props, 'style'), source, node.type);
|
|
520
|
-
return composeNativeStyle({
|
|
521
|
-
themeStyle: layers.theme,
|
|
522
|
-
surfaceStyle: group('surfaceStyle'),
|
|
523
|
-
typographyStyle: group('typographyStyle'),
|
|
524
|
-
hoverStyle: group('hoverStyle'),
|
|
525
|
-
style: layers.own
|
|
526
|
-
}, theme);
|
|
527
|
-
}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
-
import { PlatformApiError } from './errors.js';
|
|
3
|
-
import { RefResolver, isGuid } from './refs.js';
|
|
4
|
-
const text = (value) => typeof value === 'string' ? value : String(value ?? '');
|
|
5
|
-
const hostAlias = (from, host) => ({
|
|
6
|
-
tool: '*',
|
|
7
|
-
from,
|
|
8
|
-
when: (shape, args) => 'host' in shape && 'hostId' in shape && !(from in shape) && args.host === undefined && args.hostId === undefined,
|
|
9
|
-
apply: async (value) => ({ set: { host, hostId: value }, note: `${from} → host: '${host}', hostId: ${text(value)}` })
|
|
10
|
-
});
|
|
11
|
-
export const ARGUMENT_ALIASES = [
|
|
12
|
-
hostAlias('pageId', 'page'),
|
|
13
|
-
hostAlias('layoutId', 'layout'),
|
|
14
|
-
hostAlias('componentId', 'component'),
|
|
15
|
-
{
|
|
16
|
-
tool: '*',
|
|
17
|
-
from: 'project',
|
|
18
|
-
when: (shape, args) => 'projectId' in shape && !('project' in shape) && args.projectId === undefined,
|
|
19
|
-
apply: async (value, _args, { platform }) => {
|
|
20
|
-
if (isGuid(text(value)))
|
|
21
|
-
return { set: { projectId: text(value) }, note: `project → projectId: ${text(value)}` };
|
|
22
|
-
// Önce slug (`/p/{slug}`), sonra ad: liste arama sonucunda slug ya da ad birebir (büyük/küçük harf duyarsız).
|
|
23
|
-
const bySlug = await platform.org('GET', `/p/${encodeURIComponent(text(value))}`).catch(() => undefined);
|
|
24
|
-
const wanted = text(value).toLocaleLowerCase('tr');
|
|
25
|
-
const listed = bySlug?.data?.id
|
|
26
|
-
? undefined
|
|
27
|
-
: await platform.org('GET', '/projects', { query: { searchTerm: text(value), pageLength: 50 } }).catch(() => undefined);
|
|
28
|
-
const projectId = bySlug?.data?.id ?? listed?.data?.find(project => [project.slug, project.name].some(candidate => candidate?.toLocaleLowerCase('tr') === wanted))?.id;
|
|
29
|
-
if (!projectId)
|
|
30
|
-
throw new PlatformApiError(`'${text(value)}' diye bir proje yok (slug ya da ad); projectId'yi project_list ile bulun.`, 400);
|
|
31
|
-
return { set: { projectId }, note: `project '${text(value)}' → projectId: ${projectId}` };
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
tool: '*',
|
|
36
|
-
from: 'id',
|
|
37
|
-
when: (shape, args) => 'microservice' in shape && 'application' in shape && !('id' in shape) && args.microservice === undefined,
|
|
38
|
-
apply: async (value, args, { platform }) => {
|
|
39
|
-
if (!isGuid(text(value)))
|
|
40
|
-
return { set: { microservice: text(value) }, note: `id → microservice: '${text(value)}'` };
|
|
41
|
-
if (typeof args.application !== 'string')
|
|
42
|
-
throw new PlatformApiError("id bir microservice GUID'i; slug'ını çözmek için 'application' (uygulama slug'ı) da verin.", 400);
|
|
43
|
-
const resolver = new RefResolver(platform, args.project, args.environment);
|
|
44
|
-
const applicationId = await resolver.applicationId(args.application);
|
|
45
|
-
const payload = await platform.tenant('GET', args.project, `/microservices/${applicationId}/${text(value)}`, { environment: args.environment });
|
|
46
|
-
const slug = payload?.data?.slug;
|
|
47
|
-
if (!slug)
|
|
48
|
-
throw new PlatformApiError(`'${args.application}' uygulamasında ${text(value)} id'li microservice yok; microservice_list ile slug'ı bulun.`, 400);
|
|
49
|
-
return { set: { microservice: slug }, note: `id ${text(value)} → microservice: '${slug}'` };
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
tool: 'entity_get',
|
|
54
|
-
from: 'applicationId',
|
|
55
|
-
apply: async (value, args, { platform }) => {
|
|
56
|
-
const project = args.project;
|
|
57
|
-
const environment = args.environment;
|
|
58
|
-
const resolver = new RefResolver(platform, project, environment);
|
|
59
|
-
const applicationId = await resolver.applicationId(text(value));
|
|
60
|
-
const entity = await resolver.entity(text(args.id));
|
|
61
|
-
const payload = await platform.tenant('GET', project, `/entities/${entity.datasourceId}/${entity.entityId}`, { environment });
|
|
62
|
-
const linked = (payload?.data?.applications ?? []).some(link => [link.id, link.applicationId].some(id => id?.toLowerCase() === applicationId.toLowerCase()));
|
|
63
|
-
if (!linked) {
|
|
64
|
-
throw new PlatformApiError(`'${text(args.id)}' entity'si '${text(value)}' uygulamasına bağlı değil; entity_get uygulamaya göre değil entity'ye göre çalışır — applicationId'yi kaldırın ya da uygulamanın entity'lerini entity_list {applicationId} ile listeleyin.`, 400);
|
|
65
|
-
}
|
|
66
|
-
return { set: { datasourceId: entity.datasourceId }, note: `applicationId '${text(value)}' → datasourceId: ${entity.datasourceId} (entity '${text(args.id)}' bu uygulamaya bağlı)` };
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
tool: '*',
|
|
71
|
-
from: 'applicationId',
|
|
72
|
-
when: (shape, args) => shape.applicationId !== undefined && typeof args.applicationId === 'string' && !shape.applicationId.safeParse(args.applicationId).success,
|
|
73
|
-
apply: async (value, args, { platform }) => {
|
|
74
|
-
const applicationId = await new RefResolver(platform, args.project, args.environment).applicationId(text(value));
|
|
75
|
-
return { set: { applicationId }, note: `applicationId '${text(value)}' → ${applicationId}` };
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
];
|
|
79
|
-
export async function applyArgumentAliases(tool, args, context) {
|
|
80
|
-
if (!args || typeof args !== 'object' || Array.isArray(args))
|
|
81
|
-
return { args, applied: [] };
|
|
82
|
-
let current = { ...args };
|
|
83
|
-
const applied = [];
|
|
84
|
-
for (const alias of ARGUMENT_ALIASES) {
|
|
85
|
-
if (alias.tool !== '*' && alias.tool !== tool)
|
|
86
|
-
continue;
|
|
87
|
-
if (!(alias.from in current))
|
|
88
|
-
continue;
|
|
89
|
-
if (!(alias.when ? alias.when(context.shape, current) : !(alias.from in context.shape)))
|
|
90
|
-
continue;
|
|
91
|
-
const outcome = await alias.apply(current[alias.from], current, context);
|
|
92
|
-
const { [alias.from]: _replaced, ...rest } = current;
|
|
93
|
-
current = { ...rest, ...outcome.set };
|
|
94
|
-
applied.push(outcome.note);
|
|
95
|
-
}
|
|
96
|
-
return { args: current, applied };
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Takma adı olmayan bilinmeyen argüman için "bunu mu demek istedin": okunan alanlar arasından büyük/küçük
|
|
100
|
-
* harf duyarsız düzenleme uzaklığı 2'yi geçmeyen en yakın ad (`hostID` → `hostId`, `views` → `view`).
|
|
101
|
-
*/
|
|
102
|
-
export function closestArgument(key, accepted) {
|
|
103
|
-
const distance = (left, right) => {
|
|
104
|
-
const row = Array.from({ length: right.length + 1 }, (_, index) => index);
|
|
105
|
-
for (let i = 1; i <= left.length; i++) {
|
|
106
|
-
let diagonal = row[0] ?? 0;
|
|
107
|
-
row[0] = i;
|
|
108
|
-
for (let j = 1; j <= right.length; j++) {
|
|
109
|
-
const above = row[j] ?? 0;
|
|
110
|
-
row[j] = Math.min(above + 1, (row[j - 1] ?? 0) + 1, diagonal + (left[i - 1] === right[j - 1] ? 0 : 1));
|
|
111
|
-
diagonal = above;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return row[right.length] ?? 0;
|
|
115
|
-
};
|
|
116
|
-
const ranked = accepted
|
|
117
|
-
.map(name => ({ name, score: distance(key.toLowerCase(), name.toLowerCase()) }))
|
|
118
|
-
.filter(entry => entry.score <= 2)
|
|
119
|
-
.sort((left, right) => left.score - right.score);
|
|
120
|
-
return ranked[0]?.name;
|
|
121
|
-
}
|
|
122
|
-
const activeNotes = new AsyncLocalStorage();
|
|
123
|
-
export function runWithArgumentNotes(notes, run) {
|
|
124
|
-
return activeNotes.run(notes, run);
|
|
125
|
-
}
|
|
126
|
-
export function argumentNotes() {
|
|
127
|
-
return activeNotes.getStore() ?? { aliasesApplied: [] };
|
|
128
|
-
}
|