@appaflytech/zeyrek-ai-mcp 0.0.5 → 0.0.7
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 +2 -2
- package/.env.production.example +9 -1
- package/README.md +14 -38
- package/dist/config.js +36 -3
- package/dist/knowledge/backendConstraints.js +982 -0
- package/dist/knowledge/componentCatalog.js +549 -92
- package/dist/knowledge/componentEvents.js +120 -25
- package/dist/knowledge/coverage.js +43 -0
- package/dist/knowledge/flowGuards.js +30 -0
- package/dist/knowledge/functionGuards.js +134 -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 +500 -16
- package/dist/knowledge/outlines.js +167 -12
- package/dist/knowledge/policy.js +14 -5
- package/dist/knowledge/propTypes.js +80 -0
- package/dist/knowledge/rules.js +961 -44
- package/dist/knowledge/schemaGuard.js +199 -0
- package/dist/knowledge/styleResolve.js +63 -4
- package/dist/observability/trace.js +27 -3
- package/dist/platform/csv.js +123 -0
- package/dist/platform/errors.js +107 -6
- package/dist/platform/http.js +34 -4
- package/dist/platform/patch.js +27 -0
- package/dist/platform/refs.js +104 -0
- package/dist/platform/responses.js +25 -6
- package/dist/platform/screenshot.js +544 -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/flow-call-function.json +66 -0
- package/dist/resources/examples/function-total.json +70 -0
- package/dist/resources/examples/layout-app-shell.json +1 -1
- package/dist/resources/examples/microfunction-node-sum.json +56 -0
- package/dist/resources/examples/microservice-table-list.json +2 -4
- package/dist/resources/examples/page-dynamic-form.json +3 -3
- package/dist/resources/examples/page-flex-sections.json +99 -0
- package/dist/resources/examples/page-sign-in.json +4 -3
- package/dist/resources/guides/component.md +81 -8
- package/dist/resources/guides/entity.md +712 -20
- package/dist/resources/guides/expressions.md +47 -2
- package/dist/resources/guides/external-component.md +9 -0
- package/dist/resources/guides/functions.md +262 -0
- package/dist/resources/guides/getting-started.md +82 -7
- package/dist/resources/guides/layout.md +53 -10
- package/dist/resources/guides/merge.md +231 -0
- package/dist/resources/guides/microfunction.md +166 -0
- package/dist/resources/guides/microservice.md +287 -15
- package/dist/resources/guides/middleware.md +89 -1
- package/dist/resources/guides/modify-existing.md +23 -0
- package/dist/resources/guides/page.md +402 -49
- package/dist/resources/guides/translation.md +150 -8
- package/dist/resources/guides/view.md +16 -1
- package/dist/resources/guides/workflow.md +199 -28
- 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/AnalyzeImportQuery.json +51 -0
- package/dist/resources/schemas/ApplyMergePlanCommand.json +19 -0
- package/dist/resources/schemas/CreateBulkRowCommand.json +36 -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/CreateEnvironmentCommand.json +31 -0
- package/dist/resources/schemas/CreateGlobalFunctionCommand.json +95 -0
- package/dist/resources/schemas/CreateImportPlanCommand.json +278 -0
- package/dist/resources/schemas/CreateMergePlanCommand.json +34 -0
- package/dist/resources/schemas/CreateMicrofunctionCommand.json +117 -0
- package/dist/resources/schemas/CreateMicrofunctionRuntimeCommand.json +51 -0
- package/dist/resources/schemas/CreateMicroserviceCommand.json +145 -3
- 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 +106 -14
- package/dist/resources/schemas/DataJobDto.json +267 -0
- package/dist/resources/schemas/ExportRowsCommand.json +172 -0
- package/dist/resources/schemas/Filter.json +3 -1
- package/dist/resources/schemas/GetRowsQuery.json +6 -1
- package/dist/resources/schemas/GlobalFunctionDto.json +89 -0
- package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +249 -0
- package/dist/resources/schemas/ImportAnalysisDto.json +401 -0
- package/dist/resources/schemas/ImportPlanDto.json +260 -0
- package/dist/resources/schemas/ImportSampleDto.json +90 -0
- package/dist/resources/schemas/InvokeMicrofunctionCommand.json +25 -0
- package/dist/resources/schemas/PreviewMicroserviceCommand.json +135 -1
- package/dist/resources/schemas/PreviewQueryCommand.json +5 -2
- package/dist/resources/schemas/PreviewWorkflowCommand.json +45 -9
- package/dist/resources/schemas/ResolveMergeConflictsCommand.json +58 -0
- package/dist/resources/schemas/RevertMergePlanCommand.json +19 -0
- package/dist/resources/schemas/RunImportCommand.json +62 -0
- package/dist/resources/schemas/StepDto.json +34 -3
- package/dist/resources/schemas/UpdateBulkRowCommand.json +36 -0
- package/dist/resources/schemas/UpdateDatasourceCommand.json +15 -6
- package/dist/resources/schemas/UpdateEntityCommand.json +52 -11
- package/dist/resources/schemas/UpdateGlobalFunctionCommand.json +66 -0
- package/dist/resources/schemas/UpdateMicrofunctionCommand.json +121 -0
- package/dist/resources/schemas/UpdateMicrofunctionRuntimeCommand.json +54 -0
- package/dist/resources/schemas/UpdateMicroserviceCommand.json +147 -4
- 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 +106 -14
- package/dist/server.js +17 -1
- package/dist/tools/access.js +3 -3
- package/dist/tools/activities.js +40 -0
- package/dist/tools/applications.js +1 -1
- package/dist/tools/automations.js +76 -34
- package/dist/tools/common.js +55 -0
- package/dist/tools/components.js +16 -7
- package/dist/tools/datasources.js +83 -21
- package/dist/tools/dependencies.js +1 -1
- package/dist/tools/deployments.js +34 -2
- package/dist/tools/dtos.js +25 -12
- package/dist/tools/entities.js +113 -28
- package/dist/tools/environments.js +52 -0
- package/dist/tools/externalComponents.js +9 -3
- package/dist/tools/files.js +57 -42
- package/dist/tools/flows.js +205 -13
- package/dist/tools/folders.js +7 -2
- package/dist/tools/functions.js +331 -0
- package/dist/tools/globalFunctions.js +63 -0
- package/dist/tools/importSchemas.js +79 -0
- package/dist/tools/imports.js +241 -0
- package/dist/tools/layouts.js +103 -29
- package/dist/tools/merges.js +113 -0
- package/dist/tools/microfunctions.js +155 -0
- package/dist/tools/microservices.js +270 -40
- package/dist/tools/organizations.js +5 -6
- package/dist/tools/pages.js +421 -104
- package/dist/tools/platformInfo.js +155 -11
- package/dist/tools/projects.js +183 -33
- package/dist/tools/queries.js +32 -10
- package/dist/tools/revisions.js +94 -0
- package/dist/tools/rows.js +484 -50
- package/dist/tools/screenWrite.js +68 -0
- package/dist/tools/screens.js +28 -0
- package/dist/tools/templates.js +32 -5
- package/dist/tools/translations.js +24 -8
- package/dist/tools/views.js +20 -10
- package/dist/tools/workflows.js +56 -21
- package/package.json +7 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { functionSignature } from './functionGuards.js';
|
|
1
2
|
function asArray(value) {
|
|
2
3
|
return Array.isArray(value) ? value.filter((entry) => Boolean(entry) && typeof entry === 'object') : [];
|
|
3
4
|
}
|
|
@@ -62,6 +63,8 @@ export function entityOutline(definition) {
|
|
|
62
63
|
slug: definition.slug,
|
|
63
64
|
name: definition.name,
|
|
64
65
|
datasourceId: definition.datasourceId,
|
|
66
|
+
localizationEntityId: definition.localizationEntityId ?? null,
|
|
67
|
+
localizationParentId: definition.localizationParentId ?? null,
|
|
65
68
|
fieldCount: asArray(definition.fields).length,
|
|
66
69
|
fields: asArray(definition.fields).map(field => ({
|
|
67
70
|
id: field.id,
|
|
@@ -73,10 +76,116 @@ export function entityOutline(definition) {
|
|
|
73
76
|
relationId: field.relationId ?? null,
|
|
74
77
|
isLocalized: Boolean(field.isLocalized)
|
|
75
78
|
})),
|
|
79
|
+
indexCount: asArray(definition.indexes).length,
|
|
80
|
+
// Index'ler alanlardan çok daha az sayıdadır; tam projeksiyon outline'ı şişirmez ve yazılan
|
|
81
|
+
// index'in kanıtı ayrı bir tur istemez (B-45'in `entity_get`/`entity_create` ayağı).
|
|
82
|
+
...(asArray(definition.indexes).length > 0
|
|
83
|
+
? {
|
|
84
|
+
indexes: asArray(definition.indexes).map(index => ({
|
|
85
|
+
id: index.id,
|
|
86
|
+
name: index.name,
|
|
87
|
+
unique: Boolean(index.unique),
|
|
88
|
+
fieldIds: Array.isArray(index.fieldIds) ? index.fieldIds : []
|
|
89
|
+
}))
|
|
90
|
+
}
|
|
91
|
+
: {}),
|
|
76
92
|
view: 'outline',
|
|
77
93
|
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
94
|
};
|
|
79
95
|
}
|
|
96
|
+
const identityKeys = ['id', 'slug', 'name', 'elementId', 'stepId'];
|
|
97
|
+
/**
|
|
98
|
+
* Eklenen öğeyi FİNAL gövdede kimliğinden bulur. Konumsal ("dizinin son elemanı") arama
|
|
99
|
+
* platform diziye kendi öğesini eklediğinde yanlış kaydı gösterir: audit trail açık bir
|
|
100
|
+
* entity'ye alan eklendiğinde platform `fields`in sonuna dört `sys_*` alanı ekler ve rapor
|
|
101
|
+
* eklenen alan yerine `sys_updated_user_id`'yi gösteriyordu (ölçüldü 2026-09-08).
|
|
102
|
+
*/
|
|
103
|
+
function appendedPosition(section, value) {
|
|
104
|
+
if (!value || typeof value !== 'object')
|
|
105
|
+
return -1;
|
|
106
|
+
const source = value;
|
|
107
|
+
for (const key of identityKeys) {
|
|
108
|
+
const wanted = source[key];
|
|
109
|
+
if (wanted === undefined || wanted === null || wanted === '')
|
|
110
|
+
continue;
|
|
111
|
+
const position = section.findIndex(item => Boolean(item) && typeof item === 'object' && item[key] === wanted);
|
|
112
|
+
if (position >= 0)
|
|
113
|
+
return position;
|
|
114
|
+
}
|
|
115
|
+
return -1;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Patch'in DOKUNDUĞU bölümleri kayıttan çıkarır (S-8 · P2-1).
|
|
119
|
+
*
|
|
120
|
+
* `entity_patch` yanıtı bir outline'dır ve outline `indexes` taşımıyordu: 2026-09-06 koşusunda
|
|
121
|
+
* iki index yazıldı, "yazdım" demenin kanıtı yanıtta olmadığı için her entity için ayrı bir
|
|
122
|
+
* `entity_get(view:'part', part:'indexes[0]')` turu atıldı. Keşif çağrısı oranı o koşuda %30.1'di.
|
|
123
|
+
*
|
|
124
|
+
* Outline'ın kısa kalma amacı korunur: TAM gövde değil, yalnız yamanın adreslediği bölüm döner —
|
|
125
|
+
* dizide de yalnız dokunulan eleman. Yollar `resolvePatchOperations`'tan geçmiş, yani indekse
|
|
126
|
+
* çevrilmiş olmalıdır; `-` (dizi sonu) eklenen son elemana çözülür.
|
|
127
|
+
*/
|
|
128
|
+
export function patchedSections(document, operations) {
|
|
129
|
+
const explicit = new Map();
|
|
130
|
+
const appends = new Map();
|
|
131
|
+
const whole = new Set();
|
|
132
|
+
for (const operation of operations) {
|
|
133
|
+
const path = typeof operation.path === 'string' ? operation.path : '';
|
|
134
|
+
if (!path.startsWith('/'))
|
|
135
|
+
continue;
|
|
136
|
+
const [key, index] = path.split('/').slice(1);
|
|
137
|
+
if (!key || !Object.hasOwn(document, key))
|
|
138
|
+
continue;
|
|
139
|
+
if (!Array.isArray(document[key]) || index === undefined) {
|
|
140
|
+
whole.add(key);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
// Dizi sonu (`-`) yolu FİNAL gövdede tek bir indekse çözülemez: aynı çağrıda iki `add`
|
|
144
|
+
// varsa ikisi de son elemanı gösterir ve rapor bir tanesini yutardı (ölçüldü 2026-09-06,
|
|
145
|
+
// gerçek uçta: iki index eklendi, yanıt birini gösterdi). Eklenen gövde saklanır ve önce
|
|
146
|
+
// KİMLİKTEN aranır; kimlik tutmazsa son N eleman alınır.
|
|
147
|
+
if (index === '-') {
|
|
148
|
+
appends.set(key, [...(appends.get(key) ?? []), operation.value]);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const position = Number(index);
|
|
152
|
+
if (!Number.isInteger(position) || position < 0)
|
|
153
|
+
continue;
|
|
154
|
+
const positions = explicit.get(key) ?? new Set();
|
|
155
|
+
positions.add(position);
|
|
156
|
+
explicit.set(key, positions);
|
|
157
|
+
}
|
|
158
|
+
const touched = {};
|
|
159
|
+
for (const key of whole)
|
|
160
|
+
touched[key] = document[key];
|
|
161
|
+
for (const key of new Set([...explicit.keys(), ...appends.keys()])) {
|
|
162
|
+
if (whole.has(key))
|
|
163
|
+
continue;
|
|
164
|
+
const section = document[key];
|
|
165
|
+
const wanted = new Set();
|
|
166
|
+
for (const position of explicit.get(key) ?? []) {
|
|
167
|
+
if (position < section.length)
|
|
168
|
+
wanted.add(position);
|
|
169
|
+
}
|
|
170
|
+
let unresolved = 0;
|
|
171
|
+
for (const value of appends.get(key) ?? []) {
|
|
172
|
+
const position = appendedPosition(section, value);
|
|
173
|
+
if (position >= 0)
|
|
174
|
+
wanted.add(position);
|
|
175
|
+
else
|
|
176
|
+
unresolved++;
|
|
177
|
+
}
|
|
178
|
+
for (let step = 0; step < unresolved; step++) {
|
|
179
|
+
const position = section.length - 1 - step;
|
|
180
|
+
if (position >= 0)
|
|
181
|
+
wanted.add(position);
|
|
182
|
+
}
|
|
183
|
+
if (wanted.size === 0)
|
|
184
|
+
continue;
|
|
185
|
+
touched[key] = [...wanted].sort((left, right) => left - right).map(position => section[position]);
|
|
186
|
+
}
|
|
187
|
+
return touched;
|
|
188
|
+
}
|
|
80
189
|
const segmentPattern = /^(\w+)(?:\[(?:(\d+)|(\w+)=([^\]]+))\])?$/;
|
|
81
190
|
export function resolvePart(definition, part) {
|
|
82
191
|
let current = definition;
|
|
@@ -111,7 +220,7 @@ function unescapePointer(segment) {
|
|
|
111
220
|
* `*_get`'in `part` sözdizimindeki seçiciyi (`steps[id=…]`, `fields[slug=…]`) patch yollarında da
|
|
112
221
|
* kabul edip indekse çeviriyoruz; çözülemeyen seçici, gövde platforma GİTMEDEN hata verir.
|
|
113
222
|
*/
|
|
114
|
-
export function resolvePatchPointer(document, path) {
|
|
223
|
+
export function resolvePatchPointer(document, path, readTool = 'workflow_get', op = '') {
|
|
115
224
|
if (!path.startsWith('/'))
|
|
116
225
|
throw new Error(`JSON Patch yolu '/' ile başlamalı: '${path}'`);
|
|
117
226
|
const segments = path.split('/').slice(1);
|
|
@@ -131,11 +240,21 @@ export function resolvePatchPointer(document, path) {
|
|
|
131
240
|
const [, key, field, value] = match;
|
|
132
241
|
const collection = current && typeof current === 'object' ? current[key] : undefined;
|
|
133
242
|
if (!Array.isArray(collection)) {
|
|
134
|
-
throw new Error(`Patch yolu çözülemedi: '${path}' — '${key}' bir dizi değil. Mevcut yapıyı
|
|
243
|
+
throw new Error(`Patch yolu çözülemedi: '${path}' — '${key}' bir dizi değil. Mevcut yapıyı ${readTool} view:'outline' ile okuyun.`);
|
|
135
244
|
}
|
|
136
245
|
const index = collection.findIndex(entry => entry && typeof entry === 'object' && String(entry[field]) === value);
|
|
137
246
|
if (index === -1) {
|
|
138
|
-
|
|
247
|
+
const available = collection
|
|
248
|
+
.map(entry => entry && typeof entry === 'object' ? entry[field] : undefined)
|
|
249
|
+
.filter(entry => entry !== undefined && entry !== null)
|
|
250
|
+
.map(entry => `'${String(entry)}'`);
|
|
251
|
+
// Seçici VAR OLAN bir öğeyi adresler; yeni öğe eklemenin yolu dizi sonu (`-`) segmentidir.
|
|
252
|
+
// 2026-09-06 koşusunda ajan eksik bir iteratee'yi `add` ile eklemeye çalıştı, mesaj yalnız
|
|
253
|
+
// "yok" dedi ve ajan diziyi 13 girdiyle baştan yazmak zorunda kaldı (S-5 · P0-2 Step 6).
|
|
254
|
+
const addHint = op === 'add'
|
|
255
|
+
? ` 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.`
|
|
256
|
+
: '';
|
|
257
|
+
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
258
|
}
|
|
140
259
|
resolved.push(key, String(index));
|
|
141
260
|
current = collection[index];
|
|
@@ -145,24 +264,30 @@ export function resolvePatchPointer(document, path) {
|
|
|
145
264
|
return rewritten ? { path: resolvedPath, note: `${path} → ${resolvedPath}` } : { path: resolvedPath };
|
|
146
265
|
}
|
|
147
266
|
/**
|
|
148
|
-
* Yanıtın `applied: N` demekle yetinmemesi için: her op'un hangi
|
|
267
|
+
* Yanıtın `applied: N` demekle yetinmemesi için: her op'un hangi öğeye indiğini adıyla söyler.
|
|
268
|
+
* Seçiciyle yazılan yol indekse çevrildiği için, indeksin hangi kayda denk geldiğini görmek
|
|
269
|
+
* sessiz veri bozulmasını önleyen tek sinyaldir (entity'de alan sırası değişebilir).
|
|
149
270
|
*/
|
|
150
271
|
export function describePatchTarget(document, path) {
|
|
151
|
-
const match = /^\/steps\/(\d+)(\/.*)?$/.exec(path);
|
|
272
|
+
const match = /^\/(steps|fields|indexes)\/(\d+)(\/.*)?$/.exec(path);
|
|
152
273
|
if (!match)
|
|
153
274
|
return path;
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
275
|
+
const collection = asArray(document[match[1]]);
|
|
276
|
+
const entry = collection[Number(match[2])];
|
|
277
|
+
if (!entry)
|
|
278
|
+
return `${path} → (dizide ${match[2]}. eleman YOK)`;
|
|
279
|
+
const label = String(entry.name ?? entry.slug ?? entry.id ?? '?');
|
|
280
|
+
const kind = entry.type ?? entry.dbType;
|
|
281
|
+
return `${path} → '${label}'${kind ? ` (${String(kind)}` + `, id ${String(entry.id ?? '?')})` : `, id ${String(entry.id ?? '?')}`}`;
|
|
158
282
|
}
|
|
159
|
-
export function resolvePatchOperations(document, operations) {
|
|
283
|
+
export function resolvePatchOperations(document, operations, readTool = 'workflow_get') {
|
|
160
284
|
const notes = [];
|
|
161
285
|
const targets = [];
|
|
162
286
|
const resolved = operations.map(operation => {
|
|
163
287
|
const path = typeof operation.path === 'string' ? operation.path : '';
|
|
164
|
-
const
|
|
165
|
-
const
|
|
288
|
+
const op = typeof operation.op === 'string' ? operation.op : '';
|
|
289
|
+
const outcome = resolvePatchPointer(document, path, readTool, op);
|
|
290
|
+
const from = typeof operation.from === 'string' ? resolvePatchPointer(document, operation.from, readTool, op) : undefined;
|
|
166
291
|
if (outcome.note)
|
|
167
292
|
notes.push(outcome.note);
|
|
168
293
|
if (from?.note)
|
|
@@ -172,3 +297,33 @@ export function resolvePatchOperations(document, operations) {
|
|
|
172
297
|
});
|
|
173
298
|
return { operations: resolved, notes, targets };
|
|
174
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Fonksiyon özeti (G-07): kaynak, ad, kapsam, imza, parametre listesi, gövde satır sayısı —
|
|
302
|
+
* gövdenin kendisi TAŞINMAZ (liste yanıtı MAX_RESPONSE_BYTES'ı şişirmesin). `function_patch`
|
|
303
|
+
* AÇILMADI: fonksiyonda tek büyük alan gövdedir ve gövde bütün olarak yazılır; kısmi güncellemeyi
|
|
304
|
+
* `function_update` mevcut kaydı okuyup eksik alanları doldurarak sağlar.
|
|
305
|
+
*/
|
|
306
|
+
export function functionOutline(definition) {
|
|
307
|
+
const parameters = asArray(definition.parameters);
|
|
308
|
+
const source = definition.source === 'workflow' ? 'workflow' : 'studio';
|
|
309
|
+
return {
|
|
310
|
+
id: definition.id,
|
|
311
|
+
source,
|
|
312
|
+
name: definition.name,
|
|
313
|
+
applicationId: definition.applicationId ?? null,
|
|
314
|
+
scope: source === 'workflow' ? null : (definition.scope ?? 'application'),
|
|
315
|
+
pageId: definition.pageId ?? null,
|
|
316
|
+
isAsync: definition.isAsync === true,
|
|
317
|
+
signature: functionSignature(definition),
|
|
318
|
+
parameters: parameters.map(parameter => ({
|
|
319
|
+
name: parameter.name,
|
|
320
|
+
type: parameter.type ?? 'any',
|
|
321
|
+
required: parameter.required === true,
|
|
322
|
+
defaultValue: parameter.defaultValue ?? null,
|
|
323
|
+
description: parameter.description ?? null
|
|
324
|
+
})),
|
|
325
|
+
description: definition.description ?? null,
|
|
326
|
+
bodyLines: typeof definition.body === 'string' && definition.body.length > 0 ? definition.body.split('\n').length : 0,
|
|
327
|
+
view: 'outline'
|
|
328
|
+
};
|
|
329
|
+
}
|
package/dist/knowledge/policy.js
CHANGED
|
@@ -11,6 +11,19 @@ export class PolicyBlockError extends Error {
|
|
|
11
11
|
this.name = 'PolicyBlockError';
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* `POLICY=warn` ve `policyOverride` kaçışları kuralın nereden geldiğine bakmaz: senkron
|
|
16
|
+
* `check`'lerden gelen bulgular da, platformdan okunarak üretilen bulgular da (WF-MF-001'in
|
|
17
|
+
* yayın durumu ön-denetimi) aynı kapıdan geçer. İki yerde iki farklı indirgeme olursa bir
|
|
18
|
+
* bulgu `policyOverride: true` ile de isteği durdurur ve kaçış yalanı çıkar.
|
|
19
|
+
*/
|
|
20
|
+
export function applyPolicyMode(config, findings, policyOverride = false) {
|
|
21
|
+
if (config.policyMode !== 'warn' && !policyOverride)
|
|
22
|
+
return findings;
|
|
23
|
+
return findings.map(finding => finding.severity === 'block'
|
|
24
|
+
? { ...finding, severity: 'warn', message: `${finding.message} [block → warn: ${policyOverride ? 'policyOverride' : 'POLICY=warn'}]` }
|
|
25
|
+
: finding);
|
|
26
|
+
}
|
|
14
27
|
export function evaluatePolicy(config, rules, module, definition, context, policyOverride = false) {
|
|
15
28
|
if (config.policyMode === 'off') {
|
|
16
29
|
logStep('politika', `${module}/${context.operation} · POLICY=off — lint çalıştırılmadı`);
|
|
@@ -18,11 +31,7 @@ export function evaluatePolicy(config, rules, module, definition, context, polic
|
|
|
18
31
|
}
|
|
19
32
|
const applicable = rules.filter(rule => rule.module === module && rule.appliesTo.includes(context.operation));
|
|
20
33
|
const raw = applicable.flatMap(rule => rule.check(definition, context));
|
|
21
|
-
const findings = config
|
|
22
|
-
? raw.map(finding => finding.severity === 'block'
|
|
23
|
-
? { ...finding, severity: 'warn', message: `${finding.message} [block → warn: ${policyOverride ? 'policyOverride' : 'POLICY=warn'}]` }
|
|
24
|
-
: finding)
|
|
25
|
-
: raw;
|
|
34
|
+
const findings = applyPolicyMode(config, raw, policyOverride);
|
|
26
35
|
logStep('politika', `${module}/${context.operation}${context.workflowKind ? ` (${context.workflowKind})` : ''} · ${applicable.length} kural denendi · ${findings.length === 0 ? 'bulgu yok' : `${findings.length} bulgu`}${policyOverride ? ' · policyOverride açık' : ''}`, findings.map(finding => `[${finding.ruleId}] ${finding.severity}: ${finding.message}`));
|
|
27
36
|
return findings;
|
|
28
37
|
}
|
|
@@ -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
|
+
}
|