@appaflytech/zeyrek-ai-mcp 0.0.3 → 0.0.4
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 +21 -7
- package/.env.production.example +42 -0
- package/README.md +14 -7
- package/dist/config.js +113 -47
- package/dist/knowledge/componentCatalog.js +474 -31
- package/dist/knowledge/componentEvents.js +150 -12
- package/dist/knowledge/errorPath.js +64 -0
- package/dist/knowledge/normalize.js +12 -1
- package/dist/knowledge/outlines.js +6 -0
- package/dist/knowledge/rules.js +184 -3
- package/dist/knowledge/styleResolve.js +485 -0
- package/dist/observability/trace.js +4 -0
- package/dist/platform/http.js +3 -0
- package/dist/platform/responses.js +80 -4
- package/dist/platform/screenshot.js +106 -0
- package/dist/resources/examples/layout-app-shell.json +368 -0
- package/dist/resources/examples/microservice-table-list.json +1 -0
- package/dist/resources/examples/middleware-authenticate.json +243 -47
- package/dist/resources/examples/workflow-basic.json +24 -2
- package/dist/resources/guides/component.md +6 -3
- package/dist/resources/guides/external-component.md +129 -0
- package/dist/resources/guides/layout.md +147 -0
- package/dist/resources/guides/microservice.md +35 -0
- package/dist/resources/guides/middleware.md +10 -0
- package/dist/resources/guides/page.md +132 -14
- package/dist/resources/guides/workflow.md +127 -2
- package/dist/server.js +2 -0
- package/dist/tools/externalComponents.js +285 -0
- package/dist/tools/layouts.js +48 -6
- package/dist/tools/microservices.js +2 -2
- package/dist/tools/pages.js +98 -30
- package/dist/tools/platformInfo.js +2 -2
- package/dist/tools/screens.js +36 -0
- package/dist/tools/workflows.js +3 -3
- package/package.json +4 -1
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"definition": {
|
|
8
8
|
"name": "Authenticate",
|
|
9
9
|
"slug": "authenticate",
|
|
10
|
+
"description": "Korunan uçların önünde koşar: token doğrular ve user değişkenini kurar.",
|
|
10
11
|
"type": "middleware",
|
|
11
12
|
"steps": [
|
|
12
13
|
{
|
|
@@ -14,39 +15,65 @@
|
|
|
14
15
|
"name": "start",
|
|
15
16
|
"type": "start",
|
|
16
17
|
"branches": [
|
|
17
|
-
{
|
|
18
|
+
{
|
|
19
|
+
"id": "<GUID-2>",
|
|
20
|
+
"name": "start",
|
|
21
|
+
"type": "success",
|
|
22
|
+
"nextStepId": "<GUID-3>"
|
|
23
|
+
}
|
|
18
24
|
]
|
|
19
25
|
},
|
|
20
26
|
{
|
|
21
27
|
"id": "<GUID-3>",
|
|
22
28
|
"name": "token",
|
|
29
|
+
"description": "Çerezden/başlıktan ham token değerini çıkarır.",
|
|
23
30
|
"type": "code",
|
|
24
31
|
"rule": {
|
|
25
32
|
"stepType": "code",
|
|
26
33
|
"expression": "return system.validateToken(cookie.APP_Token)"
|
|
27
34
|
},
|
|
28
35
|
"branches": [
|
|
29
|
-
{
|
|
36
|
+
{
|
|
37
|
+
"id": "<GUID-4>",
|
|
38
|
+
"name": "success",
|
|
39
|
+
"type": "success",
|
|
40
|
+
"nextStepId": "<GUID-5>"
|
|
41
|
+
}
|
|
30
42
|
]
|
|
31
43
|
},
|
|
32
44
|
{
|
|
33
45
|
"id": "<GUID-5>",
|
|
34
46
|
"name": "token_check",
|
|
47
|
+
"description": "Token yoksa 401 dalına, varsa doğrulamaya yönlendirir.",
|
|
35
48
|
"type": "condition",
|
|
36
49
|
"rule": {
|
|
37
50
|
"stepType": "condition",
|
|
38
51
|
"items": [
|
|
39
|
-
{
|
|
52
|
+
{
|
|
53
|
+
"expression": "token.data.isValid && token.data.claims.userId",
|
|
54
|
+
"branchId": "<GUID-6>"
|
|
55
|
+
}
|
|
40
56
|
]
|
|
41
57
|
},
|
|
42
58
|
"branches": [
|
|
43
|
-
{
|
|
44
|
-
|
|
59
|
+
{
|
|
60
|
+
"id": "<GUID-6>",
|
|
61
|
+
"name": "<GUID-6>",
|
|
62
|
+
"type": "success",
|
|
63
|
+
"nextStepId": "<GUID-8>"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"id": "<GUID-7>",
|
|
67
|
+
"name": "else",
|
|
68
|
+
"type": "success",
|
|
69
|
+
"nextStepId": "<GUID-14>"
|
|
70
|
+
}
|
|
45
71
|
]
|
|
46
72
|
},
|
|
47
73
|
{
|
|
48
74
|
"id": "<GUID-8>",
|
|
49
75
|
"name": "userTable",
|
|
76
|
+
"description": "Token sahibini users tablosundan rolleriyle birlikte okur.",
|
|
50
77
|
"type": "table",
|
|
51
78
|
"rule": {
|
|
52
79
|
"stepType": "table",
|
|
@@ -55,24 +82,62 @@
|
|
|
55
82
|
"operation": "get",
|
|
56
83
|
"isSingle": true,
|
|
57
84
|
"selectFields": [
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
|
|
85
|
+
{
|
|
86
|
+
"alias": "users",
|
|
87
|
+
"fieldId": "<id alanı id>",
|
|
88
|
+
"fieldSlug": "id"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"alias": "users",
|
|
92
|
+
"fieldId": "<email alanı id>",
|
|
93
|
+
"fieldSlug": "email"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"alias": "users",
|
|
97
|
+
"fieldId": "<first_name alanı id>",
|
|
98
|
+
"fieldSlug": "first_name"
|
|
99
|
+
}
|
|
61
100
|
],
|
|
62
101
|
"filters": [
|
|
63
|
-
{
|
|
102
|
+
{
|
|
103
|
+
"alias": "users",
|
|
104
|
+
"fieldId": "<id alanı id>",
|
|
105
|
+
"fieldSlug": "id",
|
|
106
|
+
"operator": "eq",
|
|
107
|
+
"source": "expression",
|
|
108
|
+
"value": "token.data.claims.userId",
|
|
109
|
+
"filterType": "single",
|
|
110
|
+
"conditionType": "and",
|
|
111
|
+
"isRequired": true,
|
|
112
|
+
"children": [],
|
|
113
|
+
"order": 0
|
|
114
|
+
}
|
|
64
115
|
],
|
|
65
116
|
"joins": [],
|
|
66
|
-
"sort": {
|
|
67
|
-
|
|
117
|
+
"sort": {
|
|
118
|
+
"name": "sortField",
|
|
119
|
+
"type": "sortType",
|
|
120
|
+
"source": "query-string"
|
|
121
|
+
},
|
|
122
|
+
"limit": {
|
|
123
|
+
"name": "limit",
|
|
124
|
+
"offset": "offset",
|
|
125
|
+
"source": "query-string"
|
|
126
|
+
}
|
|
68
127
|
},
|
|
69
128
|
"branches": [
|
|
70
|
-
{
|
|
129
|
+
{
|
|
130
|
+
"id": "<GUID-9>",
|
|
131
|
+
"name": "success",
|
|
132
|
+
"type": "success",
|
|
133
|
+
"nextStepId": "<GUID-10>"
|
|
134
|
+
}
|
|
71
135
|
]
|
|
72
136
|
},
|
|
73
137
|
{
|
|
74
138
|
"id": "<GUID-10>",
|
|
75
139
|
"name": "setUser",
|
|
140
|
+
"description": "Bulunan kullanıcıyı 'user' değişkenine yazar; sonraki uçlar bunu okur.",
|
|
76
141
|
"type": "set-user",
|
|
77
142
|
"rule": {
|
|
78
143
|
"stepType": "set-user",
|
|
@@ -80,12 +145,18 @@
|
|
|
80
145
|
"dataTransferObjectId": "<user DTO id — opsiyonel; verilirse workflow_middleware_variables şemayı listeler>"
|
|
81
146
|
},
|
|
82
147
|
"branches": [
|
|
83
|
-
{
|
|
148
|
+
{
|
|
149
|
+
"id": "<GUID-11>",
|
|
150
|
+
"name": "success",
|
|
151
|
+
"type": "success",
|
|
152
|
+
"nextStepId": "<GUID-12>"
|
|
153
|
+
}
|
|
84
154
|
]
|
|
85
155
|
},
|
|
86
156
|
{
|
|
87
157
|
"id": "<GUID-12>",
|
|
88
158
|
"name": "successResponse",
|
|
159
|
+
"description": "Kapıyı açar, istek asıl uca devam eder.",
|
|
89
160
|
"type": "response",
|
|
90
161
|
"rule": {
|
|
91
162
|
"stepType": "response",
|
|
@@ -98,6 +169,7 @@
|
|
|
98
169
|
{
|
|
99
170
|
"id": "<GUID-14>",
|
|
100
171
|
"name": "unauthorizedResponse",
|
|
172
|
+
"description": "Kimliksiz/geçersiz isteği 401 ile keser.",
|
|
101
173
|
"type": "response",
|
|
102
174
|
"rule": {
|
|
103
175
|
"stepType": "response",
|
|
@@ -117,78 +189,202 @@
|
|
|
117
189
|
"relationFieldTrap": "user_roles.role_id bir table adımında NESNE DEĞİL düz FK'dır (row_list her ilişki için join'i kendisi üretir, table adımı yalnız joins'te bildirileni çevirir). 'p.role_id.slug' undefined döner, roller sessizce boşalır ve Authorized her zaman false olur. Aşağıdaki ifade iki şekle de dayanır.",
|
|
118
190
|
"steps": [
|
|
119
191
|
{
|
|
120
|
-
"id": "<GUID-R1>",
|
|
192
|
+
"id": "<GUID-R1>",
|
|
193
|
+
"name": "rolesTable",
|
|
194
|
+
"type": "table",
|
|
121
195
|
"rule": {
|
|
122
|
-
"stepType": "table",
|
|
123
|
-
"
|
|
196
|
+
"stepType": "table",
|
|
197
|
+
"datasourceId": "<datasource id>",
|
|
198
|
+
"entityId": "<user_roles entity id>",
|
|
199
|
+
"operation": "get",
|
|
200
|
+
"alias": "user_roles",
|
|
201
|
+
"isSingle": false,
|
|
124
202
|
"selectFields": [
|
|
125
|
-
{
|
|
126
|
-
|
|
203
|
+
{
|
|
204
|
+
"alias": "user_roles",
|
|
205
|
+
"fieldId": "<user_roles.id>",
|
|
206
|
+
"fieldSlug": "id"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"alias": "user_roles",
|
|
210
|
+
"fieldId": "<user_roles.role_id>",
|
|
211
|
+
"fieldSlug": "role_id"
|
|
212
|
+
}
|
|
127
213
|
],
|
|
128
214
|
"filters": [
|
|
129
|
-
{
|
|
130
|
-
"
|
|
131
|
-
"
|
|
215
|
+
{
|
|
216
|
+
"alias": "user_roles",
|
|
217
|
+
"fieldId": "<user_roles.user_id>",
|
|
218
|
+
"operator": "eq",
|
|
219
|
+
"source": "expression",
|
|
220
|
+
"value": "userTable.data.id",
|
|
221
|
+
"filterType": "single",
|
|
222
|
+
"conditionType": "and",
|
|
223
|
+
"isRequired": true,
|
|
224
|
+
"children": [],
|
|
225
|
+
"order": 0
|
|
226
|
+
}
|
|
132
227
|
],
|
|
133
|
-
"joins": [],
|
|
134
|
-
"
|
|
135
|
-
"
|
|
228
|
+
"joins": [],
|
|
229
|
+
"fields": [],
|
|
230
|
+
"returnFields": [],
|
|
231
|
+
"sort": {
|
|
232
|
+
"name": "sortField",
|
|
233
|
+
"type": "sortType",
|
|
234
|
+
"source": "query-string"
|
|
235
|
+
},
|
|
236
|
+
"limit": {
|
|
237
|
+
"name": "limit",
|
|
238
|
+
"offset": "offset",
|
|
239
|
+
"source": "query-string"
|
|
240
|
+
}
|
|
136
241
|
},
|
|
137
242
|
"branches": [
|
|
138
|
-
{
|
|
139
|
-
|
|
243
|
+
{
|
|
244
|
+
"id": "<GUID-R2>",
|
|
245
|
+
"name": "success",
|
|
246
|
+
"type": "success",
|
|
247
|
+
"nextStepId": "<GUID-R3>"
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"id": "<GUID-R2b>",
|
|
251
|
+
"name": "fail",
|
|
252
|
+
"type": "fail",
|
|
253
|
+
"nextStepId": "<GUID-14>"
|
|
254
|
+
}
|
|
140
255
|
]
|
|
141
256
|
},
|
|
142
257
|
{
|
|
143
|
-
"id": "<GUID-R3>",
|
|
258
|
+
"id": "<GUID-R3>",
|
|
259
|
+
"name": "allRoles",
|
|
260
|
+
"type": "table",
|
|
144
261
|
"rule": {
|
|
145
|
-
"stepType": "table",
|
|
146
|
-
"
|
|
262
|
+
"stepType": "table",
|
|
263
|
+
"datasourceId": "<datasource id>",
|
|
264
|
+
"entityId": "<roles entity id>",
|
|
265
|
+
"operation": "get",
|
|
266
|
+
"alias": "roles",
|
|
267
|
+
"isSingle": false,
|
|
147
268
|
"selectFields": [
|
|
148
|
-
{
|
|
149
|
-
|
|
269
|
+
{
|
|
270
|
+
"alias": "roles",
|
|
271
|
+
"fieldId": "<roles.id>",
|
|
272
|
+
"fieldSlug": "id"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"alias": "roles",
|
|
276
|
+
"fieldId": "<roles.slug>",
|
|
277
|
+
"fieldSlug": "slug"
|
|
278
|
+
}
|
|
150
279
|
],
|
|
151
|
-
"filters": [],
|
|
152
|
-
"
|
|
153
|
-
"
|
|
280
|
+
"filters": [],
|
|
281
|
+
"joins": [],
|
|
282
|
+
"fields": [],
|
|
283
|
+
"returnFields": [],
|
|
284
|
+
"sort": {
|
|
285
|
+
"name": "sortField",
|
|
286
|
+
"type": "sortType",
|
|
287
|
+
"source": "query-string"
|
|
288
|
+
},
|
|
289
|
+
"limit": {
|
|
290
|
+
"name": "limit",
|
|
291
|
+
"offset": "offset",
|
|
292
|
+
"source": "query-string"
|
|
293
|
+
}
|
|
154
294
|
},
|
|
155
295
|
"branches": [
|
|
156
|
-
{
|
|
157
|
-
|
|
296
|
+
{
|
|
297
|
+
"id": "<GUID-R4>",
|
|
298
|
+
"name": "success",
|
|
299
|
+
"type": "success",
|
|
300
|
+
"nextStepId": "<GUID-R5>"
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"id": "<GUID-R4b>",
|
|
304
|
+
"name": "fail",
|
|
305
|
+
"type": "fail",
|
|
306
|
+
"nextStepId": "<GUID-14>"
|
|
307
|
+
}
|
|
158
308
|
]
|
|
159
309
|
},
|
|
160
310
|
{
|
|
161
|
-
"id": "<GUID-R5>",
|
|
311
|
+
"id": "<GUID-R5>",
|
|
312
|
+
"name": "setUser",
|
|
313
|
+
"description": "Bulunan kullanıcıyı 'user' değişkenine yazar; sonraki uçlar bunu okur.",
|
|
314
|
+
"type": "set-user",
|
|
162
315
|
"rule": {
|
|
163
316
|
"stepType": "set-user",
|
|
164
317
|
"expression": "(function () {\n var link = rolesTable.data || [];\n var all = allRoles.data || [];\n var slugs = link.map(function (ur) {\n var rid = ur.role_id && ur.role_id.id ? ur.role_id.id : ur.role_id;\n var match = all.filter(function (r) { return r.id === rid; })[0];\n return match && match.slug;\n }).filter(function (s) { return !!s; });\n return Object.assign({}, userTable.data, { roles: slugs, roles_csv: ',' + slugs.join(',') + ',' });\n})()",
|
|
165
318
|
"dataTransferObjectId": "<user DTO id — opsiyonel>"
|
|
166
319
|
},
|
|
167
|
-
"branches": [
|
|
320
|
+
"branches": [
|
|
321
|
+
{
|
|
322
|
+
"id": "<GUID-R6>",
|
|
323
|
+
"name": "success",
|
|
324
|
+
"type": "success",
|
|
325
|
+
"nextStepId": "<GUID-R7>"
|
|
326
|
+
}
|
|
327
|
+
]
|
|
168
328
|
},
|
|
169
329
|
{
|
|
170
|
-
"id": "<GUID-R7>",
|
|
171
|
-
"
|
|
330
|
+
"id": "<GUID-R7>",
|
|
331
|
+
"name": "roleGate",
|
|
332
|
+
"type": "condition",
|
|
333
|
+
"rule": {
|
|
334
|
+
"stepType": "condition",
|
|
335
|
+
"items": [
|
|
336
|
+
{
|
|
337
|
+
"expression": "Authorized(user.roles)",
|
|
338
|
+
"branchId": "<GUID-R8>"
|
|
339
|
+
}
|
|
340
|
+
]
|
|
341
|
+
},
|
|
172
342
|
"branches": [
|
|
173
|
-
{
|
|
174
|
-
|
|
343
|
+
{
|
|
344
|
+
"id": "<GUID-R8>",
|
|
345
|
+
"name": "<GUID-R8>",
|
|
346
|
+
"type": "success",
|
|
347
|
+
"nextStepId": null
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
"id": "<GUID-R9>",
|
|
351
|
+
"name": "else",
|
|
352
|
+
"type": "fail",
|
|
353
|
+
"nextStepId": "<GUID-F>"
|
|
354
|
+
}
|
|
175
355
|
]
|
|
176
356
|
},
|
|
177
357
|
{
|
|
178
|
-
"id": "<GUID-F>",
|
|
358
|
+
"id": "<GUID-F>",
|
|
359
|
+
"name": "forbiddenResponse",
|
|
360
|
+
"type": "response",
|
|
179
361
|
"rule": {
|
|
180
362
|
"stepType": "response",
|
|
181
363
|
"bodyExpression": "{ success: false, message: 'Bu işlem için yetkiniz yok.' }",
|
|
182
|
-
"httpStatusCode": 403,
|
|
364
|
+
"httpStatusCode": 403,
|
|
365
|
+
"headerExpression": "{ }"
|
|
183
366
|
},
|
|
184
367
|
"branches": []
|
|
185
368
|
}
|
|
186
369
|
],
|
|
187
|
-
"acceptance": "Dört testle kabul edilir: (1) rolü olan kullanıcı korumalı ucu çağırır → 200; (2) rolü olmayan kullanıcı → 403; (3) kimliksiz çağrı (microservice_execute anonymous:true) → 401; (4) roleIds boş bir uç aynı middleware'e bağlıyken kimliği doğrulanmış herkese açık kalır (Authorized boş rol listesinde true döner)."
|
|
370
|
+
"acceptance": "Dört testle kabul edilir: (1) rolü olan kullanıcı korumalı ucu çağırır → 200; (2) rolü olmayan kullanıcı → 403; (3) kimliksiz çağrı (microservice_execute anonymous:true) → 401; (4) roleIds boş bir uç aynı middleware'e bağlıyken kimliği doğrulanmış herkese açık kalır (Authorized boş rol listesinde true döner).",
|
|
371
|
+
"description": "Middleware çeşidi."
|
|
188
372
|
},
|
|
189
373
|
"consumptionExample": {
|
|
190
374
|
"note": "Kimlik kapsaması: uca middleware'i bağla (definition.middlewareIds) + owner filtresi expression yap. qm kanıtı: sy-users-get-my-profile.",
|
|
191
|
-
"middlewareIds": [
|
|
192
|
-
|
|
375
|
+
"middlewareIds": [
|
|
376
|
+
"<authenticate workflow id>"
|
|
377
|
+
],
|
|
378
|
+
"filter": {
|
|
379
|
+
"fieldId": "<owner alanı id>",
|
|
380
|
+
"operator": "eq",
|
|
381
|
+
"source": "expression",
|
|
382
|
+
"value": "user.id",
|
|
383
|
+
"filterType": "single",
|
|
384
|
+
"conditionType": "and",
|
|
385
|
+
"isRequired": false,
|
|
386
|
+
"children": [],
|
|
387
|
+
"order": 0
|
|
388
|
+
}
|
|
193
389
|
}
|
|
194
390
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_meta": {
|
|
3
3
|
"synthetic": true,
|
|
4
|
-
"note": "hr projesinde doğrulanmış şekil. Kurallar: step/branch id'leri GERÇEK GUID ve global benzersiz (RowAlreadyExists); DtoId verilen yerde Behavior zorunlu; table rule'da datasourceId + fieldId zorunlu; filtre value JavaScript ifadesi; preview girdisi previewPayload anahtarıyla."
|
|
4
|
+
"note": "hr projesinde doğrulanmış şekil. Kurallar: step/branch id'leri GERÇEK GUID ve global benzersiz (RowAlreadyExists); DtoId verilen yerde Behavior zorunlu; table rule'da datasourceId + fieldId zorunlu; filtre value JavaScript ifadesi; preview girdisi previewPayload anahtarıyla. bağlanmamış fail dalı hataya düşerse start'taki global-error dalına gider (IStep.cs:74-86)."
|
|
5
5
|
},
|
|
6
6
|
"definition": {
|
|
7
7
|
"name": "Product Lookup",
|
|
8
8
|
"slug": "product-lookup",
|
|
9
|
+
"description": "Ada göre tek ürün getirir; bulunamazsa hata yoluna düşer.",
|
|
9
10
|
"type": "workflow",
|
|
10
11
|
"parameterDtoId": "<girdi DTO id: { productName: string }>",
|
|
11
12
|
"returnDtoId": "<çıktı DTO id: { name, price }>",
|
|
@@ -22,12 +23,20 @@
|
|
|
22
23
|
"name": "start",
|
|
23
24
|
"type": "success",
|
|
24
25
|
"nextStepId": "<GUID-3>"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "<GUID-7>",
|
|
29
|
+
"name": "global-error",
|
|
30
|
+
"type": "global-error",
|
|
31
|
+
"nextStepId": "<GUID-8>"
|
|
25
32
|
}
|
|
26
33
|
]
|
|
27
34
|
},
|
|
28
35
|
{
|
|
29
36
|
"id": "<GUID-3>",
|
|
30
37
|
"name": "Load Product",
|
|
38
|
+
"description": "input.productName ile ürünü okur; tek kayıt bekler.",
|
|
39
|
+
"caution": "Ad benzersiz değil: aynı adda birden çok ürün varsa ilkini alır, hiç yoksa sessizce boş döner.",
|
|
31
40
|
"type": "table",
|
|
32
41
|
"rule": {
|
|
33
42
|
"stepType": "table",
|
|
@@ -77,6 +86,7 @@
|
|
|
77
86
|
{
|
|
78
87
|
"id": "<GUID-6>",
|
|
79
88
|
"name": "Response",
|
|
89
|
+
"description": "Bulunan ürünün adını 200 ile döner.",
|
|
80
90
|
"type": "response",
|
|
81
91
|
"rule": {
|
|
82
92
|
"stepType": "response",
|
|
@@ -85,10 +95,22 @@
|
|
|
85
95
|
"headerExpression": "{ }"
|
|
86
96
|
},
|
|
87
97
|
"branches": []
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"id": "<GUID-8>",
|
|
101
|
+
"name": "onError",
|
|
102
|
+
"description": "Akış patlarsa hata kodunu ve mesajını 500 ile döner.",
|
|
103
|
+
"type": "response",
|
|
104
|
+
"rule": {
|
|
105
|
+
"stepType": "response",
|
|
106
|
+
"bodyExpression": "({ code: error.code, message: error.message })",
|
|
107
|
+
"httpStatusCode": 500
|
|
108
|
+
},
|
|
109
|
+
"branches": []
|
|
88
110
|
}
|
|
89
111
|
]
|
|
90
112
|
},
|
|
91
113
|
"automationVariant": {
|
|
92
114
|
"note": "Automation: returnDtoId/parameterDtoId YASAK (validator reddeder), returnBehavior 'object' verilebilir; state=unready NORMALDİR ve tetiklemeyi etkilemez. Tetikleme kapısı automation nesnesindeki entityId + operation + isQueue (false=anlık, true=kuyruk; null=asla tetiklenmez!). steps hem üst seviyede hem automation içinde (PLT-007); response yasak, hata yolu revert."
|
|
93
115
|
}
|
|
94
|
-
}
|
|
116
|
+
}
|
|
@@ -38,8 +38,11 @@ component_get → tek tipin TAM sözleşmesi, üç katman birleşik:
|
|
|
38
38
|
- Yük `events[].payload`'dadır ama akışa **`event.data` ile GELMEZ**: motor yükü komponentin
|
|
39
39
|
KENDİ prop'una yazar (`FlowMachine.onEmit` → `setNode`) ve akışı emit'in `params`'ıyla başlatır.
|
|
40
40
|
Yani `payload` anahtarları prop adlarıdır ve `self.<anahtar>` ile okunur (ya da
|
|
41
|
-
`value.type:'property'`); `reads` alanı yükte olmayan prop'ları söyler. `event.data`
|
|
42
|
-
`html`
|
|
41
|
+
`value.type:'property'`); `reads` alanı yükte olmayan prop'ları söyler. `event.data`
|
|
42
|
+
`html`'in `fireEvent` aksiyonlarında ve `params` da gönderen 2026-08-27 kuşağında
|
|
43
|
+
(`eventcalendar` · `importwizard` · `kanban` · `signature` · `stepper`) dolar — `kanban` ve
|
|
44
|
+
`eventcalendar` yükü `self`'e HİÇ yazmaz, yalnız `event.data` ile okunur (ayrım
|
|
45
|
+
`component_get` sözleşme notlarında).
|
|
43
46
|
- Akış bağlama: `flow_create` → `page_schema_patch set_event`. İstisna: `html` komponentinin
|
|
44
47
|
aksiyonları kendi `flow` prop'uyla bağlanır (`platform_guide('html')`).
|
|
45
48
|
|
|
@@ -88,7 +91,7 @@ Her şema düğümünde iki sözlük vardır; ikisi de ortak render katmanında
|
|
|
88
91
|
|
|
89
92
|
| `appearance` | Değerler | Anlamı |
|
|
90
93
|
|---|---|---|
|
|
91
|
-
| `heightType` | `auto` · `fixed` | `auto`: içerik kadar (önerilen — Kural 1d); `fixed`: `blocks.h × 10px` |
|
|
94
|
+
| `heightType` | `auto` · `fixed` · `fill` | `auto`: içerik kadar (önerilen — Kural 1d); `fixed`: `blocks.h × 10px`; `fill`: **kalanı doldur** — ebeveynin bıraktığı yer (ızgarada `height:100%`, flex sütununda `flex:1 1 auto`, flex satırında `align-self:stretch`). Tam ekran yerleşim kabuğu bununla kurulur, bkz. `platform_guide('layout')` |
|
|
92
95
|
| `marginType` / `marginValue` | `normal` · `none` · `custom` + px | Dış boşluk: normal=5px, custom=`marginValue` |
|
|
93
96
|
| `paddingType` / `paddingValue` | `normal` · `none` · `custom` + px | Droppable kapların iç boşluğu: normal=10px |
|
|
94
97
|
| `alignType` | `left` · `center` · `right` | İçerik hizalama (destekleyen komponentlerde) |
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Kendi komponentinizi yazmak
|
|
2
|
+
|
|
3
|
+
Hazır katalog (`component_list`) ihtiyacınızı karşılamıyorsa üç seçeneğiniz var,
|
|
4
|
+
bu sırayla deneyin:
|
|
5
|
+
|
|
6
|
+
1. **Hazır komponenti zorlayın.** `component_get` ile prop'lara bakın; çoğu
|
|
7
|
+
"yok" sanılan davranış bir prop ya da event kombinasyonuyla çıkar.
|
|
8
|
+
2. **`html` kaçış kapısı.** Tek seferlik bir görsel için yeterli — bkz.
|
|
9
|
+
`platform_guide('html')`. Kalıcı, tekrar kullanılacak bir şey değilse burada
|
|
10
|
+
durun.
|
|
11
|
+
3. **Kendi komponentinizi yayınlayın.** Aynı ihtiyaç birden fazla sayfada
|
|
12
|
+
tekrarlanıyorsa, prop/event sözleşmesi gerekiyorsa ya da `html` içinde
|
|
13
|
+
yönetilemeyecek kadar davranış varsa doğru yol budur. Bu rehberin konusu.
|
|
14
|
+
|
|
15
|
+
Yayınlanan komponent platformun kendi komponentlerinden ayırt edilmez:
|
|
16
|
+
sayfaya sürüklenir, prop'ları property panelinde düzenlenir, event'leri flow'a
|
|
17
|
+
bağlanır, tema değişkenlerini alır. Studio toolbox'ında **"Your Components"**
|
|
18
|
+
başlığı altında listelenir.
|
|
19
|
+
|
|
20
|
+
## Akış
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
external_component_scaffold → yerel iskelet (element.mjs + manifest.json)
|
|
24
|
+
↓ (element.mjs'i yazın, manifest'i gerçek prop/event'lerinize göre düzenleyin)
|
|
25
|
+
external_component_publish → kayıt + paket yüklenir, doğrulama raporu döner
|
|
26
|
+
↓ (rapor block içeriyorsa düzeltip tekrar publish — depolamaya yazılmadı)
|
|
27
|
+
↓ taslak: Studio önizlemesinde görünür, yayınlanmış uygulamada görünmez
|
|
28
|
+
external_component_activate → yayına alır (yalnız metadata; kesinti yok)
|
|
29
|
+
↓
|
|
30
|
+
page_schema_patch → add_component ile sayfaya koyun
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Aktivasyondan sonra komponent `component_list` / `component_get` çıktısında
|
|
34
|
+
normal katalog kaydı gibi döner; `add_component` micro-op'unda `type` olarak
|
|
35
|
+
slug'ı kullanın.
|
|
36
|
+
|
|
37
|
+
## Sözleşme
|
|
38
|
+
|
|
39
|
+
Host element'e şema prop'larını **JS property** olarak yazar — attribute değil,
|
|
40
|
+
böylece dizi ve nesneler bozulmadan geçer. Yanına iki kanal koyar:
|
|
41
|
+
|
|
42
|
+
| Property | İçerik |
|
|
43
|
+
|---|---|
|
|
44
|
+
| şemadaki her prop | çözülmüş değer; yalnız değişen key'ler yeniden yazılır |
|
|
45
|
+
| `zxContext` | `{ elementId, appearance, states, isRequired, editorMode, language }` |
|
|
46
|
+
| `zxMachine` | platform yüzeyi (aşağıda) |
|
|
47
|
+
|
|
48
|
+
Element geriye **tek bir DOM olayıyla** konuşur: `zx-emit`, detail'i
|
|
49
|
+
`{ name, data?, setter?, flowId?, params? }`.
|
|
50
|
+
|
|
51
|
+
- `name` manifest'te bildirdiğiniz event adı olmalı; bildirilmemiş bir ad
|
|
52
|
+
flow'a bağlanamaz.
|
|
53
|
+
- `setter: true` verirseniz `data` içindeki değer aynı adlı prop'a geri yazılır —
|
|
54
|
+
`value` gibi iki yönlü davranan proplar için budur.
|
|
55
|
+
|
|
56
|
+
`zxMachine` sayılı bir yüzeydir; burada olmayan hiçbir şeye erişemezsiniz:
|
|
57
|
+
`getProps`, `getComponents`, `getComponentProps`, `getState`/`setState`,
|
|
58
|
+
`getVariable`/`setVariable`, `getStorage`/`setStorage`,
|
|
59
|
+
`getLanguage`/`setLanguage`, `t`, `checkAuthorization`, `user`, `pageParams`,
|
|
60
|
+
`emit`, `on`.
|
|
61
|
+
|
|
62
|
+
## Yasaklar — yayınlamayı reddeder
|
|
63
|
+
|
|
64
|
+
Paket sunucuda AST taramasından geçer. Şunlardan biri varsa paket **depolamaya
|
|
65
|
+
hiç yazılmaz**:
|
|
66
|
+
|
|
67
|
+
`eval`, `new Function` / `Function(...)`, dinamik `import()`,
|
|
68
|
+
`document.cookie`, `window.machine`, `navigator.serviceWorker.register`,
|
|
69
|
+
`document.write`, `localStorage.clear()` / `sessionStorage.clear()`.
|
|
70
|
+
|
|
71
|
+
Tarama AST üzerinde çalışır: bir string sabitinin içindeki `eval` kelimesi bulgu
|
|
72
|
+
değildir, `eval(...)` çağrısı bulgudur.
|
|
73
|
+
|
|
74
|
+
## Uyarılar — rapora yazılır, aktivasyonda onay ister
|
|
75
|
+
|
|
76
|
+
Dış ağ erişimi (`fetch`, `XMLHttpRequest`, `WebSocket`, `EventSource`),
|
|
77
|
+
doğrudan `localStorage`/`sessionStorage` erişimi, `window.X = ...` ataması,
|
|
78
|
+
`innerHTML`/`outerHTML` ataması, ve manifest'te bildirip element'te
|
|
79
|
+
karşılığını yazmadığınız proplar.
|
|
80
|
+
|
|
81
|
+
Uyarısı olan bir sürüm `acknowledgeWarnings: true` olmadan aktive edilemez.
|
|
82
|
+
Uyarıyı gördüğünüzde önce gerçekten gerekli mi diye bakın: veriyi flow ile
|
|
83
|
+
almak `fetch`'ten, `zxMachine.setStorage` doğrudan storage'dan iyidir.
|
|
84
|
+
|
|
85
|
+
## Kurallar
|
|
86
|
+
|
|
87
|
+
- Slug `x-` ile başlamak zorunda (`^x-[a-z][a-z0-9-]*$`). Bu önek platform
|
|
88
|
+
slug'larıyla çakışmayı imkânsız kılar.
|
|
89
|
+
- Tek `export default`, `HTMLElement` türeten bir sınıf.
|
|
90
|
+
- Prop adları DOM'u bozacak adlar olamaz: `id`, `class`, `className`, `style`,
|
|
91
|
+
`slot`, `name`, `children`, `innerHTML`, `outerHTML`, `textContent`, `zx*`,
|
|
92
|
+
`on*`.
|
|
93
|
+
- `manifest.definition.blocks` boş olamaz — ızgara ayak izi olmayan komponent
|
|
94
|
+
ölçeklenemez.
|
|
95
|
+
- Prop tipleri platformun tanıdığı kümeden olmalı (`text`, `long-text`,
|
|
96
|
+
`number`, `switch`, `dropdown`, `array`, `object`, `flow`, `icon`, `color`,
|
|
97
|
+
`date`, …). Yeni bir prop tipi uyduramazsınız.
|
|
98
|
+
- Paket 2 MB'ı geçemez.
|
|
99
|
+
- Renk, boşluk, tipografi için `--ng-*` tema değişkenlerini kullanın; sabit renk
|
|
100
|
+
yazarsanız komponent kullanıcının temasına uymaz.
|
|
101
|
+
|
|
102
|
+
## Sürümler ve geri alma
|
|
103
|
+
|
|
104
|
+
Paketler değişmezdir: aynı `(slug, version)` ikinci kez yayınlanamaz, düzeltme
|
|
105
|
+
yeni bir sürüm demektir. `external_component_versions` geçmişi ve her sürümün
|
|
106
|
+
doğrulama raporunu verir; `external_component_activate` ile eski bir sürümü
|
|
107
|
+
aktive etmek geri alma olarak çalışır. Aktivasyon yalnız metadata değiştirir —
|
|
108
|
+
platform yeniden başlamaz, açık oturumlar bozulmaz.
|
|
109
|
+
|
|
110
|
+
## Editor modu
|
|
111
|
+
|
|
112
|
+
`zxContext.editorMode` true olduğunda element Studio kanvasında statik bir
|
|
113
|
+
önizleme olarak duruyor: zamanlayıcı kurmayın, ağ çağrısı yapmayın, tıklamayı
|
|
114
|
+
işlemeyin. Kanvasta etkileşim host tarafından zaten engellenir, ama gereksiz iş
|
|
115
|
+
yapmamak kanvası hızlı tutar.
|
|
116
|
+
|
|
117
|
+
## Geliştirici kiti
|
|
118
|
+
|
|
119
|
+
Platform, npm paketi olmadan servis eder:
|
|
120
|
+
|
|
121
|
+
- `{studio}/component-kit/zeyrek-component.d.ts` — protokolün tip bildirimleri
|
|
122
|
+
- `{studio}/component-kit/harness.html` — platformsuz deneme sayfası
|
|
123
|
+
- `{studio}/component-kit/example-rating-stars.mjs` — çalışan örnek
|
|
124
|
+
- `GET {tenant}/{project}/components/external/manifest-schema` — manifest için
|
|
125
|
+
JSON Schema; izin verilen prop tipleri ve rezerve adlar sunucudaki kural
|
|
126
|
+
setinden **üretilir**, statik bir kopya olmadığı için sapmaz.
|
|
127
|
+
|
|
128
|
+
`external_component_scaffold` bu sözleşmeye uyan bir iskeleti yerel dizine
|
|
129
|
+
zaten yazar; kit, iskeleti elle düzenlerken referans olarak işinize yarar.
|