@appaflytech/zeyrek-ai-mcp 0.0.4 → 0.0.6
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 +8 -3
- package/.env.production.example +2 -0
- package/README.md +229 -193
- package/dist/config.js +20 -2
- package/dist/knowledge/backendConstraints.js +897 -0
- package/dist/knowledge/componentCatalog.js +196 -42
- package/dist/knowledge/coverage.js +43 -0
- package/dist/knowledge/flowGuards.js +30 -0
- package/dist/knowledge/guideSections.js +49 -0
- package/dist/knowledge/hydrate.js +97 -0
- package/dist/knowledge/languageCodes.js +36 -0
- package/dist/knowledge/languages.js +105 -0
- package/dist/knowledge/layoutSummary.js +10 -0
- package/dist/knowledge/localization.js +51 -0
- package/dist/knowledge/normalize.js +449 -16
- package/dist/knowledge/outlines.js +136 -12
- package/dist/knowledge/propTypes.js +80 -0
- package/dist/knowledge/rules.js +618 -43
- package/dist/knowledge/schemaGuard.js +199 -0
- package/dist/knowledge/styleResolve.js +63 -4
- package/dist/observability/trace.js +27 -3
- package/dist/platform/errors.js +46 -4
- package/dist/platform/http.js +33 -4
- package/dist/platform/patch.js +27 -0
- package/dist/platform/refs.js +104 -0
- package/dist/platform/responses.js +9 -2
- package/dist/platform/screenshot.js +527 -16
- package/dist/platform/secrets.js +40 -0
- package/dist/platform/tokenVault.js +89 -0
- package/dist/platform/writeDiff.js +281 -0
- package/dist/resources/examples/layout-app-shell.json +1 -1
- package/dist/resources/examples/microservice-table-list.json +2 -4
- package/dist/resources/examples/page-dynamic-form.json +2 -2
- package/dist/resources/examples/page-flex-sections.json +99 -0
- package/dist/resources/examples/page-sign-in.json +3 -2
- package/dist/resources/guides/component.md +69 -8
- package/dist/resources/guides/entity.md +404 -16
- package/dist/resources/guides/expressions.md +44 -2
- package/dist/resources/guides/external-component.md +9 -0
- package/dist/resources/guides/getting-started.md +77 -7
- package/dist/resources/guides/layout.md +53 -10
- package/dist/resources/guides/microservice.md +226 -13
- package/dist/resources/guides/middleware.md +89 -1
- package/dist/resources/guides/page.md +383 -46
- package/dist/resources/guides/translation.md +126 -8
- package/dist/resources/guides/view.md +16 -1
- package/dist/resources/guides/workflow.md +198 -27
- package/dist/resources/knowledge.js +5 -0
- package/dist/resources/rules.js +27 -0
- package/dist/resources/schema-fingerprint.json +8 -0
- package/dist/resources/schemas/CreateBulkRowCommand.json +33 -0
- package/dist/resources/schemas/CreateDatasourceCommand.json +15 -6
- package/dist/resources/schemas/CreateDiscoveredEntitiesCommand.json +19 -8
- package/dist/resources/schemas/CreateEntityCommand.json +52 -12
- package/dist/resources/schemas/CreateMicroserviceCommand.json +26 -2
- package/dist/resources/schemas/CreateQueryCommand.json +56 -3
- package/dist/resources/schemas/CreateRowCommand.json +38 -0
- package/dist/resources/schemas/CreateViewCommand.json +13 -10
- package/dist/resources/schemas/CreateWorkflowCommand.json +95 -14
- package/dist/resources/schemas/GetRowsQuery.json +3 -0
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +16 -0
- package/dist/resources/schemas/PreviewQueryCommand.json +5 -2
- package/dist/resources/schemas/PreviewWorkflowCommand.json +34 -9
- package/dist/resources/schemas/StepDto.json +23 -3
- package/dist/resources/schemas/UpdateBulkRowCommand.json +33 -0
- package/dist/resources/schemas/UpdateDatasourceCommand.json +15 -6
- package/dist/resources/schemas/UpdateEntityCommand.json +49 -10
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +28 -3
- package/dist/resources/schemas/UpdateQueryCommand.json +13 -3
- package/dist/resources/schemas/UpdateRowCommand.json +40 -0
- package/dist/resources/schemas/UpdateViewCommand.json +15 -10
- package/dist/resources/schemas/UpdateWorkflowCommand.json +95 -14
- package/dist/server.js +4 -0
- package/dist/tools/access.js +3 -3
- package/dist/tools/applications.js +1 -1
- package/dist/tools/automations.js +63 -30
- package/dist/tools/common.js +39 -0
- package/dist/tools/components.js +16 -7
- package/dist/tools/datasources.js +83 -21
- package/dist/tools/deployments.js +34 -2
- package/dist/tools/dtos.js +25 -12
- package/dist/tools/entities.js +113 -28
- package/dist/tools/externalComponents.js +9 -3
- package/dist/tools/files.js +20 -6
- package/dist/tools/flows.js +110 -11
- package/dist/tools/folders.js +7 -2
- package/dist/tools/globalFunctions.js +63 -0
- package/dist/tools/layouts.js +103 -29
- package/dist/tools/microservices.js +229 -38
- package/dist/tools/organizations.js +5 -6
- package/dist/tools/pages.js +365 -100
- package/dist/tools/platformInfo.js +152 -11
- package/dist/tools/projects.js +183 -33
- package/dist/tools/queries.js +32 -10
- package/dist/tools/rows.js +159 -45
- package/dist/tools/screenWrite.js +59 -0
- package/dist/tools/screens.js +28 -0
- package/dist/tools/translations.js +24 -8
- package/dist/tools/views.js +20 -10
- package/dist/tools/workflows.js +33 -16
- package/package.json +6 -3
|
@@ -62,6 +62,8 @@ export function entityOutline(definition) {
|
|
|
62
62
|
slug: definition.slug,
|
|
63
63
|
name: definition.name,
|
|
64
64
|
datasourceId: definition.datasourceId,
|
|
65
|
+
localizationEntityId: definition.localizationEntityId ?? null,
|
|
66
|
+
localizationParentId: definition.localizationParentId ?? null,
|
|
65
67
|
fieldCount: asArray(definition.fields).length,
|
|
66
68
|
fields: asArray(definition.fields).map(field => ({
|
|
67
69
|
id: field.id,
|
|
@@ -73,10 +75,116 @@ export function entityOutline(definition) {
|
|
|
73
75
|
relationId: field.relationId ?? null,
|
|
74
76
|
isLocalized: Boolean(field.isLocalized)
|
|
75
77
|
})),
|
|
78
|
+
indexCount: asArray(definition.indexes).length,
|
|
79
|
+
// Index'ler alanlardan çok daha az sayıdadır; tam projeksiyon outline'ı şişirmez ve yazılan
|
|
80
|
+
// index'in kanıtı ayrı bir tur istemez (B-45'in `entity_get`/`entity_create` ayağı).
|
|
81
|
+
...(asArray(definition.indexes).length > 0
|
|
82
|
+
? {
|
|
83
|
+
indexes: asArray(definition.indexes).map(index => ({
|
|
84
|
+
id: index.id,
|
|
85
|
+
name: index.name,
|
|
86
|
+
unique: Boolean(index.unique),
|
|
87
|
+
fieldIds: Array.isArray(index.fieldIds) ? index.fieldIds : []
|
|
88
|
+
}))
|
|
89
|
+
}
|
|
90
|
+
: {}),
|
|
76
91
|
view: 'outline',
|
|
77
92
|
hint: "Bir alanın tam gövdesi için view:'part', part:'fields[slug=<slug>]'; değişiklik için entity_patch. isLocalized alanlar için platform_guide('entity') §'Çoklu dilli alan'."
|
|
78
93
|
};
|
|
79
94
|
}
|
|
95
|
+
const identityKeys = ['id', 'slug', 'name', 'elementId', 'stepId'];
|
|
96
|
+
/**
|
|
97
|
+
* Eklenen öğeyi FİNAL gövdede kimliğinden bulur. Konumsal ("dizinin son elemanı") arama
|
|
98
|
+
* platform diziye kendi öğesini eklediğinde yanlış kaydı gösterir: audit trail açık bir
|
|
99
|
+
* entity'ye alan eklendiğinde platform `fields`in sonuna dört `sys_*` alanı ekler ve rapor
|
|
100
|
+
* eklenen alan yerine `sys_updated_user_id`'yi gösteriyordu (ölçüldü 2026-09-08).
|
|
101
|
+
*/
|
|
102
|
+
function appendedPosition(section, value) {
|
|
103
|
+
if (!value || typeof value !== 'object')
|
|
104
|
+
return -1;
|
|
105
|
+
const source = value;
|
|
106
|
+
for (const key of identityKeys) {
|
|
107
|
+
const wanted = source[key];
|
|
108
|
+
if (wanted === undefined || wanted === null || wanted === '')
|
|
109
|
+
continue;
|
|
110
|
+
const position = section.findIndex(item => Boolean(item) && typeof item === 'object' && item[key] === wanted);
|
|
111
|
+
if (position >= 0)
|
|
112
|
+
return position;
|
|
113
|
+
}
|
|
114
|
+
return -1;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Patch'in DOKUNDUĞU bölümleri kayıttan çıkarır (S-8 · P2-1).
|
|
118
|
+
*
|
|
119
|
+
* `entity_patch` yanıtı bir outline'dır ve outline `indexes` taşımıyordu: 2026-09-06 koşusunda
|
|
120
|
+
* iki index yazıldı, "yazdım" demenin kanıtı yanıtta olmadığı için her entity için ayrı bir
|
|
121
|
+
* `entity_get(view:'part', part:'indexes[0]')` turu atıldı. Keşif çağrısı oranı o koşuda %30.1'di.
|
|
122
|
+
*
|
|
123
|
+
* Outline'ın kısa kalma amacı korunur: TAM gövde değil, yalnız yamanın adreslediği bölüm döner —
|
|
124
|
+
* dizide de yalnız dokunulan eleman. Yollar `resolvePatchOperations`'tan geçmiş, yani indekse
|
|
125
|
+
* çevrilmiş olmalıdır; `-` (dizi sonu) eklenen son elemana çözülür.
|
|
126
|
+
*/
|
|
127
|
+
export function patchedSections(document, operations) {
|
|
128
|
+
const explicit = new Map();
|
|
129
|
+
const appends = new Map();
|
|
130
|
+
const whole = new Set();
|
|
131
|
+
for (const operation of operations) {
|
|
132
|
+
const path = typeof operation.path === 'string' ? operation.path : '';
|
|
133
|
+
if (!path.startsWith('/'))
|
|
134
|
+
continue;
|
|
135
|
+
const [key, index] = path.split('/').slice(1);
|
|
136
|
+
if (!key || !Object.hasOwn(document, key))
|
|
137
|
+
continue;
|
|
138
|
+
if (!Array.isArray(document[key]) || index === undefined) {
|
|
139
|
+
whole.add(key);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
// Dizi sonu (`-`) yolu FİNAL gövdede tek bir indekse çözülemez: aynı çağrıda iki `add`
|
|
143
|
+
// varsa ikisi de son elemanı gösterir ve rapor bir tanesini yutardı (ölçüldü 2026-09-06,
|
|
144
|
+
// gerçek uçta: iki index eklendi, yanıt birini gösterdi). Eklenen gövde saklanır ve önce
|
|
145
|
+
// KİMLİKTEN aranır; kimlik tutmazsa son N eleman alınır.
|
|
146
|
+
if (index === '-') {
|
|
147
|
+
appends.set(key, [...(appends.get(key) ?? []), operation.value]);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const position = Number(index);
|
|
151
|
+
if (!Number.isInteger(position) || position < 0)
|
|
152
|
+
continue;
|
|
153
|
+
const positions = explicit.get(key) ?? new Set();
|
|
154
|
+
positions.add(position);
|
|
155
|
+
explicit.set(key, positions);
|
|
156
|
+
}
|
|
157
|
+
const touched = {};
|
|
158
|
+
for (const key of whole)
|
|
159
|
+
touched[key] = document[key];
|
|
160
|
+
for (const key of new Set([...explicit.keys(), ...appends.keys()])) {
|
|
161
|
+
if (whole.has(key))
|
|
162
|
+
continue;
|
|
163
|
+
const section = document[key];
|
|
164
|
+
const wanted = new Set();
|
|
165
|
+
for (const position of explicit.get(key) ?? []) {
|
|
166
|
+
if (position < section.length)
|
|
167
|
+
wanted.add(position);
|
|
168
|
+
}
|
|
169
|
+
let unresolved = 0;
|
|
170
|
+
for (const value of appends.get(key) ?? []) {
|
|
171
|
+
const position = appendedPosition(section, value);
|
|
172
|
+
if (position >= 0)
|
|
173
|
+
wanted.add(position);
|
|
174
|
+
else
|
|
175
|
+
unresolved++;
|
|
176
|
+
}
|
|
177
|
+
for (let step = 0; step < unresolved; step++) {
|
|
178
|
+
const position = section.length - 1 - step;
|
|
179
|
+
if (position >= 0)
|
|
180
|
+
wanted.add(position);
|
|
181
|
+
}
|
|
182
|
+
if (wanted.size === 0)
|
|
183
|
+
continue;
|
|
184
|
+
touched[key] = [...wanted].sort((left, right) => left - right).map(position => section[position]);
|
|
185
|
+
}
|
|
186
|
+
return touched;
|
|
187
|
+
}
|
|
80
188
|
const segmentPattern = /^(\w+)(?:\[(?:(\d+)|(\w+)=([^\]]+))\])?$/;
|
|
81
189
|
export function resolvePart(definition, part) {
|
|
82
190
|
let current = definition;
|
|
@@ -111,7 +219,7 @@ function unescapePointer(segment) {
|
|
|
111
219
|
* `*_get`'in `part` sözdizimindeki seçiciyi (`steps[id=…]`, `fields[slug=…]`) patch yollarında da
|
|
112
220
|
* kabul edip indekse çeviriyoruz; çözülemeyen seçici, gövde platforma GİTMEDEN hata verir.
|
|
113
221
|
*/
|
|
114
|
-
export function resolvePatchPointer(document, path) {
|
|
222
|
+
export function resolvePatchPointer(document, path, readTool = 'workflow_get', op = '') {
|
|
115
223
|
if (!path.startsWith('/'))
|
|
116
224
|
throw new Error(`JSON Patch yolu '/' ile başlamalı: '${path}'`);
|
|
117
225
|
const segments = path.split('/').slice(1);
|
|
@@ -131,11 +239,21 @@ export function resolvePatchPointer(document, path) {
|
|
|
131
239
|
const [, key, field, value] = match;
|
|
132
240
|
const collection = current && typeof current === 'object' ? current[key] : undefined;
|
|
133
241
|
if (!Array.isArray(collection)) {
|
|
134
|
-
throw new Error(`Patch yolu çözülemedi: '${path}' — '${key}' bir dizi değil. Mevcut yapıyı
|
|
242
|
+
throw new Error(`Patch yolu çözülemedi: '${path}' — '${key}' bir dizi değil. Mevcut yapıyı ${readTool} view:'outline' ile okuyun.`);
|
|
135
243
|
}
|
|
136
244
|
const index = collection.findIndex(entry => entry && typeof entry === 'object' && String(entry[field]) === value);
|
|
137
245
|
if (index === -1) {
|
|
138
|
-
|
|
246
|
+
const available = collection
|
|
247
|
+
.map(entry => entry && typeof entry === 'object' ? entry[field] : undefined)
|
|
248
|
+
.filter(entry => entry !== undefined && entry !== null)
|
|
249
|
+
.map(entry => `'${String(entry)}'`);
|
|
250
|
+
// Seçici VAR OLAN bir öğeyi adresler; yeni öğe eklemenin yolu dizi sonu (`-`) segmentidir.
|
|
251
|
+
// 2026-09-06 koşusunda ajan eksik bir iteratee'yi `add` ile eklemeye çalıştı, mesaj yalnız
|
|
252
|
+
// "yok" dedi ve ajan diziyi 13 girdiyle baştan yazmak zorunda kaldı (S-5 · P0-2 Step 6).
|
|
253
|
+
const addHint = op === 'add'
|
|
254
|
+
? ` EKLEMEK istiyorsanız seçici değil dizi sonu yolunu kullanın: '${path.slice(0, path.indexOf(`${key}[`) + key.length)}/-' — seçici yalnız VAR OLAN öğeyi adresler.`
|
|
255
|
+
: '';
|
|
256
|
+
throw new Error(`Patch yolu çözülemedi: '${path}' — '${key}' dizisinde ${field}='${value}' yok. Mevcut değerler: ${available.length > 0 ? available.join(', ') : '(hiç)'}.${addHint} Tam listeyi ${readTool} view:'outline' ile okuyun.`);
|
|
139
257
|
}
|
|
140
258
|
resolved.push(key, String(index));
|
|
141
259
|
current = collection[index];
|
|
@@ -145,24 +263,30 @@ export function resolvePatchPointer(document, path) {
|
|
|
145
263
|
return rewritten ? { path: resolvedPath, note: `${path} → ${resolvedPath}` } : { path: resolvedPath };
|
|
146
264
|
}
|
|
147
265
|
/**
|
|
148
|
-
* Yanıtın `applied: N` demekle yetinmemesi için: her op'un hangi
|
|
266
|
+
* Yanıtın `applied: N` demekle yetinmemesi için: her op'un hangi öğeye indiğini adıyla söyler.
|
|
267
|
+
* Seçiciyle yazılan yol indekse çevrildiği için, indeksin hangi kayda denk geldiğini görmek
|
|
268
|
+
* sessiz veri bozulmasını önleyen tek sinyaldir (entity'de alan sırası değişebilir).
|
|
149
269
|
*/
|
|
150
270
|
export function describePatchTarget(document, path) {
|
|
151
|
-
const match = /^\/steps\/(\d+)(\/.*)?$/.exec(path);
|
|
271
|
+
const match = /^\/(steps|fields|indexes)\/(\d+)(\/.*)?$/.exec(path);
|
|
152
272
|
if (!match)
|
|
153
273
|
return path;
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
274
|
+
const collection = asArray(document[match[1]]);
|
|
275
|
+
const entry = collection[Number(match[2])];
|
|
276
|
+
if (!entry)
|
|
277
|
+
return `${path} → (dizide ${match[2]}. eleman YOK)`;
|
|
278
|
+
const label = String(entry.name ?? entry.slug ?? entry.id ?? '?');
|
|
279
|
+
const kind = entry.type ?? entry.dbType;
|
|
280
|
+
return `${path} → '${label}'${kind ? ` (${String(kind)}` + `, id ${String(entry.id ?? '?')})` : `, id ${String(entry.id ?? '?')}`}`;
|
|
158
281
|
}
|
|
159
|
-
export function resolvePatchOperations(document, operations) {
|
|
282
|
+
export function resolvePatchOperations(document, operations, readTool = 'workflow_get') {
|
|
160
283
|
const notes = [];
|
|
161
284
|
const targets = [];
|
|
162
285
|
const resolved = operations.map(operation => {
|
|
163
286
|
const path = typeof operation.path === 'string' ? operation.path : '';
|
|
164
|
-
const
|
|
165
|
-
const
|
|
287
|
+
const op = typeof operation.op === 'string' ? operation.op : '';
|
|
288
|
+
const outcome = resolvePatchPointer(document, path, readTool, op);
|
|
289
|
+
const from = typeof operation.from === 'string' ? resolvePatchPointer(document, operation.from, readTool, op) : undefined;
|
|
166
290
|
if (outcome.note)
|
|
167
291
|
notes.push(outcome.note);
|
|
168
292
|
if (from?.note)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { findNode } from '../tools/screens.js';
|
|
2
|
+
/**
|
|
3
|
+
* Prop değerinin `type` alanı üç değer alır ve her biri taşıyıcısı farklıdır.
|
|
4
|
+
*
|
|
5
|
+
* Platformun kendi micro-op applier'ı `replace_prop`'ta gönderilen ham değeri HER ZAMAN `Static`
|
|
6
|
+
* (ifade verilmişse `Code`) Prop'una sarar (`PageSchemaMicroOpApplier.cs:77`), yani kurulu bir
|
|
7
|
+
* etiketi çeviriye bağlamanın platform tarafında bir yolu yoktur. Bu op o boşluğu kapatır:
|
|
8
|
+
* şemayı okur, prop'un TİPİNİ yerinde değiştirir, gövdeyi tam yazar.
|
|
9
|
+
*
|
|
10
|
+
* Alternatifi `remove_component` + `add_component`'tı ve pahalıydı: 2026-09-06 koşusunda on bir
|
|
11
|
+
* etiket o yolla yeniden kuruldu, o düğümlere yazan DOKUZ setter iteratee'si platform tarafından
|
|
12
|
+
* sessizce silindi ve üç KPI kartı boş kaldı (S-5/G-2).
|
|
13
|
+
*
|
|
14
|
+
* Taşıyıcı: `static` değeri `data`'da; `code` ve `translation` ifadeyi/anahtarı `ref`'te taşır —
|
|
15
|
+
* runtime `data`'yı her turda çözümlenmiş değerle ezer, o yüzden anahtar yalnız `ref`'te yaşar
|
|
16
|
+
* (`platform_guide('translation')`).
|
|
17
|
+
*/
|
|
18
|
+
export const PROP_TYPE_CARRIER = { static: 'data', code: 'ref', translation: 'ref' };
|
|
19
|
+
export const SET_PROP_TYPE_OP = 'set_prop_type';
|
|
20
|
+
export function isSetPropTypeOp(op) {
|
|
21
|
+
return Boolean(op) && typeof op === 'object' && String(op.op ?? '') === SET_PROP_TYPE_OP;
|
|
22
|
+
}
|
|
23
|
+
export function setPropTypeErrors(ops) {
|
|
24
|
+
const issues = [];
|
|
25
|
+
for (const op of ops) {
|
|
26
|
+
const target = String(op.target ?? '');
|
|
27
|
+
const prop = String(op.prop ?? '');
|
|
28
|
+
const propType = String(op.propType ?? '');
|
|
29
|
+
if (!target || !prop) {
|
|
30
|
+
issues.push("set_prop_type için 'target' (elementId) ve 'prop' (prop adı) zorunludur.");
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const carrier = PROP_TYPE_CARRIER[propType];
|
|
34
|
+
if (!carrier) {
|
|
35
|
+
issues.push(`set_prop_type '${target}.${prop}': geçersiz propType '${propType || '(boş)'}'. Yazılabilir tipler: ${Object.keys(PROP_TYPE_CARRIER).join(' · ')}.`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (carrier === 'ref' && String(op.ref ?? '').trim().length === 0) {
|
|
39
|
+
issues.push(`set_prop_type '${target}.${prop}': propType '${propType}' değeri 'ref' alanında taşır ve 'ref' boş. ${propType === 'translation' ? "translation_list ile çeviri anahtarını bulun (ör. ref: 'dashboard.kpi.total')" : "ref: '<ifade>' verin (ör. 'Page.variables.total')"} — runtime 'data'yı her turda ezer, anahtar yalnız ref'te yaşar.`);
|
|
40
|
+
}
|
|
41
|
+
if (carrier === 'data' && op.data === undefined && op.value === undefined) {
|
|
42
|
+
issues.push(`set_prop_type '${target}.${prop}': propType 'static' değeri 'data' alanında taşır ve 'data' verilmedi. Mevcut değeri korumak istiyorsanız data'yı açıkça yazın.`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return issues;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Op'ları verilen ağaca uygular. Ağacı YERİNDE değiştirir — çağıran kopyayı kendisi alır, çünkü
|
|
49
|
+
* sayfa ve layout hatları gövdeyi farklı biçimde geri yazıyor (`pageUpdateBody` / `layoutUpdateBody`).
|
|
50
|
+
* Bulunamayan hedefler atılmaz, `missingTargets` ile döner: çağıran kendi aracının adını içeren
|
|
51
|
+
* hata mesajını kurar.
|
|
52
|
+
*/
|
|
53
|
+
export function applyPropTypesToSchema(schema, ops) {
|
|
54
|
+
const applied = [];
|
|
55
|
+
const missingTargets = [];
|
|
56
|
+
for (const op of ops) {
|
|
57
|
+
const target = String(op.target ?? '');
|
|
58
|
+
const prop = String(op.prop ?? '');
|
|
59
|
+
const propType = String(op.propType ?? '');
|
|
60
|
+
const node = findNode(schema, target);
|
|
61
|
+
if (!node) {
|
|
62
|
+
missingTargets.push(target);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const props = (node.props ?? {});
|
|
66
|
+
const existing = props[prop];
|
|
67
|
+
const current = existing && typeof existing === 'object' && !Array.isArray(existing)
|
|
68
|
+
? existing
|
|
69
|
+
: undefined;
|
|
70
|
+
// `data` tasarım zamanı yedeğidir: `code`/`translation`'a geçerken mevcut metni koruyoruz ki
|
|
71
|
+
// Studio'da boş kutu görünmesin (runtime onu zaten çözümlenmiş değerle ezer).
|
|
72
|
+
const carried = op.data !== undefined ? op.data : op.value !== undefined ? op.value : current?.data ?? null;
|
|
73
|
+
props[prop] = propType === 'static'
|
|
74
|
+
? { type: 'static', ref: null, data: carried }
|
|
75
|
+
: { type: propType, ref: String(op.ref), data: carried };
|
|
76
|
+
node.props = props;
|
|
77
|
+
applied.push(`${target}.${prop}: ${current?.type ?? '(yok)'} → ${propType}`);
|
|
78
|
+
}
|
|
79
|
+
return { applied, missingTargets };
|
|
80
|
+
}
|