diff --git a/.gitignore b/.gitignore index 96484c7..80013cf 100644 --- a/.gitignore +++ b/.gitignore @@ -275,4 +275,9 @@ ai-docs/ # JMeter jmeter/results/ -!jmeter/results/.gitkeep \ No newline at end of file +!jmeter/results/.gitkeep +# vnext-forge LSP scaffold +.vnext-forge-lsp/ + +# vnext-forge LSP scaffold +.vnext-forge-lsp/ diff --git a/api-tests/error-boundary/error-boundary-test-workflow.http b/api-tests/error-boundary/error-boundary-test-workflow.http new file mode 100644 index 0000000..a3eac3d --- /dev/null +++ b/api-tests/error-boundary/error-boundary-test-workflow.http @@ -0,0 +1,57 @@ +@baseUrl = http://localhost:4201 +@apiVersion = 1 +@domain = core +@workflow = error-boundary-test-workflow +@mocklabBaseUrl = http://localhost:3002 + +############################################################################### +# Error boundary integration: HTTP 500 retries (task boundary), script error +# ignored (state boundary; errorTypes/errorCodes rules), rollback (action 2) +# then log (action 5), notify-test-state (onError action 4 + transition), then +# completed-state. Global errorBoundary includes onTimeout (action 3). +# Requires: API with MocklabBaseUrl, Mocklab seeded (POST api/test/error-endpoint +# returns 500). Task-level retries use PT2S delays (expect several seconds). +############################################################################### + +### Adim 1: Workflow baslat (sync; HTTP task retries may add delay) +# @name createErrorBoundaryInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "error-boundary-test-{{$timestamp}}", + "tags": ["integration-test", "error-boundary"], + "attributes": {} +} + +@errorBoundaryInstanceId = {{createErrorBoundaryInstance.response.body.$.id}} + +### Adim 2: Durum (notify-test-state uzerinden completed-state beklenir; global abort veya basarisizlikta error-final) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{errorBoundaryInstanceId}}/functions/state + +### Adim 3: Instance data (errorTestStarted, httpErrorHandled, errorIgnored, rollbackExecuted, rollbackAt, logOnlyExecuted, notifyExecuted, notifyAt) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{errorBoundaryInstanceId}}/functions/data + +############################################################################### +# Paket 5 — Rollback (2) + Log (5): Adim 3 yanitinda asagidakiler dogrulanir: +# - errorIgnored: true (ignore-test-state) +# - rollbackExecuted: true, rollbackAt: ISO8601 (rollback-test-state, ThrowError + rollback policy) +# - logOnlyExecuted: true (log-test-state; ThrowError + log policy, sonra LogOnlyMapping) +############################################################################### + +############################################################################### +# Paket 6 — Notify (action 4), timeoutPolicy, errorTypes/errorCodes +# +# Notify (action 4): notify-test-state ilk gorevde ThrowErrorMapping ile hata +# uretir; errorBoundary onError action 4 + transition ile akis completed-state'e +# gider. Adim 3 yanitinda notifyExecuted: true ve notifyAt: ISO8601 dogrulanir. +# +# timeoutPolicy: workflow attributes.errorBoundary.onTimeout.action = 3 (ignore). +# Tam timeout senaryosu bu dosyada ayri istek gerektirir; motor global timeout +# uyguladiginda bu politikanin secildigini workflow tanimindan dogrulayin. +# +# errorTypes / errorCodes: ignore-test-state errorBoundary kurali +# errorTypes: ["System.InvalidOperationException"], errorCodes: ["*"]. +# Ilk script gorevinin firlattigi istisna tipi bu listeyle eslesmeli; aksi halde +# ignore kurali tetiklenmez (motorun davranisina gore abort veya ust boundary). +############################################################################### diff --git a/api-tests/error-boundary/postman-error-boundary.json b/api-tests/error-boundary/postman-error-boundary.json new file mode 100644 index 0000000..4f97441 --- /dev/null +++ b/api-tests/error-boundary/postman-error-boundary.json @@ -0,0 +1,146 @@ +{ + "info": { + "_postman_id": "b383d938-352a-4425-a364-3e3f27ce9306", + "name": "vNext Test - Error Boundary", + "description": "Auto-generated from error-boundary-test-workflow.http.\nvNext workflow integration test collection for error-boundary.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:4201", + "type": "string" + }, + { + "key": "apiVersion", + "value": "1", + "type": "string" + }, + { + "key": "domain", + "value": "core", + "type": "string" + }, + { + "key": "workflow", + "value": "error-boundary-test-workflow", + "type": "string" + }, + { + "key": "mocklabBaseUrl", + "value": "http://localhost:3002", + "type": "string" + } + ], + "item": [ + { + "name": "Adim 1: Workflow baslat (sync; HTTP task retries may add delay)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"error-boundary-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"error-boundary\"],\n \"attributes\": {}\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"errorBoundaryInstanceId\", jsonData.id);", + " console.log(\"errorBoundaryInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Durum (notify-test-state uzerinden completed-state beklenir; global abort veya basarisizlikta error-final)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{errorBoundaryInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{errorBoundaryInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 3: Instance data (errorTestStarted, httpErrorHandled, errorIgnored, rollbackExecuted, rollbackAt, logOnlyExecuted, notifyExecuted, notifyAt)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{errorBoundaryInstanceId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{errorBoundaryInstanceId}}", + "functions", + "data" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/api-tests/extended-tasks/extended-tasks-test-workflow.http b/api-tests/extended-tasks/extended-tasks-test-workflow.http new file mode 100644 index 0000000..80e1f4c --- /dev/null +++ b/api-tests/extended-tasks/extended-tasks-test-workflow.http @@ -0,0 +1,59 @@ +@baseUrl = http://localhost:4201 +@apiVersion = 1 +@domain = core +@workflow = extended-tasks-test-workflow + +### ============================================================ +### TEST 1: Happy Path - Tum Task Tipleri Zinciri +### Dapr HTTP (1) → Dapr Service (3) → Dapr Binding (2) → +### Dapr PubSub (4) → Notification (10) → TriggerTransition (12) → +### SubProcess (14) → GetInstances (15) → Human Task (5) → Completed +### ============================================================ + +### Adim 1: Workflow Baslat +# @name createInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start +Content-Type: application/json + +{ + "key": "extended-tasks-test-{{$timestamp}}", + "tags": ["extended-tasks-test"], + "attributes": { + "testId": "extended-tasks-happy-path" + } +} + +### Response'dan instance ID'yi yakala +@instanceId = {{createInstance.response.body.$.id}} + +### Adim 2: Durum Kontrol - Auto zincir sonrasi human-task-state'de beklenmeli +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceId}}/functions/state + +### Adim 3: Instance Data Kontrol - Tum task sonuclarini kontrol et +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceId}} + +### Adim 4: Human Task Onayla (manuel transition) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceId}}/transitions/approve-human-task +Content-Type: application/json + +{} + +### Adim 5: Durum Kontrol - completed-state olmali +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceId}}/functions/state + +### Adim 6: Final Instance Data - Tum task sonuclari mevcut olmali +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceId}} + +### ============================================================ +### Beklenen Sonuclar: +### - initCompleted: true +### - taskResults.daprHttp.completed: true +### - taskResults.daprService.completed: true +### - taskResults.daprBinding.completed: true +### - taskResults.daprPubSub.completed: true +### - taskResults.notification.completed: true +### - taskResults.triggerTransition.completed: true +### - taskResults.subprocess.completed: true +### - taskResults.getInstances.completed: true +### - taskResults.humanTask.completed: true +### ============================================================ diff --git a/api-tests/extended-tasks/postman-extended-tasks.json b/api-tests/extended-tasks/postman-extended-tasks.json new file mode 100644 index 0000000..5e00926 --- /dev/null +++ b/api-tests/extended-tasks/postman-extended-tasks.json @@ -0,0 +1,221 @@ +{ + "info": { + "_postman_id": "382174e0-fc37-4d36-ba7b-653b40194f3c", + "name": "vNext Test - Extended Tasks", + "description": "Auto-generated from extended-tasks-test-workflow.http.\nvNext workflow integration test collection for extended-tasks.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:4201", + "type": "string" + }, + { + "key": "apiVersion", + "value": "1", + "type": "string" + }, + { + "key": "domain", + "value": "core", + "type": "string" + }, + { + "key": "workflow", + "value": "extended-tasks-test-workflow", + "type": "string" + } + ], + "item": [ + { + "name": "Adim 1: Workflow Baslat", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"extended-tasks-test-{{$timestamp}}\",\n \"tags\": [\"extended-tasks-test\"],\n \"attributes\": {\n \"testId\": \"extended-tasks-happy-path\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"instanceId\", jsonData.id);", + " console.log(\"instanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Durum Kontrol - Auto zincir sonrasi human-task-state'de beklenmeli", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 3: Instance Data Kontrol - Tum task sonuclarini kontrol et", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceId}}" + ] + } + }, + "response": [] + }, + { + "name": "Adim 4: Human Task Onayla (manuel transition)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceId}}/transitions/approve-human-task", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceId}}", + "transitions", + "approve-human-task" + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 5: Durum Kontrol - completed-state olmali", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 6: Final Instance Data - Tum task sonuclari mevcut olmali", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceId}}" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/api-tests/flow-types/flow-types-test.http b/api-tests/flow-types/flow-types-test.http new file mode 100644 index 0000000..d357eec --- /dev/null +++ b/api-tests/flow-types/flow-types-test.http @@ -0,0 +1,43 @@ +@baseUrl = http://localhost:4201 +@apiVersion = 1 +@domain = core + +### Grup 9: Flow Types — Core (C) and SubProcess (P) + +### ===== CORE FLOW TYPE TEST ===== + +### Adim 1: Core Flow Baslat +# @name startCore +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/core-flow-test/instances/start +Content-Type: application/json + +{ + "key": "core-test-{{$timestamp}}", + "tags": ["test", "core-flow"], + "attributes": {} +} + +### Core Instance ID yakala +@coreInstanceId = {{startCore.response.body.$.id}} + +### Adim 2: Core State Kontrol (auto transition ile core-completed'a gecmis olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/core-flow-test/instances/{{coreInstanceId}}/functions/state + +### ===== SUBPROCESS FLOW TYPE TEST ===== + +### Adim 3: SubProcess Flow Baslat +# @name startSubProcess +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/subprocess-flow-test/instances/start +Content-Type: application/json + +{ + "key": "subprocess-test-{{$timestamp}}", + "tags": ["test", "subprocess-flow"], + "attributes": {} +} + +### SubProcess Instance ID yakala +@subProcessInstanceId = {{startSubProcess.response.body.$.id}} + +### Adim 4: SubProcess State Kontrol +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/subprocess-flow-test/instances/{{subProcessInstanceId}}/functions/state diff --git a/api-tests/flow-types/postman-flow-types.json b/api-tests/flow-types/postman-flow-types.json new file mode 100644 index 0000000..cdca4e1 --- /dev/null +++ b/api-tests/flow-types/postman-flow-types.json @@ -0,0 +1,193 @@ +{ + "info": { + "_postman_id": "c51b9d51-e6b7-4435-87bd-d88e5a5cdf7b", + "name": "vNext Test - Flow Types", + "description": "Auto-generated from flow-types-test.http.\nvNext workflow integration test collection for flow-types.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:4201", + "type": "string" + }, + { + "key": "apiVersion", + "value": "1", + "type": "string" + }, + { + "key": "domain", + "value": "core", + "type": "string" + } + ], + "item": [ + { + "name": "Section", + "item": [ + { + "name": "Adim 1: Core Flow Baslat", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/core-flow-test/instances/start", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "core-flow-test", + "instances", + "start" + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"core-test-{{$timestamp}}\",\n \"tags\": [\"test\", \"core-flow\"],\n \"attributes\": {}\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"coreInstanceId\", jsonData.id);", + " console.log(\"coreInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Core State Kontrol (auto transition ile core-completed'a gecmis olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/core-flow-test/instances/{{coreInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "core-flow-test", + "instances", + "{{coreInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Section", + "item": [ + { + "name": "Adim 3: SubProcess Flow Baslat", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/subprocess-flow-test/instances/start", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "subprocess-flow-test", + "instances", + "start" + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"subprocess-test-{{$timestamp}}\",\n \"tags\": [\"test\", \"subprocess-flow\"],\n \"attributes\": {}\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"subProcessInstanceId\", jsonData.id);", + " console.log(\"subProcessInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 4: SubProcess State Kontrol", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/subprocess-flow-test/instances/{{subProcessInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "subprocess-flow-test", + "instances", + "{{subProcessInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file diff --git a/api-tests/instance-management/instance-management-test-workflow.http b/api-tests/instance-management/instance-management-test-workflow.http new file mode 100644 index 0000000..ccf37ef --- /dev/null +++ b/api-tests/instance-management/instance-management-test-workflow.http @@ -0,0 +1,240 @@ +@baseUrl = http://localhost:4201 +@apiVersion = 1 +@domain = core +@workflow = instance-management-test-workflow + +############################################################################### +# TEST 1: Create multiple instances (categories / priorities) and move states +# Instance 1: active-state (finance, 1) +# Instance 2: processing-state (finance, 2) after "process" +# Instance 3: completed-state (hr, 1) after "fast-complete" +############################################################################### + +### Instance 1: category finance, priority 1 (remains active) +# @name createInstanceMgmt1 +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "instance-mgmt-filter-1-{{$timestamp}}", + "tags": ["integration-test", "instance-management"], + "attributes": { + "category": "finance", + "priority": 1 + } +} + +@instanceMgmtId1 = {{createInstanceMgmt1.response.body.$.id}} + +### Instance 2: category finance, priority 2 -> processing-state +# @name createInstanceMgmt2 +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "instance-mgmt-filter-2-{{$timestamp}}", + "tags": ["integration-test", "instance-management"], + "attributes": { + "category": "finance", + "priority": 2 + } +} + +@instanceMgmtId2 = {{createInstanceMgmt2.response.body.$.id}} + +### Instance 2: move to processing-state +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceMgmtId2}}/transitions/process?sync=true +Content-Type: application/json + +{} + +### Instance 3: category hr, priority 1 -> completed-state (fast path) +# @name createInstanceMgmt3 +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "instance-mgmt-filter-3-{{$timestamp}}", + "tags": ["integration-test", "instance-management"], + "attributes": { + "category": "hr", + "priority": 1 + } +} + +@instanceMgmtId3 = {{createInstanceMgmt3.response.body.$.id}} + +### Instance 3: complete from active-state +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceMgmtId3}}/transitions/fast-complete?sync=true +Content-Type: application/json + +{} + +############################################################################### +# TEST 2: List / filter / sort / pagination +############################################################################### + +### Filter by category (finance) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances?filter=attributes.category%20eq%20%27finance%27 + +### Filter by state key +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances?filter=state%20eq%20%27active-state%27 + +### Filter by status (active) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances?filter=status%20eq%20%27A%27 + +### Sort descending by createdAt +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances?sort=-createdAt + +### Pagination +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances?page=1&pageSize=2 + +############################################################################### +# TEST 3: Idempotent start (same business key twice -> same instance id) +############################################################################### + +### First start with fixed key +# @name idempotentStart1 +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "instance-mgmt-idempotent-key", + "tags": ["integration-test", "instance-management", "idempotent"], + "attributes": { + "category": "finance", + "priority": 1 + } +} + +@idempotentInstanceId1 = {{idempotentStart1.response.body.$.id}} + +### Second start with same key (should return same instance) +# @name idempotentStart2 +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "instance-mgmt-idempotent-key", + "tags": ["integration-test", "instance-management", "idempotent"], + "attributes": { + "category": "hr", + "priority": 9 + } +} + +@idempotentInstanceId2 = {{idempotentStart2.response.body.$.id}} + +### Compare: idempotentInstanceId1 should equal idempotentInstanceId2 +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{idempotentInstanceId1}}/functions/state + +############################################################################### +# TEST 4: Instance data endpoint +############################################################################### + +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceMgmtId1}}/functions/data + +############################################################################### +# TEST 5: subType 4 — suspended-state (start → process → suspend) +############################################################################### + +### Start instance for subType 4 path +# @name createInstanceSubtypeSuspended +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "instance-mgmt-subtype-4-{{$timestamp}}", + "tags": ["integration-test", "instance-management", "subtype-suspended"], + "attributes": { + "category": "finance", + "priority": 1 + } +} + +@subtypeSuspendedInstanceId = {{createInstanceSubtypeSuspended.response.body.$.id}} + +### Move to processing-state +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeSuspendedInstanceId}}/transitions/process?sync=true +Content-Type: application/json + +{} + +### Suspend → suspended-state (subType 4) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeSuspendedInstanceId}}/transitions/suspend?sync=true +Content-Type: application/json + +{} + +### Verify state is suspended-state (check response: current state / effective state) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeSuspendedInstanceId}}/functions/state + +############################################################################### +# TEST 6: subType 5 — busy-state (start → process → set-busy) +############################################################################### + +### Start instance for subType 5 path +# @name createInstanceSubtypeBusy +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "instance-mgmt-subtype-5-{{$timestamp}}", + "tags": ["integration-test", "instance-management", "subtype-busy"], + "attributes": { + "category": "finance", + "priority": 1 + } +} + +@subtypeBusyInstanceId = {{createInstanceSubtypeBusy.response.body.$.id}} + +### Move to processing-state +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeBusyInstanceId}}/transitions/process?sync=true +Content-Type: application/json + +{} + +### Set busy → busy-state (subType 5) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeBusyInstanceId}}/transitions/set-busy?sync=true +Content-Type: application/json + +{} + +### Verify state is busy-state +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeBusyInstanceId}}/functions/state + +############################################################################### +# TEST 7: subType 6 — human-state (start → process → assign-human) +############################################################################### + +### Start instance for subType 6 path +# @name createInstanceSubtypeHuman +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "instance-mgmt-subtype-6-{{$timestamp}}", + "tags": ["integration-test", "instance-management", "subtype-human"], + "attributes": { + "category": "finance", + "priority": 1 + } +} + +@subtypeHumanInstanceId = {{createInstanceSubtypeHuman.response.body.$.id}} + +### Move to processing-state +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeHumanInstanceId}}/transitions/process?sync=true +Content-Type: application/json + +{} + +### Assign human → human-state (subType 6) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeHumanInstanceId}}/transitions/assign-human?sync=true +Content-Type: application/json + +{} + +### Verify state is human-state +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeHumanInstanceId}}/functions/state diff --git a/api-tests/instance-management/postman-instance-management.json b/api-tests/instance-management/postman-instance-management.json new file mode 100644 index 0000000..498c9d5 --- /dev/null +++ b/api-tests/instance-management/postman-instance-management.json @@ -0,0 +1,1176 @@ +{ + "info": { + "_postman_id": "87a260c7-e4f4-40c2-8067-e329abdaf7a5", + "name": "vNext Test - Instance Management", + "description": "Auto-generated from instance-management-test-workflow.http.\nvNext workflow integration test collection for instance-management.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:4201", + "type": "string" + }, + { + "key": "apiVersion", + "value": "1", + "type": "string" + }, + { + "key": "domain", + "value": "core", + "type": "string" + }, + { + "key": "workflow", + "value": "instance-management-test-workflow", + "type": "string" + } + ], + "item": [ + { + "name": "TEST 1: Create multiple instances (categories / priorities) and move states", + "item": [ + { + "name": "Instance 1: category finance, priority 1 (remains active)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"instance-mgmt-filter-1-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"instance-management\"],\n \"attributes\": {\n \"category\": \"finance\",\n \"priority\": 1\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"instanceMgmtId1\", jsonData.id);", + " console.log(\"instanceMgmtId1 set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Instance 2: category finance, priority 2 -> processing-state", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"instance-mgmt-filter-2-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"instance-management\"],\n \"attributes\": {\n \"category\": \"finance\",\n \"priority\": 2\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"instanceMgmtId2\", jsonData.id);", + " console.log(\"instanceMgmtId2 set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Instance 2: move to processing-state", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceMgmtId2}}/transitions/process?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceMgmtId2}}", + "transitions", + "process" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Instance 3: category hr, priority 1 -> completed-state (fast path)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"instance-mgmt-filter-3-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"instance-management\"],\n \"attributes\": {\n \"category\": \"hr\",\n \"priority\": 1\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"instanceMgmtId3\", jsonData.id);", + " console.log(\"instanceMgmtId3 set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Instance 3: complete from active-state", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceMgmtId3}}/transitions/fast-complete?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceMgmtId3}}", + "transitions", + "fast-complete" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 2: List / filter / sort / pagination", + "item": [ + { + "name": "Filter by category (finance)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances?filter=attributes.category%20eq%20%27finance%27", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances" + ], + "query": [ + { + "key": "filter", + "value": "attributes.category eq 'finance'" + } + ] + } + }, + "response": [] + }, + { + "name": "Filter by state key", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances?filter=state%20eq%20%27active-state%27", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances" + ], + "query": [ + { + "key": "filter", + "value": "state eq 'active-state'" + } + ] + } + }, + "response": [] + }, + { + "name": "Filter by status (active)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances?filter=status%20eq%20%27A%27", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances" + ], + "query": [ + { + "key": "filter", + "value": "status eq 'A'" + } + ] + } + }, + "response": [] + }, + { + "name": "Sort descending by createdAt", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances?sort=-createdAt", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances" + ], + "query": [ + { + "key": "sort", + "value": "-createdAt" + } + ] + } + }, + "response": [] + }, + { + "name": "Pagination", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances?page=1&pageSize=2", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances" + ], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "pageSize", + "value": "2" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 3: Idempotent start (same business key twice -> same instance id)", + "item": [ + { + "name": "First start with fixed key", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"instance-mgmt-idempotent-key\",\n \"tags\": [\"integration-test\", \"instance-management\", \"idempotent\"],\n \"attributes\": {\n \"category\": \"finance\",\n \"priority\": 1\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"idempotentInstanceId1\", jsonData.id);", + " console.log(\"idempotentInstanceId1 set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Second start with same key (should return same instance)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"instance-mgmt-idempotent-key\",\n \"tags\": [\"integration-test\", \"instance-management\", \"idempotent\"],\n \"attributes\": {\n \"category\": \"hr\",\n \"priority\": 9\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"idempotentInstanceId2\", jsonData.id);", + " console.log(\"idempotentInstanceId2 set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Compare: idempotentInstanceId1 should equal idempotentInstanceId2", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{idempotentInstanceId1}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{idempotentInstanceId1}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 4: Instance data endpoint", + "item": [ + { + "name": "GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{in", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceMgmtId1}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceMgmtId1}}", + "functions", + "data" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 5: subType 4 — suspended-state (start → process → suspend)", + "item": [ + { + "name": "Start instance for subType 4 path", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"instance-mgmt-subtype-4-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"instance-management\", \"subtype-suspended\"],\n \"attributes\": {\n \"category\": \"finance\",\n \"priority\": 1\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"subtypeSuspendedInstanceId\", jsonData.id);", + " console.log(\"subtypeSuspendedInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Move to processing-state", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeSuspendedInstanceId}}/transitions/process?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{subtypeSuspendedInstanceId}}", + "transitions", + "process" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Suspend → suspended-state (subType 4)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeSuspendedInstanceId}}/transitions/suspend?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{subtypeSuspendedInstanceId}}", + "transitions", + "suspend" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Verify state is suspended-state (check response: current state / effective state)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeSuspendedInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{subtypeSuspendedInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 6: subType 5 — busy-state (start → process → set-busy)", + "item": [ + { + "name": "Start instance for subType 5 path", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"instance-mgmt-subtype-5-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"instance-management\", \"subtype-busy\"],\n \"attributes\": {\n \"category\": \"finance\",\n \"priority\": 1\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"subtypeBusyInstanceId\", jsonData.id);", + " console.log(\"subtypeBusyInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Move to processing-state", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeBusyInstanceId}}/transitions/process?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{subtypeBusyInstanceId}}", + "transitions", + "process" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Set busy → busy-state (subType 5)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeBusyInstanceId}}/transitions/set-busy?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{subtypeBusyInstanceId}}", + "transitions", + "set-busy" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Verify state is busy-state", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeBusyInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{subtypeBusyInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 7: subType 6 — human-state (start → process → assign-human)", + "item": [ + { + "name": "Start instance for subType 6 path", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"instance-mgmt-subtype-6-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"instance-management\", \"subtype-human\"],\n \"attributes\": {\n \"category\": \"finance\",\n \"priority\": 1\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"subtypeHumanInstanceId\", jsonData.id);", + " console.log(\"subtypeHumanInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Move to processing-state", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeHumanInstanceId}}/transitions/process?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{subtypeHumanInstanceId}}", + "transitions", + "process" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Assign human → human-state (subType 6)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeHumanInstanceId}}/transitions/assign-human?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{subtypeHumanInstanceId}}", + "transitions", + "assign-human" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Verify state is human-state", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{subtypeHumanInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{subtypeHumanInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file diff --git a/api-tests/lifecycle-transitions/lifecycle-transitions-test-workflow.http b/api-tests/lifecycle-transitions/lifecycle-transitions-test-workflow.http new file mode 100644 index 0000000..cdad213 --- /dev/null +++ b/api-tests/lifecycle-transitions/lifecycle-transitions-test-workflow.http @@ -0,0 +1,313 @@ +@baseUrl = http://localhost:4201 +@apiVersion = 1 +@domain = core +@workflow = lifecycle-transitions-test-workflow + +############################################################################### +# TEST 1: Happy Path (testPath=pass) +# Tests: start, manual transition, ITransitionMapping, onEntries, onExits, +# auto transition (complementary rules), scheduled timer, +# auto AlwaysTrue, manual to Final(Success) +############################################################################### + +### Adim 1: Workflow Baslat (testPath=pass) +# @name createPassInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "lifecycle-pass-test-{{$timestamp}}", + "tags": ["integration-test", "lifecycle", "pass-path"], + "attributes": { + "testPath": "pass" + } +} + +### Response'dan instance ID yakala +@passInstanceId = {{createPassInstance.response.body.$.id}} + +### Adim 2: Durum Kontrol (initialize-state olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/functions/state + +### Adim 3: Manuel Transition - Move to Processing (ITransitionMapping test) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/transitions/move-to-processing?sync=true +Content-Type: application/json + +{} + +### Adim 4: Durum Kontrol (auto-passed-state olmali, auto transition testPath=pass rule calisti) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/functions/state + +### Adim 5: 15 saniye bekle (scheduled timer 10s) ve durum kontrol +# timer-triggered-state -> (auto AlwaysTrue) -> pre-complete-state olmali +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/functions/state + +### Adim 6: Manuel Transition - Complete Workflow +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/transitions/complete-workflow?sync=true +Content-Type: application/json + +{} + +### Adim 7: Durum Kontrol (completed-state, Final/Success olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/functions/state + +############################################################################### +# TEST 2: Fail Path (testPath=fail) +# Tests: complementary auto rule (fail path), Final(Error) state subtype +############################################################################### + +### Adim 1: Workflow Baslat (testPath=fail) +# @name createFailInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "lifecycle-fail-test-{{$timestamp}}", + "tags": ["integration-test", "lifecycle", "fail-path"], + "attributes": { + "testPath": "fail" + } +} + +@failInstanceId = {{createFailInstance.response.body.$.id}} + +### Adim 2: Manuel Transition - Move to Processing +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{failInstanceId}}/transitions/move-to-processing?sync=true +Content-Type: application/json + +{} + +### Adim 3: Durum Kontrol (auto-failed-state, Final/Error olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{failInstanceId}}/functions/state + +############################################################################### +# TEST 3: Default Auto Transition (triggerKind:10) +# Tests: testPath=unknown, neither pass nor fail rule matches -> default auto +############################################################################### + +### Adim 1: Workflow Baslat (testPath=unknown) +# @name createDefaultInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "lifecycle-default-test-{{$timestamp}}", + "tags": ["integration-test", "lifecycle", "default-path"], + "attributes": { + "testPath": "unknown" + } +} + +@defaultInstanceId = {{createDefaultInstance.response.body.$.id}} + +### Adim 2: Manuel Transition - Move to Processing +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{defaultInstanceId}}/transitions/move-to-processing?sync=true +Content-Type: application/json + +{} + +### Adim 3: Durum Kontrol (default-fallback-state -> completed-state olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{defaultInstanceId}}/functions/state + +############################################################################### +# TEST 4: Idempotent Start +# Tests: same key returns existing instance, no duplicate created +############################################################################### + +### Adim 1: Workflow Baslat +# @name createIdempotentInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "lifecycle-idempotent-key", + "tags": ["integration-test", "lifecycle", "idempotent"], + "attributes": { + "testPath": "pass" + } +} + +@idempotentInstanceId = {{createIdempotentInstance.response.body.$.id}} + +### Adim 2: Ayni Key ile Tekrar Baslat (ayni instance donmeli) +# @name createIdempotentInstance2 +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "lifecycle-idempotent-key", + "tags": ["integration-test"], + "attributes": { + "testPath": "pass" + } +} + +@idempotentInstanceId2 = {{createIdempotentInstance2.response.body.$.id}} + +### Karsilastir: idempotentInstanceId == idempotentInstanceId2 olmali + +############################################################################### +# TEST 5: Cancel Transition +# Tests: cancel from any state -> terminated-state (Final/Terminated) +############################################################################### + +### Adim 1: Workflow Baslat +# @name createCancelInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "lifecycle-cancel-test-{{$timestamp}}", + "tags": ["integration-test", "lifecycle", "cancel"], + "attributes": { + "testPath": "pass" + } +} + +@cancelInstanceId = {{createCancelInstance.response.body.$.id}} + +### Adim 2: Cancel Workflow +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{cancelInstanceId}}/transitions/cancel-workflow?sync=true +Content-Type: application/json + +{} + +### Adim 3: Durum Kontrol (terminated-state, Final/Terminated olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{cancelInstanceId}}/functions/state + +### ============================================================ +### TEST: Exit Transition +### ============================================================ + +### Adim 1: Workflow Baslat (Exit Test) +# @name exitCreate +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start +Content-Type: application/json + +{ + "key": "exit-test-{{$timestamp}}", + "tags": ["exit-test"], + "attributes": { + "testId": "exit-test" + } +} + +### Response'dan instance ID'yi yakala +@exitInstanceId = {{exitCreate.response.body.$.id}} + +### Adim 2: Exit Transition Tetikle (initialize-state'den) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{exitInstanceId}}/transitions/exit-workflow +Content-Type: application/json + +{} + +### Adim 3: Durum Kontrol - terminated-state olmali +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{exitInstanceId}}/functions/state + +### Adim 4: Instance Data Kontrol - exitExecuted=true olmali +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{exitInstanceId}} + +### ============================================================ +### TEST: Schedule Cancel (Manual ile timer iptali) +### ============================================================ + +### Adim 1: Workflow Baslat (Schedule Cancel Test) +# @name scheduleCancelCreate +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start +Content-Type: application/json + +{ + "key": "schedule-cancel-test-{{$timestamp}}", + "tags": ["schedule-cancel-test"], + "attributes": { + "testId": "schedule-cancel-test", + "testPath": "pass" + } +} + +### Response'dan instance ID'yi yakala +@scheduleCancelInstanceId = {{scheduleCancelCreate.response.body.$.id}} + +### Adim 2: Durum Kontrol - auto-passed-state olmali (auto transitions sonrasi) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{scheduleCancelInstanceId}}/functions/state + +### Adim 3: Timer tetiklenmeden cancel-schedule-manually transition cagir +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{scheduleCancelInstanceId}}/transitions/cancel-schedule-manually +Content-Type: application/json + +{} + +### Adim 4: Durum Kontrol - pre-complete-state olmali (timer iptali basarili) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{scheduleCancelInstanceId}}/functions/state + +### ============================================================ +### TEST: Reschedule Timer ($self transition) +### ============================================================ + +### Adim 1: Workflow Baslat (Reschedule Test) +# @name rescheduleCreate +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start +Content-Type: application/json + +{ + "key": "reschedule-test-{{$timestamp}}", + "tags": ["reschedule-test"], + "attributes": { + "testId": "reschedule-test", + "testPath": "pass" + } +} + +### Response'dan instance ID'yi yakala +@rescheduleInstanceId = {{rescheduleCreate.response.body.$.id}} + +### Adim 2: Durum Kontrol - auto-passed-state olmali +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rescheduleInstanceId}}/functions/state + +### Adim 3: Reschedule timer ($self transition - timer sifirlanmali) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rescheduleInstanceId}}/transitions/reschedule-timer +Content-Type: application/json + +{} + +### Adim 4: Durum Kontrol - hala auto-passed-state olmali ($self = ayni state) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rescheduleInstanceId}}/functions/state + +### ============================================================ +### TEST: QueryRoles ve Transition Roles +### ============================================================ + +### Adim 1: Workflow Baslat (Roles Test) +# @name rolesCreate +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start +Content-Type: application/json + +{ + "key": "roles-test-{{$timestamp}}", + "tags": ["roles-test"], + "attributes": { + "testId": "roles-test", + "testPath": "pass" + } +} + +### Response'dan instance ID'yi yakala +@rolesInstanceId = {{rolesCreate.response.body.$.id}} + +### Adim 2: QueryRoles ile yetki kontrolu - test-viewer izinli olmali (workflow-level) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rolesInstanceId}}/functions/authorize?role=test-viewer + +### Adim 3: move-to-processing transition (test-operator rolu ile) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rolesInstanceId}}/transitions/move-to-processing +Content-Type: application/json + +{} + +### Adim 4: Durum Kontrol - processing-state olmali +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rolesInstanceId}}/functions/state + +### Adim 5: QueryRoles - processing-state'de test-processor izinli, test-viewer reddedilmis olmali +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rolesInstanceId}}/functions/authorize?role=test-processor + +### Adim 6: QueryRoles - test-viewer deny olmali (state-level override) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rolesInstanceId}}/functions/authorize?role=test-viewer diff --git a/api-tests/lifecycle-transitions/postman-lifecycle-transitions.json b/api-tests/lifecycle-transitions/postman-lifecycle-transitions.json new file mode 100644 index 0000000..f97b393 --- /dev/null +++ b/api-tests/lifecycle-transitions/postman-lifecycle-transitions.json @@ -0,0 +1,1474 @@ +{ + "info": { + "_postman_id": "bcbe98ff-758a-4921-8cf8-78b5db33ea2b", + "name": "vNext Test - Lifecycle Transitions", + "description": "Auto-generated from lifecycle-transitions-test-workflow.http.\nvNext workflow integration test collection for lifecycle-transitions.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:4201", + "type": "string" + }, + { + "key": "apiVersion", + "value": "1", + "type": "string" + }, + { + "key": "domain", + "value": "core", + "type": "string" + }, + { + "key": "workflow", + "value": "lifecycle-transitions-test-workflow", + "type": "string" + } + ], + "item": [ + { + "name": "TEST 1: Happy Path (testPath=pass)", + "item": [ + { + "name": "Adim 1: Workflow Baslat (testPath=pass)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"lifecycle-pass-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"lifecycle\", \"pass-path\"],\n \"attributes\": {\n \"testPath\": \"pass\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"passInstanceId\", jsonData.id);", + " console.log(\"passInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Durum Kontrol (initialize-state olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{passInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 3: Manuel Transition - Move to Processing (ITransitionMapping test)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/transitions/move-to-processing?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{passInstanceId}}", + "transitions", + "move-to-processing" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 4: Durum Kontrol (auto-passed-state olmali, auto transition testPath=pass rule calisti)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{passInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 5: 15 saniye bekle (scheduled timer 10s) ve durum kontrol", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{passInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 6: Manuel Transition - Complete Workflow", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/transitions/complete-workflow?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{passInstanceId}}", + "transitions", + "complete-workflow" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 7: Durum Kontrol (completed-state, Final/Success olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{passInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{passInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 2: Fail Path (testPath=fail)", + "item": [ + { + "name": "Adim 1: Workflow Baslat (testPath=fail)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"lifecycle-fail-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"lifecycle\", \"fail-path\"],\n \"attributes\": {\n \"testPath\": \"fail\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"failInstanceId\", jsonData.id);", + " console.log(\"failInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Manuel Transition - Move to Processing", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{failInstanceId}}/transitions/move-to-processing?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{failInstanceId}}", + "transitions", + "move-to-processing" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 3: Durum Kontrol (auto-failed-state, Final/Error olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{failInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{failInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 3: Default Auto Transition (triggerKind:10)", + "item": [ + { + "name": "Adim 1: Workflow Baslat (testPath=unknown)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"lifecycle-default-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"lifecycle\", \"default-path\"],\n \"attributes\": {\n \"testPath\": \"unknown\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"defaultInstanceId\", jsonData.id);", + " console.log(\"defaultInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Manuel Transition - Move to Processing", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{defaultInstanceId}}/transitions/move-to-processing?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{defaultInstanceId}}", + "transitions", + "move-to-processing" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 3: Durum Kontrol (default-fallback-state -> completed-state olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{defaultInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{defaultInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 4: Idempotent Start", + "item": [ + { + "name": "Adim 1: Workflow Baslat", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"lifecycle-idempotent-key\",\n \"tags\": [\"integration-test\", \"lifecycle\", \"idempotent\"],\n \"attributes\": {\n \"testPath\": \"pass\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"idempotentInstanceId\", jsonData.id);", + " console.log(\"idempotentInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Ayni Key ile Tekrar Baslat (ayni instance donmeli)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"lifecycle-idempotent-key\",\n \"tags\": [\"integration-test\"],\n \"attributes\": {\n \"testPath\": \"pass\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"idempotentInstanceId2\", jsonData.id);", + " console.log(\"idempotentInstanceId2 set to: \" + jsonData.id);", + "}" + ] + } + } + ] + } + ] + }, + { + "name": "TEST 5: Cancel Transition", + "item": [ + { + "name": "Adim 1: Workflow Baslat", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"lifecycle-cancel-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"lifecycle\", \"cancel\"],\n \"attributes\": {\n \"testPath\": \"pass\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"cancelInstanceId\", jsonData.id);", + " console.log(\"cancelInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Cancel Workflow", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{cancelInstanceId}}/transitions/cancel-workflow?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{cancelInstanceId}}", + "transitions", + "cancel-workflow" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 3: Durum Kontrol (terminated-state, Final/Terminated olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{cancelInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{cancelInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST: Exit Transition", + "item": [ + { + "name": "Adim 1: Workflow Baslat (Exit Test)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"exit-test-{{$timestamp}}\",\n \"tags\": [\"exit-test\"],\n \"attributes\": {\n \"testId\": \"exit-test\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"exitInstanceId\", jsonData.id);", + " console.log(\"exitInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Exit Transition Tetikle (initialize-state'den)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{exitInstanceId}}/transitions/exit-workflow", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{exitInstanceId}}", + "transitions", + "exit-workflow" + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 3: Durum Kontrol - terminated-state olmali", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{exitInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{exitInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 4: Instance Data Kontrol - exitExecuted=true olmali", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{exitInstanceId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{exitInstanceId}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST: Schedule Cancel (Manual ile timer iptali)", + "item": [ + { + "name": "Adim 1: Workflow Baslat (Schedule Cancel Test)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"schedule-cancel-test-{{$timestamp}}\",\n \"tags\": [\"schedule-cancel-test\"],\n \"attributes\": {\n \"testId\": \"schedule-cancel-test\",\n \"testPath\": \"pass\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"scheduleCancelInstanceId\", jsonData.id);", + " console.log(\"scheduleCancelInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Durum Kontrol - auto-passed-state olmali (auto transitions sonrasi)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{scheduleCancelInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{scheduleCancelInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 3: Timer tetiklenmeden cancel-schedule-manually transition cagir", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{scheduleCancelInstanceId}}/transitions/cancel-schedule-manually", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{scheduleCancelInstanceId}}", + "transitions", + "cancel-schedule-manually" + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 4: Durum Kontrol - pre-complete-state olmali (timer iptali basarili)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{scheduleCancelInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{scheduleCancelInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST: Reschedule Timer ($self transition)", + "item": [ + { + "name": "Adim 1: Workflow Baslat (Reschedule Test)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"reschedule-test-{{$timestamp}}\",\n \"tags\": [\"reschedule-test\"],\n \"attributes\": {\n \"testId\": \"reschedule-test\",\n \"testPath\": \"pass\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"rescheduleInstanceId\", jsonData.id);", + " console.log(\"rescheduleInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Durum Kontrol - auto-passed-state olmali", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rescheduleInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{rescheduleInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 3: Reschedule timer ($self transition - timer sifirlanmali)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rescheduleInstanceId}}/transitions/reschedule-timer", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{rescheduleInstanceId}}", + "transitions", + "reschedule-timer" + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 4: Durum Kontrol - hala auto-passed-state olmali ($self = ayni state)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rescheduleInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{rescheduleInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST: QueryRoles ve Transition Roles", + "item": [ + { + "name": "Adim 1: Workflow Baslat (Roles Test)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"roles-test-{{$timestamp}}\",\n \"tags\": [\"roles-test\"],\n \"attributes\": {\n \"testId\": \"roles-test\",\n \"testPath\": \"pass\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"rolesInstanceId\", jsonData.id);", + " console.log(\"rolesInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: QueryRoles ile yetki kontrolu - test-viewer izinli olmali (workflow-level)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rolesInstanceId}}/functions/authorize?role=test-viewer", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{rolesInstanceId}}", + "functions", + "authorize" + ], + "query": [ + { + "key": "role", + "value": "test-viewer" + } + ] + } + }, + "response": [] + }, + { + "name": "Adim 3: move-to-processing transition (test-operator rolu ile)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rolesInstanceId}}/transitions/move-to-processing", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{rolesInstanceId}}", + "transitions", + "move-to-processing" + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 4: Durum Kontrol - processing-state olmali", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rolesInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{rolesInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 5: QueryRoles - processing-state'de test-processor izinli, test-viewer reddedilmis olmali", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rolesInstanceId}}/functions/authorize?role=test-processor", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{rolesInstanceId}}", + "functions", + "authorize" + ], + "query": [ + { + "key": "role", + "value": "test-processor" + } + ] + } + }, + "response": [] + }, + { + "name": "Adim 6: QueryRoles - test-viewer deny olmali (state-level override)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rolesInstanceId}}/functions/authorize?role=test-viewer", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{rolesInstanceId}}", + "functions", + "authorize" + ], + "query": [ + { + "key": "role", + "value": "test-viewer" + } + ] + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file diff --git a/api-tests/schema-data/postman-schema-data.json b/api-tests/schema-data/postman-schema-data.json new file mode 100644 index 0000000..a944605 --- /dev/null +++ b/api-tests/schema-data/postman-schema-data.json @@ -0,0 +1,653 @@ +{ + "info": { + "_postman_id": "3f65c974-a6ce-456b-81ca-b47a3e24e9f2", + "name": "vNext Test - Schema Data", + "description": "Auto-generated from schema-data-test-workflow.http.\nvNext workflow integration test collection for schema-data.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:4201", + "type": "string" + }, + { + "key": "apiVersion", + "value": "1", + "type": "string" + }, + { + "key": "domain", + "value": "core", + "type": "string" + }, + { + "key": "workflow", + "value": "schema-data-test-workflow", + "type": "string" + } + ], + "item": [ + { + "name": "TEST 1: Master Schema + Transition Schema Validation", + "item": [ + { + "name": "Adim 1: Workflow Baslat (master schema required alanlarla)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"schema-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"schema-data\"],\n \"attributes\": {\n \"orderId\": \"ORD-001\",\n \"customerName\": \"Test Customer\",\n \"amount\": 1500.50,\n \"currency\": \"TRY\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"schemaInstanceId\", jsonData.id);", + " console.log(\"schemaInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Durum Kontrol (data-initialized olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{schemaInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{schemaInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 3: Transition Schema ile Onayla (dogru data)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{schemaInstanceId}}/transitions/confirm-with-schema?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{schemaInstanceId}}", + "transitions", + "confirm-with-schema" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"confirmed\": true,\n \"confirmedBy\": \"test-admin\"\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 4: Durum Kontrol (schema-validated-state olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{schemaInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{schemaInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 5: No-schema state'e gec", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{schemaInstanceId}}/transitions/to-no-schema?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{schemaInstanceId}}", + "transitions", + "to-no-schema" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 6: Tamamla", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{schemaInstanceId}}/transitions/complete-schema-test?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{schemaInstanceId}}", + "transitions", + "complete-schema-test" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 2: Transition Schema Rejection (Sessiz Red)", + "item": [ + { + "name": "Adim 1: Yeni Instance Baslat", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"schema-reject-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"schema-data\", \"rejection\"],\n \"attributes\": {\n \"orderId\": \"ORD-002\",\n \"customerName\": \"Reject Test\",\n \"amount\": 500,\n \"currency\": \"USD\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"rejectInstanceId\", jsonData.id);", + " console.log(\"rejectInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Transition Schema ile YANLIS data gonder (confirmed ve confirmedBy required)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rejectInstanceId}}/transitions/confirm-with-schema?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{rejectInstanceId}}", + "transitions", + "confirm-with-schema" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"wrongField\": \"this does not match schema\"\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 3: Durum Kontrol (HALA data-initialized olmali - state degismemeli)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rejectInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{rejectInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 3: updateData ($self) Transition", + "item": [ + { + "name": "Adim 1: Yeni Instance Baslat", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"schema-updatedata-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"schema-data\", \"update-data\"],\n \"attributes\": {\n \"orderId\": \"ORD-003\",\n \"customerName\": \"UpdateData Test\",\n \"amount\": 750,\n \"currency\": \"EUR\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"updateDataInstanceId\", jsonData.id);", + " console.log(\"updateDataInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Durum Kontrol (data-initialized olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{updateDataInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 3: updateData ($self) ile data guncelle - state degismemeli", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataInstanceId}}/transitions/update-instance-data?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{updateDataInstanceId}}", + "transitions", + "update-instance-data" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"orderId\": \"ORD-003\",\n \"customerName\": \"UpdateData Test - UPDATED\",\n \"amount\": 800,\n \"currency\": \"EUR\"\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Adim 4: Durum Kontrol (HALA data-initialized olmali ama data guncellenmis olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{updateDataInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 5: Data kontrol et (guncellenmis data'yi gor)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataInstanceId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{updateDataInstanceId}}", + "functions", + "data" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 4: Master Schema Violation at Start", + "item": [ + { + "name": "Adim 1: Eksik required alan ile baslat (currency yok)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"schema-violation-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"schema-data\", \"violation\"],\n \"attributes\": {\n \"orderId\": \"ORD-004\",\n \"customerName\": \"Missing Currency\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file diff --git a/api-tests/schema-data/schema-data-test-workflow.http b/api-tests/schema-data/schema-data-test-workflow.http new file mode 100644 index 0000000..42f7d18 --- /dev/null +++ b/api-tests/schema-data/schema-data-test-workflow.http @@ -0,0 +1,151 @@ +@baseUrl = http://localhost:4201 +@apiVersion = 1 +@domain = core +@workflow = schema-data-test-workflow + +############################################################################### +# TEST 1: Master Schema + Transition Schema Validation +# Tests: master schema active, transition schema enforcement, +# onExecutionTasks with mapping after schema passes +############################################################################### + +### Adim 1: Workflow Baslat (master schema required alanlarla) +# @name createSchemaInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "schema-test-{{$timestamp}}", + "tags": ["integration-test", "schema-data"], + "attributes": { + "orderId": "ORD-001", + "customerName": "Test Customer", + "amount": 1500.50, + "currency": "TRY" + } +} + +@schemaInstanceId = {{createSchemaInstance.response.body.$.id}} + +### Adim 2: Durum Kontrol (data-initialized olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{schemaInstanceId}}/functions/state + +### Adim 3: Transition Schema ile Onayla (dogru data) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{schemaInstanceId}}/transitions/confirm-with-schema?sync=true +Content-Type: application/json + +{ + "confirmed": true, + "confirmedBy": "test-admin" +} + +### Adim 4: Durum Kontrol (schema-validated-state olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{schemaInstanceId}}/functions/state + +### Adim 5: No-schema state'e gec +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{schemaInstanceId}}/transitions/to-no-schema?sync=true +Content-Type: application/json + +{} + +### Adim 6: Tamamla +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{schemaInstanceId}}/transitions/complete-schema-test?sync=true +Content-Type: application/json + +{} + +############################################################################### +# TEST 2: Transition Schema Rejection (Sessiz Red) +# Tests: yanlis data gonderilirse transition 200 doner ama state DEGISMEZ +############################################################################### + +### Adim 1: Yeni Instance Baslat +# @name createRejectInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "schema-reject-test-{{$timestamp}}", + "tags": ["integration-test", "schema-data", "rejection"], + "attributes": { + "orderId": "ORD-002", + "customerName": "Reject Test", + "amount": 500, + "currency": "USD" + } +} + +@rejectInstanceId = {{createRejectInstance.response.body.$.id}} + +### Adim 2: Transition Schema ile YANLIS data gonder (confirmed ve confirmedBy required) +# Bu 200 donecek ama state DEGISMEMELI (sessiz red) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rejectInstanceId}}/transitions/confirm-with-schema?sync=true +Content-Type: application/json + +{ + "wrongField": "this does not match schema" +} + +### Adim 3: Durum Kontrol (HALA data-initialized olmali - state degismemeli) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{rejectInstanceId}}/functions/state + +############################################################################### +# TEST 3: updateData ($self) Transition +# Tests: state degistirmeden instance data guncelleme +############################################################################### + +### Adim 1: Yeni Instance Baslat +# @name createUpdateDataInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "schema-updatedata-test-{{$timestamp}}", + "tags": ["integration-test", "schema-data", "update-data"], + "attributes": { + "orderId": "ORD-003", + "customerName": "UpdateData Test", + "amount": 750, + "currency": "EUR" + } +} + +@updateDataInstanceId = {{createUpdateDataInstance.response.body.$.id}} + +### Adim 2: Durum Kontrol (data-initialized olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataInstanceId}}/functions/state + +### Adim 3: updateData ($self) ile data guncelle - state degismemeli +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataInstanceId}}/transitions/update-instance-data?sync=true +Content-Type: application/json + +{ + "orderId": "ORD-003", + "customerName": "UpdateData Test - UPDATED", + "amount": 800, + "currency": "EUR" +} + +### Adim 4: Durum Kontrol (HALA data-initialized olmali ama data guncellenmis olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataInstanceId}}/functions/state + +### Adim 5: Data kontrol et (guncellenmis data'yi gor) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataInstanceId}}/functions/data + +############################################################################### +# TEST 4: Master Schema Violation at Start +# Tests: master schema zorunlu alan eksik olunca baslatma basarisiz olmali +############################################################################### + +### Adim 1: Eksik required alan ile baslat (currency yok) +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "schema-violation-test-{{$timestamp}}", + "tags": ["integration-test", "schema-data", "violation"], + "attributes": { + "orderId": "ORD-004", + "customerName": "Missing Currency" + } +} diff --git a/api-tests/subflow-orchestration/postman-subflow-orchestration.json b/api-tests/subflow-orchestration/postman-subflow-orchestration.json new file mode 100644 index 0000000..31a306c --- /dev/null +++ b/api-tests/subflow-orchestration/postman-subflow-orchestration.json @@ -0,0 +1,978 @@ +{ + "info": { + "_postman_id": "18552093-7267-4048-893f-aea2a7fe1ece", + "name": "vNext Test - Subflow Orchestration", + "description": "Auto-generated from subflow-orchestration.http.\nvNext workflow integration test collection for subflow-orchestration.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:4201", + "type": "string" + }, + { + "key": "apiVersion", + "value": "1", + "type": "string" + }, + { + "key": "domain", + "value": "core", + "type": "string" + }, + { + "key": "workflow", + "value": "subflow-orchestration-parent", + "type": "string" + } + ], + "item": [ + { + "name": "TEST 1: Happy path", + "item": [ + { + "name": "TEST 1 — Step 1: Start parent workflow (sync)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"subflow-orch-happy-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"subflow-orchestration\"],\n \"attributes\": {\n \"testId\": \"orch-happy-path\",\n \"parentData\": {\n \"note\": \"from-parent-start\"\n }\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"happyParentInstanceId\", jsonData.id);", + " console.log(\"happyParentInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "TEST 1 — Step 2: State (deepest active should be grandchild-initial after autos)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{happyParentInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{happyParentInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "TEST 1 — Step 3: Complete grandchild (routed via parent instance + parent workflow key)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{happyParentInstanceId}}/transitions/complete-grandchild?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{happyParentInstanceId}}", + "transitions", + "complete-grandchild" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "TEST 1 — Step 4: State should reach parent-completed after cascade autos", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{happyParentInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{happyParentInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "TEST 1 — Step 5: Instance data flags", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{happyParentInstanceId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{happyParentInstanceId}}", + "functions", + "data" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 2: Cancel cascade", + "item": [ + { + "name": "TEST 2 — Step 1: Start parent (sync)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"subflow-orch-cancel-cascade-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"subflow-orchestration\", \"cancel-cascade\"],\n \"attributes\": {\n \"testId\": \"orch-cancel-cascade\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"cancelCascadeParentInstanceId\", jsonData.id);", + " console.log(\"cancelCascadeParentInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "TEST 2 — Step 2: Wait until deepest state is grandchild-initial (poll until effectiveState or state reflects grandchild-initial; re-run if autos are slower)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{cancelCascadeParentInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{cancelCascadeParentInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "TEST 2 — Step 3: Cancel parent while nested (cascade should terminate child/grandchild definitions toward parent-cancelled)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{cancelCascadeParentInstanceId}}/transitions/cancel-parent?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{cancelCascadeParentInstanceId}}", + "transitions", + "cancel-parent" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "TEST 2 — Step 4: Verify parent reached parent-cancelled (state function)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{cancelCascadeParentInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{cancelCascadeParentInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 3: Shared transition from child workflow", + "item": [ + { + "name": "TEST 3 — Step 1: Start parent (sync)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"subflow-orch-child-shared-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"subflow-orchestration\", \"child-shared\"],\n \"attributes\": {\n \"testId\": \"orch-child-shared\",\n \"parentData\": {\n \"beforeChildShared\": true\n }\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"childSharedParentInstanceId\", jsonData.id);", + " console.log(\"childSharedParentInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "TEST 3 — Step 2: Confirm nested / effective view shows grandchild-initial (effectiveState or nested state payload per runtime)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{childSharedParentInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "TEST 3 — Step 3: Trigger child shared transition on parent instance (availableIn child-subflow-state)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/transitions/shared-child-update?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{childSharedParentInstanceId}}", + "transitions", + "shared-child-update" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"attributes\": {\n \"message\": \"child-shared-from-http\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "TEST 3 — Step 4: Data should include childSharedUpdateExecuted=true while still nested until grandchild completes", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{childSharedParentInstanceId}}", + "functions", + "data" + ] + } + }, + "response": [] + }, + { + "name": "TEST 3 — Step 5: Complete grandchild then verify final cascade", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/transitions/complete-grandchild?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{childSharedParentInstanceId}}", + "transitions", + "complete-grandchild" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "TEST 3 — Step 6: Final state and merged data", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{childSharedParentInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "TEST 3 — Step 6: Final state and merged data", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{childSharedParentInstanceId}}", + "functions", + "data" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 4: Effective state", + "item": [ + { + "name": "TEST 4 — Step 1: Start parent (sync)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"subflow-orch-effective-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"subflow-orchestration\", \"effective-state\"],\n \"attributes\": {\n \"testId\": \"orch-effective-state\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"effectiveStateParentInstanceId\", jsonData.id);", + " console.log(\"effectiveStateParentInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "TEST 4 — Step 2: State function — verify effectiveState (and related metadata if present) shows deepest active subflow state (grandchild-initial)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{effectiveStateParentInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{effectiveStateParentInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "TEST 4 — Step 3: Optional data snapshot while nested", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{effectiveStateParentInstanceId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{effectiveStateParentInstanceId}}", + "functions", + "data" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 5: UpdateData transition from SubFlow", + "item": [ + { + "name": "TEST 5 — Step 1: Start parent (sync)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"subflow-orch-updatedata-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"subflow-orchestration\", \"update-data\"],\n \"attributes\": {\n \"testId\": \"orch-update-data\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"updateDataParentInstanceId\", jsonData.id);", + " console.log(\"updateDataParentInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "TEST 5 — Step 2: Verify nested state (child-subflow-state or grandchild-initial)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataParentInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{updateDataParentInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "TEST 5 — Step 3: Trigger updateData transition from child", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataParentInstanceId}}/transitions/update-parent-data?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{updateDataParentInstanceId}}", + "transitions", + "update-parent-data" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"attributes\": {\n \"updateMessage\": \"from-child-updatedata\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "TEST 5 — Step 4: Verify parent data now includes childUpdatedParent=true", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataParentInstanceId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{updateDataParentInstanceId}}", + "functions", + "data" + ] + } + }, + "response": [] + }, + { + "name": "TEST 5 — Step 5: Complete grandchild to finish the flow", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataParentInstanceId}}/transitions/complete-grandchild?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{updateDataParentInstanceId}}", + "transitions", + "complete-grandchild" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "TEST 5 — Step 6: Verify final state and data", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataParentInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{updateDataParentInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file diff --git a/api-tests/subflow-orchestration/subflow-orchestration.http b/api-tests/subflow-orchestration/subflow-orchestration.http new file mode 100644 index 0000000..c44d175 --- /dev/null +++ b/api-tests/subflow-orchestration/subflow-orchestration.http @@ -0,0 +1,206 @@ +@baseUrl = http://localhost:4201 +@apiVersion = 1 +@domain = core +@workflow = subflow-orchestration-parent + +############################################################################### +# TEST 1: Happy path +# Start parent (autos to child then grandchild), complete grandchild on the +# parent instance URL, cascade to parent-completed. Verify data flags via +# /functions/data (parentStarted, childStarted, grandchildStarted, +# grandchildFinished, childCompleted as produced by mappings). +############################################################################### + +### TEST 1 — Step 1: Start parent workflow (sync) +# @name createHappyPathInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "subflow-orch-happy-{{$timestamp}}", + "tags": ["integration-test", "subflow-orchestration"], + "attributes": { + "testId": "orch-happy-path", + "parentData": { + "note": "from-parent-start" + } + } +} + +@happyParentInstanceId = {{createHappyPathInstance.response.body.$.id}} + +### TEST 1 — Step 2: State (deepest active should be grandchild-initial after autos) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{happyParentInstanceId}}/functions/state + +### TEST 1 — Step 3: Complete grandchild (routed via parent instance + parent workflow key) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{happyParentInstanceId}}/transitions/complete-grandchild?sync=true +Content-Type: application/json + +{} + +### TEST 1 — Step 4: State should reach parent-completed after cascade autos +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{happyParentInstanceId}}/functions/state + +### TEST 1 — Step 5: Instance data flags +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{happyParentInstanceId}}/functions/data + +############################################################################### +# TEST 2: Cancel cascade +# Start parent, confirm nested execution reached grandchild-initial, cancel the +# parent from the parent instance. Expect parent final state parent-cancelled +# (verify via /functions/state: state / metadata.currentState and cancel +# cascade into subflows per platform rules). +############################################################################### + +### TEST 2 — Step 1: Start parent (sync) +# @name createCancelCascadeInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "subflow-orch-cancel-cascade-{{$timestamp}}", + "tags": ["integration-test", "subflow-orchestration", "cancel-cascade"], + "attributes": { + "testId": "orch-cancel-cascade" + } +} + +@cancelCascadeParentInstanceId = {{createCancelCascadeInstance.response.body.$.id}} + +### TEST 2 — Step 2: Wait until deepest state is grandchild-initial (poll until effectiveState or state reflects grandchild-initial; re-run if autos are slower) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{cancelCascadeParentInstanceId}}/functions/state + +### TEST 2 — Step 3: Cancel parent while nested (cascade should terminate child/grandchild definitions toward parent-cancelled) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{cancelCascadeParentInstanceId}}/transitions/cancel-parent?sync=true +Content-Type: application/json + +{} + +### TEST 2 — Step 4: Verify parent reached parent-cancelled (state function) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{cancelCascadeParentInstanceId}}/functions/state + +############################################################################### +# TEST 3: Shared transition from child workflow +# While nested, effective tracking should surface grandchild. Fire the child +# flow shared transition (shared-child-update) through the parent instance URL. +############################################################################### + +### TEST 3 — Step 1: Start parent (sync) +# @name createChildSharedInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "subflow-orch-child-shared-{{$timestamp}}", + "tags": ["integration-test", "subflow-orchestration", "child-shared"], + "attributes": { + "testId": "orch-child-shared", + "parentData": { + "beforeChildShared": true + } + } +} + +@childSharedParentInstanceId = {{createChildSharedInstance.response.body.$.id}} + +### TEST 3 — Step 2: Confirm nested / effective view shows grandchild-initial (effectiveState or nested state payload per runtime) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/functions/state + +### TEST 3 — Step 3: Trigger child shared transition on parent instance (availableIn child-subflow-state) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/transitions/shared-child-update?sync=true +Content-Type: application/json + +{ + "attributes": { + "message": "child-shared-from-http" + } +} + +### TEST 3 — Step 4: Data should include childSharedUpdateExecuted=true while still nested until grandchild completes +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/functions/data + +### TEST 3 — Step 5: Complete grandchild then verify final cascade +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/transitions/complete-grandchild?sync=true +Content-Type: application/json + +{} + +### TEST 3 — Step 6: Final state and merged data +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/functions/state + +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{childSharedParentInstanceId}}/functions/data + +############################################################################### +# TEST 4: Effective state +# After start, /functions/state should expose effectiveState (deepest active +# subflow state, e.g. grandchild-initial) alongside the parent stack state. +############################################################################### + +### TEST 4 — Step 1: Start parent (sync) +# @name createEffectiveStateInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "subflow-orch-effective-{{$timestamp}}", + "tags": ["integration-test", "subflow-orchestration", "effective-state"], + "attributes": { + "testId": "orch-effective-state" + } +} + +@effectiveStateParentInstanceId = {{createEffectiveStateInstance.response.body.$.id}} + +### TEST 4 — Step 2: State function — verify effectiveState (and related metadata if present) shows deepest active subflow state (grandchild-initial) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{effectiveStateParentInstanceId}}/functions/state + +### TEST 4 — Step 3: Optional data snapshot while nested +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{effectiveStateParentInstanceId}}/functions/data + +############################################################################### +# TEST 5: UpdateData transition from SubFlow +# Start parent, wait until nested in child-subflow-state, trigger the +# updateData transition (update-parent-data) on the child. This should +# update the parent instance data with childUpdatedParent=true via +# UpdateParentDataMapping.csx. Target is $self so child stays in same state. +############################################################################### + +### TEST 5 — Step 1: Start parent (sync) +# @name createUpdateDataInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "subflow-orch-updatedata-{{$timestamp}}", + "tags": ["integration-test", "subflow-orchestration", "update-data"], + "attributes": { + "testId": "orch-update-data" + } +} + +@updateDataParentInstanceId = {{createUpdateDataInstance.response.body.$.id}} + +### TEST 5 — Step 2: Verify nested state (child-subflow-state or grandchild-initial) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataParentInstanceId}}/functions/state + +### TEST 5 — Step 3: Trigger updateData transition from child +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataParentInstanceId}}/transitions/update-parent-data?sync=true +Content-Type: application/json + +{ + "attributes": { + "updateMessage": "from-child-updatedata" + } +} + +### TEST 5 — Step 4: Verify parent data now includes childUpdatedParent=true +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataParentInstanceId}}/functions/data + +### TEST 5 — Step 5: Complete grandchild to finish the flow +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataParentInstanceId}}/transitions/complete-grandchild?sync=true +Content-Type: application/json + +{} + +### TEST 5 — Step 6: Verify final state and data +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{updateDataParentInstanceId}}/functions/state diff --git a/api-tests/task-execution/postman-task-execution.json b/api-tests/task-execution/postman-task-execution.json new file mode 100644 index 0000000..17f7cf1 --- /dev/null +++ b/api-tests/task-execution/postman-task-execution.json @@ -0,0 +1,245 @@ +{ + "info": { + "_postman_id": "2835031e-c465-4e76-b09c-a4b3b3e63246", + "name": "vNext Test - Task Execution", + "description": "Auto-generated from task-execution-test-workflow.http.\nvNext workflow integration test collection for task-execution.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:4201", + "type": "string" + }, + { + "key": "apiVersion", + "value": "1", + "type": "string" + }, + { + "key": "domain", + "value": "core", + "type": "string" + }, + { + "key": "workflow", + "value": "task-execution-test-workflow", + "type": "string" + }, + { + "key": "targetWorkflow", + "value": "task-target-workflow", + "type": "string" + }, + { + "key": "mocklabBaseUrl", + "value": "http://localhost:3002", + "type": "string" + } + ], + "item": [ + { + "name": "TEST 1: Full task execution chain", + "item": [ + { + "name": "Adim 1: Ana workflow baslat (sync)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"task-exec-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"task-execution\"],\n \"attributes\": {}\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"taskExecInstanceId\", jsonData.id);", + " console.log(\"taskExecInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Durum kontrol (completed-state beklenir)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{taskExecInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{taskExecInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Adim 3: Instance data dogrula", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{taskExecInstanceId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{taskExecInstanceId}}", + "functions", + "data" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "TEST 2: Hedef workflow (task-target-workflow) bagimsiz baslatma", + "item": [ + { + "name": "Adim 1: Hedef workflow baslat", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{targetWorkflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{targetWorkflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"task-target-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"task-execution\", \"target\"],\n \"attributes\": {}\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"targetInstanceId\", jsonData.id);", + " console.log(\"targetInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Adim 2: Hedef workflow durumu (target-completed olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{targetWorkflow}}/instances/{{targetInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{targetWorkflow}}", + "instances", + "{{targetInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file diff --git a/api-tests/task-execution/task-execution-test-workflow.http b/api-tests/task-execution/task-execution-test-workflow.http new file mode 100644 index 0000000..ead15b1 --- /dev/null +++ b/api-tests/task-execution/task-execution-test-workflow.http @@ -0,0 +1,55 @@ +@baseUrl = http://localhost:4201 +@apiVersion = 1 +@domain = core +@workflow = task-execution-test-workflow +@targetWorkflow = task-target-workflow +@mocklabBaseUrl = http://localhost:3002 + +############################################################################### +# TEST 1: Full task execution chain +# HTTP task -> Script task -> Cross workflow -> Start Flow (type 11) -> +# Get Instance Data (type 13) -> Completed +# Requires: MocklabBaseUrl config, Mocklab seeded (POST /api/test/process) +############################################################################### + +### Adim 1: Ana workflow baslat (sync) +# @name createTaskExecInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "task-exec-test-{{$timestamp}}", + "tags": ["integration-test", "task-execution"], + "attributes": {} +} + +@taskExecInstanceId = {{createTaskExecInstance.response.body.$.id}} + +### Adim 2: Durum kontrol (completed-state beklenir) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{taskExecInstanceId}}/functions/state + +### Adim 3: Instance data dogrula +# Beklenen bayraklar: testId, httpTaskCompleted, scriptProcessed, +# crossWorkflowCompleted, startFlowCompleted, startedInstanceId, +# getInstanceDataCompleted, remoteInstanceData +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{taskExecInstanceId}}/functions/data + +############################################################################### +# TEST 2: Hedef workflow (task-target-workflow) bagimsiz baslatma +############################################################################### + +### Adim 1: Hedef workflow baslat +# @name createTargetInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{targetWorkflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "task-target-test-{{$timestamp}}", + "tags": ["integration-test", "task-execution", "target"], + "attributes": {} +} + +@targetInstanceId = {{createTargetInstance.response.body.$.id}} + +### Adim 2: Hedef workflow durumu (target-completed olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{targetWorkflow}}/instances/{{targetInstanceId}}/functions/state diff --git a/api-tests/version-consistency/postman-version-consistency.json b/api-tests/version-consistency/postman-version-consistency.json new file mode 100644 index 0000000..2dd9dde --- /dev/null +++ b/api-tests/version-consistency/postman-version-consistency.json @@ -0,0 +1,523 @@ +{ + "info": { + "_postman_id": "f108af4c-1b76-49b2-8d26-53a2721fa7c2", + "name": "vNext Test - Version Consistency", + "description": "Auto-generated from version-consistency-test.http.\nvNext workflow integration test collection for version-consistency.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:4201", + "type": "string" + }, + { + "key": "apiVersion", + "value": "1", + "type": "string" + }, + { + "key": "domain", + "value": "core", + "type": "string" + }, + { + "key": "workflow", + "value": "version-consistency-test-workflow", + "type": "string" + } + ], + "item": [ + { + "name": "ADIM 2: Instance A baslatma (v1.0.0 uzerinde)", + "item": [ + { + "name": "Instance A - Baslat (v1.0.0 akisinda calisacak)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"version-test-A-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"version-consistency\", \"v1-instance\"],\n \"attributes\": {\n \"testId\": \"version-consistency-A\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"instanceAId\", jsonData.id);", + " console.log(\"instanceAId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + } + ] + }, + { + "name": "ADIM 3: Instance A state kontrolu (processing-state'te olmali)", + "item": [ + { + "name": "Instance A - State kontrolu (processing-state bekleniyor)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceAId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceAId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "ADIM 5: Instance B baslatma (v2.0.0 uzerinde calisacak)", + "item": [ + { + "name": "Instance B - Baslat (v2.0.0 akisinda calisacak)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"version-test-B-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"version-consistency\", \"v2-instance\"],\n \"attributes\": {\n \"testId\": \"version-consistency-B\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"instanceBId\", jsonData.id);", + " console.log(\"instanceBId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + } + ] + }, + { + "name": "ADIM 6: Instance B state kontrolu (processing-state'te olmali)", + "item": [ + { + "name": "Instance B - State kontrolu (processing-state bekleniyor)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceBId}}", + "functions", + "state" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "ADIM 7: Instance A'yi tamamla", + "item": [ + { + "name": "Instance A - complete-processing (v1: dogrudan completed-state'e gitmeli)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceAId}}/transitions/complete-processing?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceAId}}", + "transitions", + "complete-processing" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Instance A - Final state kontrolu (completed-state bekleniyor)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceAId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceAId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Instance A - Data kontrolu", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceAId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceAId}}", + "functions", + "data" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "ADIM 8: Instance B'yi processing'den ilerlet", + "item": [ + { + "name": "Instance B - complete-processing (v2: review-state'e gitmeli)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/transitions/complete-processing?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceBId}}", + "transitions", + "complete-processing" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Instance B - State kontrolu (review-state bekleniyor)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceBId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Instance B - Data kontrolu (reviewExecuted=true olmali)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceBId}}", + "functions", + "data" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "ADIM 9: Instance B review'dan completed'a", + "item": [ + { + "name": "Instance B - approve-review (v2: completed-state'e gitmeli)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/transitions/approve-review?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceBId}}", + "transitions", + "approve-review" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [] + }, + { + "name": "Instance B - Final state kontrolu (completed-state bekleniyor)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceBId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Instance B - Final data kontrolu", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{instanceBId}}", + "functions", + "data" + ] + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file diff --git a/api-tests/version-consistency/version-consistency-test.http b/api-tests/version-consistency/version-consistency-test.http new file mode 100644 index 0000000..aa3f53a --- /dev/null +++ b/api-tests/version-consistency/version-consistency-test.http @@ -0,0 +1,159 @@ +@baseUrl = http://localhost:4201 +@apiVersion = 1 +@domain = core +@workflow = version-consistency-test-workflow + +############################################################################### +# VERSION CONSISTENCY TEST +# +# Bu test, workflow versiyonu degistiginde mevcut instance'larin kendi +# versiyonlarinin akisindan devam ettigini dogrular. +# +# ONKOŞUL: Sadece v1.0.0 publish edilmis olmali. +# v2.0.0 HENUZ publish edilmemis olmali. +# +# ADIMLAR: +# 1. v1.0.0 workflow'u publish et (version-consistency-test-workflow.json) +# 2. Instance A'yi baslat (v1.0.0 uzerinde calisacak) +# 3. Instance A'yi processing-state'e tasra (auto ile gider) +# 4. v2.0.0 workflow'u publish et (version-consistency-test-workflow-v2.json) +# 5. Instance B'yi baslat (v2.0.0 uzerinde calisacak) +# 6. Instance B'yi processing-state'e birak +# 7. Instance A: complete-processing → completed-state (v1 yolu, review YOK) +# 8. Instance B: complete-processing → review-state (v2 yolu) +# 9. Instance B: approve-review → completed-state +# 10. Her iki instance'in datasini karsilastir +############################################################################### + +############################################################################### +# ADIM 1: v1.0.0 PUBLISH EDILMIS OLMALI +# → version-consistency-test-workflow.json dosyasini publish edin +############################################################################### + +############################################################################### +# ADIM 2: Instance A baslatma (v1.0.0 uzerinde) +############################################################################### + +### Instance A - Baslat (v1.0.0 akisinda calisacak) +# @name createInstanceA +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "version-test-A-{{$timestamp}}", + "tags": ["integration-test", "version-consistency", "v1-instance"], + "attributes": { + "testId": "version-consistency-A" + } +} + +@instanceAId = {{createInstanceA.response.body.$.id}} + +############################################################################### +# ADIM 3: Instance A state kontrolu (processing-state'te olmali) +############################################################################### + +### Instance A - State kontrolu (processing-state bekleniyor) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceAId}}/functions/state + +############################################################################### +# ADIM 4: v2.0.0 PUBLISH ET +# → version-consistency-test-workflow-v2.json dosyasini publish edin +# Instance A hala processing-state'te bekliyor. +############################################################################### + +############################################################################### +# ADIM 5: Instance B baslatma (v2.0.0 uzerinde calisacak) +############################################################################### + +### Instance B - Baslat (v2.0.0 akisinda calisacak) +# @name createInstanceB +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "version-test-B-{{$timestamp}}", + "tags": ["integration-test", "version-consistency", "v2-instance"], + "attributes": { + "testId": "version-consistency-B" + } +} + +@instanceBId = {{createInstanceB.response.body.$.id}} + +############################################################################### +# ADIM 6: Instance B state kontrolu (processing-state'te olmali) +############################################################################### + +### Instance B - State kontrolu (processing-state bekleniyor) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/functions/state + +############################################################################### +# ADIM 7: Instance A'yi tamamla +# complete-processing → completed-state (v1 yolu, review-state YOK) +############################################################################### + +### Instance A - complete-processing (v1: dogrudan completed-state'e gitmeli) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceAId}}/transitions/complete-processing?sync=true +Content-Type: application/json + +{} + +### Instance A - Final state kontrolu (completed-state bekleniyor) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceAId}}/functions/state + +### Instance A - Data kontrolu +# BEKLENEN: v1Completed=true, reviewExecuted OLMAMALI +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceAId}}/functions/data + +############################################################################### +# ADIM 8: Instance B'yi processing'den ilerlet +# complete-processing → review-state (v2 yolu, ekstra state) +############################################################################### + +### Instance B - complete-processing (v2: review-state'e gitmeli) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/transitions/complete-processing?sync=true +Content-Type: application/json + +{} + +### Instance B - State kontrolu (review-state bekleniyor) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/functions/state + +### Instance B - Data kontrolu (reviewExecuted=true olmali) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/functions/data + +############################################################################### +# ADIM 9: Instance B review'dan completed'a +############################################################################### + +### Instance B - approve-review (v2: completed-state'e gitmeli) +PATCH {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/transitions/approve-review?sync=true +Content-Type: application/json + +{} + +### Instance B - Final state kontrolu (completed-state bekleniyor) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/functions/state + +### Instance B - Final data kontrolu +# BEKLENEN: reviewExecuted=true, v2Completed=true, v1Completed OLMAMALI +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{instanceBId}}/functions/data + +############################################################################### +# DOGRULAMA OZETI +# +# Instance A (v1.0.0): +# - State: completed-state +# - Data: v1Completed=true, completedByVersion="1.0.0" +# - reviewExecuted OLMAMALI (v1'de review-state yok) +# +# Instance B (v2.0.0): +# - State: completed-state +# - Data: reviewExecuted=true, v2Completed=true, completedByVersion="2.0.0" +# - v1Completed OLMAMALI (v2 yolunu izledi) +# +# BASARI KRITERI: +# v2 publish edildikten sonra bile Instance A, v1 akisini takip etti +# ve review-state'e ugramadan dogrudan completed'a gitti. +############################################################################### diff --git a/api-tests/view-function-extension/postman-view-function-extension.json b/api-tests/view-function-extension/postman-view-function-extension.json new file mode 100644 index 0000000..9286c43 --- /dev/null +++ b/api-tests/view-function-extension/postman-view-function-extension.json @@ -0,0 +1,258 @@ +{ + "info": { + "_postman_id": "5422afe4-5655-4252-91ff-ecbbd776cb64", + "name": "vNext Test - View Function Extension", + "description": "Auto-generated from view-function-extension-test-workflow.http.\nvNext workflow integration test collection for view-function-extension.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:4201", + "type": "string" + }, + { + "key": "apiVersion", + "value": "1", + "type": "string" + }, + { + "key": "domain", + "value": "core", + "type": "string" + }, + { + "key": "workflow", + "value": "view-function-extension-test-workflow", + "type": "string" + }, + { + "key": "mocklabBaseUrl", + "value": "http://localhost:3002", + "type": "string" + } + ], + "item": [ + { + "name": "Start workflow (sync)", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "start" + ], + "query": [ + { + "key": "sync", + "value": "true" + } + ] + }, + "body": { + "mode": "raw", + "raw": "{\n \"key\": \"vfe-test-{{$timestamp}}\",\n \"tags\": [\"integration-test\", \"view-function-extension\"],\n \"attributes\": {}\n}", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "var jsonData = pm.response.json();", + "if (jsonData && jsonData.id) {", + " pm.collectionVariables.set(\"vfeInstanceId\", jsonData.id);", + " console.log(\"vfeInstanceId set to: \" + jsonData.id);", + "}" + ] + } + } + ] + }, + { + "name": "Get state (includes view href when state has a view)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/state", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{vfeInstanceId}}", + "functions", + "state" + ] + } + }, + "response": [] + }, + { + "name": "Get view payload for current state (optional transitionKey; platform for rule-based clients)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/view?platform=web", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{vfeInstanceId}}", + "functions", + "view" + ], + "query": [ + { + "key": "platform", + "value": "web" + } + ] + } + }, + "response": [] + }, + { + "name": "Execute single-task function (instance-scoped)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/single-task-function", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{vfeInstanceId}}", + "functions", + "single-task-function" + ] + } + }, + "response": [] + }, + { + "name": "Execute multi-task function (script then HTTP; output handler aggregates)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/multi-task-function", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{vfeInstanceId}}", + "functions", + "multi-task-function" + ] + } + }, + "response": [] + }, + { + "name": "Instance data without extension filter (global-extension scope Everywhere may apply)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/data", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{vfeInstanceId}}", + "functions", + "data" + ] + } + }, + "response": [] + }, + { + "name": "Requested extensions via query (DefinedFlowAndRequested + on-demand)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/data?extensions=requested-extension,global-extension", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v{{apiVersion}}", + "{{domain}}", + "workflows", + "{{workflow}}", + "instances", + "{{vfeInstanceId}}", + "functions", + "data" + ], + "query": [ + { + "key": "extensions", + "value": "requested-extension,global-extension" + } + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/api-tests/view-function-extension/view-function-extension-test-workflow.http b/api-tests/view-function-extension/view-function-extension-test-workflow.http new file mode 100644 index 0000000..6c277ea --- /dev/null +++ b/api-tests/view-function-extension/view-function-extension-test-workflow.http @@ -0,0 +1,42 @@ +@baseUrl = http://localhost:4201 +@apiVersion = 1 +@domain = core +@workflow = view-function-extension-test-workflow +@mocklabBaseUrl = http://localhost:3002 + +############################################################################### +# View, function, and extension integration tests. +# Requires: API with MocklabBaseUrl for HTTP task in multi-task-function; +# Mocklab seeded with GET /api/test/user-info (integration-test-collection). +############################################################################### + +### Start workflow (sync) +# @name createVfeInstance +POST {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/start?sync=true +Content-Type: application/json + +{ + "key": "vfe-test-{{$timestamp}}", + "tags": ["integration-test", "view-function-extension"], + "attributes": {} +} + +@vfeInstanceId = {{createVfeInstance.response.body.$.id}} + +### Get state (includes view href when state has a view) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/state + +### Get view payload for current state (optional transitionKey; platform for rule-based clients) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/view?platform=web + +### Execute single-task function (instance-scoped) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/single-task-function + +### Execute multi-task function (script then HTTP; output handler aggregates) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/multi-task-function + +### Instance data without extension filter (global-extension scope Everywhere may apply) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/data + +### Requested extensions via query (DefinedFlowAndRequested + on-demand) +GET {{baseUrl}}/api/v{{apiVersion}}/{{domain}}/workflows/{{workflow}}/instances/{{vfeInstanceId}}/functions/data?extensions=requested-extension,global-extension diff --git a/core/Extensions/view-function-extension/global-extension.json b/core/Extensions/view-function-extension/global-extension.json new file mode 100644 index 0000000..a940de8 --- /dev/null +++ b/core/Extensions/view-function-extension/global-extension.json @@ -0,0 +1,29 @@ +{ + "key": "global-extension", + "version": "1.0.0", + "domain": "core", + "flow": "sys-extensions", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "view-function-extension", + "global-extension" + ], + "attributes": { + "type": 1, + "scope": 3, + "task": { + "order": 1, + "task": { + "key": "vfe-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "type": "G", + "location": "./src/GlobalExtensionMapping.csx" + } + } + } +} diff --git a/core/Extensions/view-function-extension/requested-extension.json b/core/Extensions/view-function-extension/requested-extension.json new file mode 100644 index 0000000..9309add --- /dev/null +++ b/core/Extensions/view-function-extension/requested-extension.json @@ -0,0 +1,29 @@ +{ + "key": "requested-extension", + "version": "1.0.0", + "domain": "core", + "flow": "sys-extensions", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "view-function-extension", + "requested-extension" + ], + "attributes": { + "type": 4, + "scope": 1, + "task": { + "order": 1, + "task": { + "key": "vfe-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "type": "G", + "location": "./src/RequestedExtensionMapping.csx" + } + } + } +} diff --git a/core/Extensions/view-function-extension/src/GlobalExtensionMapping.csx b/core/Extensions/view-function-extension/src/GlobalExtensionMapping.csx new file mode 100644 index 0000000..36ff29d --- /dev/null +++ b/core/Extensions/view-function-extension/src/GlobalExtensionMapping.csx @@ -0,0 +1,20 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class GlobalExtensionMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + dynamic result = new ExpandoObject(); + result.extensionType = "global"; + result.timestamp = DateTime.UtcNow.ToString("o"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Extensions/view-function-extension/src/RequestedExtensionMapping.csx b/core/Extensions/view-function-extension/src/RequestedExtensionMapping.csx new file mode 100644 index 0000000..8315ec2 --- /dev/null +++ b/core/Extensions/view-function-extension/src/RequestedExtensionMapping.csx @@ -0,0 +1,19 @@ +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class RequestedExtensionMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + dynamic result = new ExpandoObject(); + result.extensionType = "requested"; + result.onDemand = true; + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Functions/view-function-extension/multi-task-function.json b/core/Functions/view-function-extension/multi-task-function.json new file mode 100644 index 0000000..7405e01 --- /dev/null +++ b/core/Functions/view-function-extension/multi-task-function.json @@ -0,0 +1,47 @@ +{ + "key": "multi-task-function", + "version": "1.0.0", + "domain": "core", + "flow": "sys-functions", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "view-function-extension", + "multi-task-function" + ], + "attributes": { + "scope": "I", + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "vfe-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "type": "G", + "location": "./src/FunctionMultiTask1Mapping.csx" + } + }, + { + "order": 2, + "task": { + "key": "vfe-http-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "type": "G", + "location": "./src/FunctionMultiTask2Mapping.csx" + } + } + ], + "output": { + "type": "G", + "location": "./src/FunctionOutputMapping.csx" + } + } +} diff --git a/core/Functions/view-function-extension/single-task-function.json b/core/Functions/view-function-extension/single-task-function.json new file mode 100644 index 0000000..6da0c5b --- /dev/null +++ b/core/Functions/view-function-extension/single-task-function.json @@ -0,0 +1,28 @@ +{ + "key": "single-task-function", + "version": "1.0.0", + "domain": "core", + "flow": "sys-functions", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "view-function-extension", + "single-task-function" + ], + "attributes": { + "scope": "I", + "task": { + "order": 1, + "task": { + "key": "vfe-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "type": "G", + "location": "./src/FunctionSingleTaskMapping.csx" + } + } + } +} diff --git a/core/Functions/view-function-extension/src/FunctionMultiTask1Mapping.csx b/core/Functions/view-function-extension/src/FunctionMultiTask1Mapping.csx new file mode 100644 index 0000000..016e744 --- /dev/null +++ b/core/Functions/view-function-extension/src/FunctionMultiTask1Mapping.csx @@ -0,0 +1,21 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class FunctionMultiTask1Mapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + dynamic result = new ExpandoObject(); + result.step = 1; + result.vfeScript = true; + result.at = DateTime.UtcNow.ToString("o"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Functions/view-function-extension/src/FunctionMultiTask2Mapping.csx b/core/Functions/view-function-extension/src/FunctionMultiTask2Mapping.csx new file mode 100644 index 0000000..de5d5fb --- /dev/null +++ b/core/Functions/view-function-extension/src/FunctionMultiTask2Mapping.csx @@ -0,0 +1,34 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; +using BBT.Workflow.Scripting.Functions; + +public class FunctionMultiTask2Mapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + var httpTask = task as HttpTask; + if (httpTask != null) + { + string baseUrl = GetConfigValue("MocklabBaseUrl"); + httpTask.Url = httpTask.Url.Replace("{MocklabBaseUrl}", baseUrl); + } + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var taskResponse = context.Body; + dynamic result = new ExpandoObject(); + result.step = 2; + result.vfeHttp = true; + if (taskResponse != null && HasProperty(taskResponse, "statusCode")) + result.statusCode = taskResponse.statusCode; + if (taskResponse != null && HasProperty(taskResponse, "data")) + result.userInfo = taskResponse.data; + result.at = DateTime.UtcNow.ToString("o"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Functions/view-function-extension/src/FunctionOutputMapping.csx b/core/Functions/view-function-extension/src/FunctionOutputMapping.csx new file mode 100644 index 0000000..c8fb185 --- /dev/null +++ b/core/Functions/view-function-extension/src/FunctionOutputMapping.csx @@ -0,0 +1,21 @@ +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class FunctionOutputMapping : ScriptBase, IOutputHandler +{ + public Task OutputHandler(ScriptContext context) + { + dynamic result = new ExpandoObject(); + var outputs = context.OutputResponse; + if (outputs != null) + { + if (HasProperty(outputs, "vfeScriptTask")) + result.scriptResult = outputs.vfeScriptTask; + if (HasProperty(outputs, "vfeHttpTask")) + result.httpResult = outputs.vfeHttpTask; + } + result.aggregated = true; + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Functions/view-function-extension/src/FunctionSingleTaskMapping.csx b/core/Functions/view-function-extension/src/FunctionSingleTaskMapping.csx new file mode 100644 index 0000000..02d9cfc --- /dev/null +++ b/core/Functions/view-function-extension/src/FunctionSingleTaskMapping.csx @@ -0,0 +1,20 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class FunctionSingleTaskMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + dynamic result = new ExpandoObject(); + result.singleTaskFunction = true; + result.executedAt = DateTime.UtcNow.ToString("o"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Schemas/schema-data/schema-data-confirm-transition.json b/core/Schemas/schema-data/schema-data-confirm-transition.json new file mode 100644 index 0000000..428efae --- /dev/null +++ b/core/Schemas/schema-data/schema-data-confirm-transition.json @@ -0,0 +1,38 @@ +{ + "key": "schema-data-confirm-transition", + "version": "1.0.0", + "domain": "core", + "flow": "sys-schemas", + "flowVersion": "1.0.0", + "tags": ["integration-test", "schema-data", "transition-schema"], + "attributes": { + "type": "workflow", + "labels": [ + { + "language": "en-US", + "label": "Confirm Transition Schema" + }, + { + "language": "tr-TR", + "label": "Onay Gecisi Semasi" + } + ], + "schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://core.burgan.com/schemas/schema-data-confirm-transition", + "title": "Confirm Transition Payload Schema", + "type": "object", + "properties": { + "confirmed": { + "type": "boolean" + }, + "confirmedBy": { + "type": "string", + "minLength": 1 + } + }, + "required": ["confirmed", "confirmedBy"], + "additionalProperties": true + } + } +} diff --git a/core/Schemas/schema-data/schema-data-master.json b/core/Schemas/schema-data/schema-data-master.json new file mode 100644 index 0000000..aef4852 --- /dev/null +++ b/core/Schemas/schema-data/schema-data-master.json @@ -0,0 +1,67 @@ +{ + "key": "schema-data-master", + "version": "1.0.0", + "domain": "core", + "flow": "sys-schemas", + "flowVersion": "1.0.0", + "tags": ["integration-test", "schema-data", "master-schema", "field-roles"], + "attributes": { + "type": "workflow", + "labels": [ + { + "language": "en-US", + "label": "Schema Data Test Master Schema" + }, + { + "language": "tr-TR", + "label": "Schema Data Test Ana Semasi" + } + ], + "schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://core.burgan.com/schemas/schema-data-master", + "title": "Schema Data Test Master Schema", + "type": "object", + "properties": { + "orderId": { + "type": "string", + "minLength": 1 + }, + "customerName": { + "type": "string", + "minLength": 1 + }, + "amount": { + "type": "number", + "minimum": 0 + }, + "currency": { + "type": "string", + "enum": ["TRY", "USD", "EUR"] + }, + "status": { + "type": "string" + }, + "internalNote": { + "type": "string", + "roles": [ + { "role": "admin", "grant": "allow" }, + { "role": "customer", "grant": "deny" } + ] + }, + "auditLog": { + "type": "string", + "roles": [ + { "role": "auditor", "grant": "allow" } + ] + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "required": ["orderId", "customerName", "amount", "currency"], + "additionalProperties": true + } + } +} diff --git a/core/Tasks/error-boundary/error-http-task.json b/core/Tasks/error-boundary/error-http-task.json new file mode 100644 index 0000000..ba5b7d3 --- /dev/null +++ b/core/Tasks/error-boundary/error-http-task.json @@ -0,0 +1,23 @@ +{ + "key": "error-http-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "error-boundary", + "http-task" + ], + "attributes": { + "type": "6", + "config": { + "url": "{MocklabBaseUrl}/api/test/error-endpoint", + "method": "POST", + "headers": { + "Content-Type": "application/json" + }, + "timeoutSeconds": 30 + } + } +} diff --git a/core/Tasks/error-boundary/error-script-task.json b/core/Tasks/error-boundary/error-script-task.json new file mode 100644 index 0000000..217dabf --- /dev/null +++ b/core/Tasks/error-boundary/error-script-task.json @@ -0,0 +1,16 @@ +{ + "key": "error-script-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "error-boundary", + "script-task" + ], + "attributes": { + "type": "7", + "config": {} + } +} diff --git a/core/Tasks/extended-tasks/dapr-binding-task.json b/core/Tasks/extended-tasks/dapr-binding-task.json new file mode 100644 index 0000000..716c205 --- /dev/null +++ b/core/Tasks/extended-tasks/dapr-binding-task.json @@ -0,0 +1,15 @@ +{ + "key": "dapr-binding-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "extended-tasks", "dapr-binding"], + "attributes": { + "type": "2", + "config": { + "bindingName": "test-binding", + "operation": "create" + } + } +} diff --git a/core/Tasks/extended-tasks/dapr-http-task.json b/core/Tasks/extended-tasks/dapr-http-task.json new file mode 100644 index 0000000..cd48f1f --- /dev/null +++ b/core/Tasks/extended-tasks/dapr-http-task.json @@ -0,0 +1,16 @@ +{ + "key": "dapr-http-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "extended-tasks", "dapr-http"], + "attributes": { + "type": "1", + "config": { + "endpointName": "core-mocklab", + "path": "/api/test/process", + "method": "POST" + } + } +} diff --git a/core/Tasks/extended-tasks/dapr-pubsub-task.json b/core/Tasks/extended-tasks/dapr-pubsub-task.json new file mode 100644 index 0000000..2d80175 --- /dev/null +++ b/core/Tasks/extended-tasks/dapr-pubsub-task.json @@ -0,0 +1,15 @@ +{ + "key": "dapr-pubsub-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "extended-tasks", "dapr-pubsub"], + "attributes": { + "type": "4", + "config": { + "pubSubName": "test-pubsub", + "topic": "test-topic" + } + } +} diff --git a/core/Tasks/extended-tasks/dapr-service-task.json b/core/Tasks/extended-tasks/dapr-service-task.json new file mode 100644 index 0000000..618f4ad --- /dev/null +++ b/core/Tasks/extended-tasks/dapr-service-task.json @@ -0,0 +1,16 @@ +{ + "key": "dapr-service-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "extended-tasks", "dapr-service"], + "attributes": { + "type": "3", + "config": { + "appId": "core-mocklab", + "methodName": "api/test/process", + "httpVerb": "POST" + } + } +} diff --git a/core/Tasks/extended-tasks/get-instances-task.json b/core/Tasks/extended-tasks/get-instances-task.json new file mode 100644 index 0000000..4e03a14 --- /dev/null +++ b/core/Tasks/extended-tasks/get-instances-task.json @@ -0,0 +1,17 @@ +{ + "key": "get-instances-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "extended-tasks", "get-instances"], + "attributes": { + "type": "15", + "config": { + "domain": "core", + "flow": "task-target-workflow", + "page": 1, + "pageSize": 10 + } + } +} diff --git a/core/Tasks/extended-tasks/human-task.json b/core/Tasks/extended-tasks/human-task.json new file mode 100644 index 0000000..ffa89f7 --- /dev/null +++ b/core/Tasks/extended-tasks/human-task.json @@ -0,0 +1,16 @@ +{ + "key": "human-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "extended-tasks", "human-task"], + "attributes": { + "type": "5", + "config": { + "title": "Test Approval", + "instructions": "Approve or reject the test request", + "assignedTo": "test-user" + } + } +} diff --git a/core/Tasks/extended-tasks/notification-task.json b/core/Tasks/extended-tasks/notification-task.json new file mode 100644 index 0000000..0a07c01 --- /dev/null +++ b/core/Tasks/extended-tasks/notification-task.json @@ -0,0 +1,17 @@ +{ + "key": "notification-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "extended-tasks", "notification"], + "attributes": { + "type": "10", + "config": { + "metadata": { + "type": "test", + "channel": "mock" + } + } + } +} diff --git a/core/Tasks/extended-tasks/subprocess-task.json b/core/Tasks/extended-tasks/subprocess-task.json new file mode 100644 index 0000000..b986f08 --- /dev/null +++ b/core/Tasks/extended-tasks/subprocess-task.json @@ -0,0 +1,15 @@ +{ + "key": "subprocess-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "extended-tasks", "subprocess"], + "attributes": { + "type": "14", + "config": { + "domain": "core", + "flow": "task-target-workflow" + } + } +} diff --git a/core/Tasks/extended-tasks/trigger-transition-task.json b/core/Tasks/extended-tasks/trigger-transition-task.json new file mode 100644 index 0000000..7a1b996 --- /dev/null +++ b/core/Tasks/extended-tasks/trigger-transition-task.json @@ -0,0 +1,16 @@ +{ + "key": "trigger-transition-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "extended-tasks", "trigger-transition"], + "attributes": { + "type": "12", + "config": { + "domain": "core", + "flow": "task-target-workflow", + "transitionName": "auto-complete-target" + } + } +} diff --git a/core/Tasks/flow-types/flow-types-script-task.json b/core/Tasks/flow-types/flow-types-script-task.json new file mode 100644 index 0000000..43a4c10 --- /dev/null +++ b/core/Tasks/flow-types/flow-types-script-task.json @@ -0,0 +1,12 @@ +{ + "key": "flow-types-script-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "flow-types", "script"], + "attributes": { + "type": "7", + "config": {} + } +} diff --git a/core/Tasks/instance-management/instance-mgmt-script-task.json b/core/Tasks/instance-management/instance-mgmt-script-task.json new file mode 100644 index 0000000..aea7d9a --- /dev/null +++ b/core/Tasks/instance-management/instance-mgmt-script-task.json @@ -0,0 +1,16 @@ +{ + "key": "instance-mgmt-script-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "instance-management", + "script-task" + ], + "attributes": { + "type": "7", + "config": {} + } +} diff --git a/core/Tasks/lifecycle-transitions/script-task.json b/core/Tasks/lifecycle-transitions/script-task.json new file mode 100644 index 0000000..7ed408a --- /dev/null +++ b/core/Tasks/lifecycle-transitions/script-task.json @@ -0,0 +1,12 @@ +{ + "key": "script-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "script", "reusable"], + "attributes": { + "type": "7", + "config": {} + } +} diff --git a/core/Tasks/schema-data/schema-data-script-task.json b/core/Tasks/schema-data/schema-data-script-task.json new file mode 100644 index 0000000..e2d1ff7 --- /dev/null +++ b/core/Tasks/schema-data/schema-data-script-task.json @@ -0,0 +1,12 @@ +{ + "key": "schema-data-script-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "schema-data", "script"], + "attributes": { + "type": "7", + "config": {} + } +} diff --git a/core/Tasks/subflow-orchestration/subflow-script-task.json b/core/Tasks/subflow-orchestration/subflow-script-task.json new file mode 100644 index 0000000..618a4cc --- /dev/null +++ b/core/Tasks/subflow-orchestration/subflow-script-task.json @@ -0,0 +1,16 @@ +{ + "key": "subflow-script-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "subflow-orchestration", + "script-task" + ], + "attributes": { + "type": "7", + "config": {} + } +} diff --git a/core/Tasks/task-execution/get-instance-data-task.json b/core/Tasks/task-execution/get-instance-data-task.json new file mode 100644 index 0000000..5dd9bd8 --- /dev/null +++ b/core/Tasks/task-execution/get-instance-data-task.json @@ -0,0 +1,19 @@ +{ + "key": "get-instance-data-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "task-execution", + "get-instance-data-task" + ], + "attributes": { + "type": "13", + "config": { + "domain": "core", + "flow": "task-target-workflow" + } + } +} diff --git a/core/Tasks/task-execution/http-process-task.json b/core/Tasks/task-execution/http-process-task.json new file mode 100644 index 0000000..411bc07 --- /dev/null +++ b/core/Tasks/task-execution/http-process-task.json @@ -0,0 +1,23 @@ +{ + "key": "http-process-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "task-execution", + "http-task" + ], + "attributes": { + "type": "6", + "config": { + "url": "{MocklabBaseUrl}/api/test/process", + "method": "POST", + "headers": { + "Content-Type": "application/json" + }, + "timeoutSeconds": 30 + } + } +} diff --git a/core/Tasks/task-execution/start-flow-task.json b/core/Tasks/task-execution/start-flow-task.json new file mode 100644 index 0000000..73dc9ba --- /dev/null +++ b/core/Tasks/task-execution/start-flow-task.json @@ -0,0 +1,19 @@ +{ + "key": "start-flow-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "task-execution", + "start-flow-task" + ], + "attributes": { + "type": "11", + "config": { + "domain": "core", + "flow": "task-target-workflow" + } + } +} diff --git a/core/Tasks/task-execution/task-exec-script-task.json b/core/Tasks/task-execution/task-exec-script-task.json new file mode 100644 index 0000000..4bc89dc --- /dev/null +++ b/core/Tasks/task-execution/task-exec-script-task.json @@ -0,0 +1,16 @@ +{ + "key": "task-exec-script-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "task-execution", + "script-task" + ], + "attributes": { + "type": "7", + "config": {} + } +} diff --git a/core/Tasks/version-consistency/version-consistency-script-task.json b/core/Tasks/version-consistency/version-consistency-script-task.json new file mode 100644 index 0000000..3f23401 --- /dev/null +++ b/core/Tasks/version-consistency/version-consistency-script-task.json @@ -0,0 +1,12 @@ +{ + "key": "version-consistency-script-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": ["integration-test", "version-consistency", "script"], + "attributes": { + "type": "7", + "config": {} + } +} diff --git a/core/Tasks/view-function-extension/vfe-http-task.json b/core/Tasks/view-function-extension/vfe-http-task.json new file mode 100644 index 0000000..28c06a7 --- /dev/null +++ b/core/Tasks/view-function-extension/vfe-http-task.json @@ -0,0 +1,21 @@ +{ + "key": "vfe-http-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "view-function-extension", + "http-task" + ], + "attributes": { + "type": "6", + "config": { + "url": "{MocklabBaseUrl}/api/test/user-info", + "method": "GET", + "headers": {}, + "timeoutSeconds": 30 + } + } +} diff --git a/core/Tasks/view-function-extension/vfe-script-task.json b/core/Tasks/view-function-extension/vfe-script-task.json new file mode 100644 index 0000000..3c88264 --- /dev/null +++ b/core/Tasks/view-function-extension/vfe-script-task.json @@ -0,0 +1,16 @@ +{ + "key": "vfe-script-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "view-function-extension", + "script-task" + ], + "attributes": { + "type": "7", + "config": {} + } +} diff --git a/core/Views/view-function-extension/html-view.json b/core/Views/view-function-extension/html-view.json new file mode 100644 index 0000000..2feb09a --- /dev/null +++ b/core/Views/view-function-extension/html-view.json @@ -0,0 +1,17 @@ +{ + "key": "html-view", + "version": "1.0.0", + "domain": "core", + "flow": "sys-views", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "view-function-extension", + "html-view" + ], + "attributes": { + "type": 2, + "display": "popup", + "content": "

HTML View Test

Integration test view

" + } +} diff --git a/core/Views/view-function-extension/json-view.json b/core/Views/view-function-extension/json-view.json new file mode 100644 index 0000000..7deb215 --- /dev/null +++ b/core/Views/view-function-extension/json-view.json @@ -0,0 +1,17 @@ +{ + "key": "json-view", + "version": "1.0.0", + "domain": "core", + "flow": "sys-views", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "view-function-extension", + "json-view" + ], + "attributes": { + "type": 1, + "display": "full-page", + "content": "{\"title\":\"JSON View Test\",\"fields\":[{\"key\":\"status\",\"label\":\"Status\"}]}" + } +} diff --git a/core/Views/view-function-extension/markdown-view.json b/core/Views/view-function-extension/markdown-view.json new file mode 100644 index 0000000..4cb62ca --- /dev/null +++ b/core/Views/view-function-extension/markdown-view.json @@ -0,0 +1,17 @@ +{ + "key": "markdown-view", + "version": "1.0.0", + "domain": "core", + "flow": "sys-views", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "view-function-extension", + "markdown-view" + ], + "attributes": { + "type": 3, + "display": "bottom-sheet", + "content": "# Markdown View\n\nIntegration test view" + } +} diff --git a/core/Workflows/account-opening/account-opening-workflow.json b/core/Workflows/account-opening/account-opening-workflow.json index 7d1bc66..9fe4f48 100644 --- a/core/Workflows/account-opening/account-opening-workflow.json +++ b/core/Workflows/account-opening/account-opening-workflow.json @@ -683,7 +683,7 @@ { "key": "timeouted", "stateType": 3, - "subType": 8, + "subType": 6, "versionStrategy": "Minor", "labels": [ { diff --git a/core/Workflows/collection-object-test/collection-object-test-workflow.json b/core/Workflows/collection-object-test/collection-object-test-workflow.json index 199bf5a..405909a 100644 --- a/core/Workflows/collection-object-test/collection-object-test-workflow.json +++ b/core/Workflows/collection-object-test/collection-object-test-workflow.json @@ -127,7 +127,7 @@ "schema": null, "rule": { "location": "./src/AlwaysTrueRule.csx", - "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cg==" + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cgo=" }, "timer": null, "view": null, @@ -187,7 +187,7 @@ "schema": null, "rule": { "location": "./src/AlwaysTrueRule.csx", - "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cg==" + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cgo=" }, "timer": null, "view": null, @@ -247,7 +247,7 @@ "schema": null, "rule": { "location": "./src/AlwaysTrueRule.csx", - "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cg==" + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cgo=" }, "timer": null, "view": null, @@ -307,7 +307,7 @@ "schema": null, "rule": { "location": "./src/AlwaysTrueRule.csx", - "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cg==" + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cgo=" }, "timer": null, "view": null, @@ -367,7 +367,7 @@ "schema": null, "rule": { "location": "./src/AlwaysTrueRule.csx", - "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cg==" + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cgo=" }, "timer": null, "view": null, @@ -427,7 +427,7 @@ "schema": null, "rule": { "location": "./src/AlwaysTrueRule.csx", - "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cg==" + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cgo=" }, "timer": null, "view": null, @@ -487,7 +487,7 @@ "schema": null, "rule": { "location": "./src/AlwaysTrueRule.csx", - "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cg==" + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9Cgo=" }, "timer": null, "view": null, diff --git a/core/Workflows/collection-object-test/src/AlwaysTrueRule.csx b/core/Workflows/collection-object-test/src/AlwaysTrueRule.csx index 28bac4f..2dc331f 100644 --- a/core/Workflows/collection-object-test/src/AlwaysTrueRule.csx +++ b/core/Workflows/collection-object-test/src/AlwaysTrueRule.csx @@ -8,3 +8,4 @@ public class AlwaysTrueRule : IConditionMapping return true; } } + diff --git a/core/Workflows/error-boundary/error-boundary-test-workflow.json b/core/Workflows/error-boundary/error-boundary-test-workflow.json new file mode 100644 index 0000000..06f0609 --- /dev/null +++ b/core/Workflows/error-boundary/error-boundary-test-workflow.json @@ -0,0 +1,520 @@ +{ + "key": "error-boundary-test-workflow", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "error-boundary", + "retry", + "abort", + "ignore", + "log", + "rollback", + "log-action", + "retry-policy", + "priority", + "task-level-boundary", + "state-level-boundary", + "global-boundary", + "notify", + "notify-action", + "timeout-policy", + "error-types", + "error-codes" + ], + "attributes": { + "type": "F", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "Error Boundary Integration Test" + }, + { + "language": "tr-TR", + "label": "Hata Sinir Entegrasyon Testi" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [], + "errorBoundary": { + "onError": [ + { + "action": 0, + "priority": 100 + } + ], + "onTimeout": { + "action": 3 + } + }, + "startTransition": { + "key": "start-error-boundary-test", + "target": "retry-test-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Error Boundary Test" + }, + { + "language": "tr-TR", + "label": "Hata Sinir Testini Baslat" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "error-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/InitErrorTestMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBJbml0RXJyb3JUZXN0TWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHJlc3VsdC50ZXN0SWQgPSBHdWlkLk5ld0d1aWQoKS5Ub1N0cmluZygpOwogICAgICAgIHJlc3VsdC5lcnJvclRlc3RTdGFydGVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQuc3RhcnRlZEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CiAgICAgICAgTG9nSW5mb3JtYXRpb24oIkluaXRFcnJvclRlc3RNYXBwaW5nOiBlcnJvciBib3VuZGFyeSBpbnRlZ3JhdGlvbiB0ZXN0IGluaXRpYWxpemVkIik7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ] + }, + "states": [ + { + "key": "retry-test-state", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Retry Test State" + }, + { + "language": "tr-TR", + "label": "Yeniden Deneme Test Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "error-http-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ErrorHttpMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nLkZ1bmN0aW9uczsKCnB1YmxpYyBjbGFzcyBFcnJvckh0dHBNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIGFzeW5jIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBodHRwVGFzayA9ICh0YXNrIGFzIEh0dHBUYXNrKSE7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgc3RyaW5nIGJhc2VVcmwgPSBHZXRDb25maWdWYWx1ZSgiTW9ja2xhYkJhc2VVcmwiKTsKICAgICAgICBodHRwVGFzay5VcmwgPSBodHRwVGFzay5VcmwuUmVwbGFjZSgie01vY2tsYWJCYXNlVXJsfSIsIGJhc2VVcmwpOwogICAgICAgIHZhciBib2R5ID0gbmV3CiAgICAgICAgewogICAgICAgICAgICBzb3VyY2UgPSAiZXJyb3ItYm91bmRhcnktdGVzdCIsCiAgICAgICAgICAgIHRlc3RJZCA9IEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSA/IGRhdGEudGVzdElkIDogbnVsbCwKICAgICAgICAgICAgdGltZXN0YW1wID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIikKICAgICAgICB9OwogICAgICAgIGh0dHBUYXNrLlNldEJvZHkoYm9keSk7CiAgICAgICAgcmV0dXJuIG5ldyBTY3JpcHRSZXNwb25zZSgpOwogICAgfQoKICAgIHB1YmxpYyBhc3luYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKICAgICAgICB2YXIgdGFza1Jlc3BvbnNlID0gY29udGV4dC5Cb2R5OwogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKSByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJlcnJvclRlc3RTdGFydGVkIikpIHJlc3VsdC5lcnJvclRlc3RTdGFydGVkID0gZGF0YS5lcnJvclRlc3RTdGFydGVkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAic3RhcnRlZEF0IikpIHJlc3VsdC5zdGFydGVkQXQgPSBkYXRhLnN0YXJ0ZWRBdDsKICAgICAgICByZXN1bHQuaHR0cEVycm9ySGFuZGxlZCA9IHRydWU7CiAgICAgICAgaWYgKHRhc2tSZXNwb25zZSAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgcmVzdWx0Lmh0dHBTdGF0dXNDb2RlID0gdGFza1Jlc3BvbnNlLnN0YXR1c0NvZGU7CiAgICAgICAgICAgIHJlc3VsdC5odHRwSXNTdWNjZXNzID0gdGFza1Jlc3BvbnNlLmlzU3VjY2VzczsKICAgICAgICAgICAgaWYgKHRhc2tSZXNwb25zZS5kYXRhICE9IG51bGwpCiAgICAgICAgICAgICAgICByZXN1bHQuaHR0cFJlc3BvbnNlRGF0YSA9IHRhc2tSZXNwb25zZS5kYXRhOwogICAgICAgIH0KICAgICAgICBMb2dJbmZvcm1hdGlvbigiRXJyb3JIdHRwTWFwcGluZzogb3V0cHV0IGFmdGVyIEhUVFAgY2FsbCAoZXJyb3IgYm91bmRhcnkgbWF5IGhhdmUgcmV0cmllZCkiKTsKICAgICAgICByZXR1cm4gbmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9OwogICAgfQp9Cg==" + }, + "errorBoundary": { + "onError": [ + { + "action": 1, + "priority": 10, + "retryPolicy": { + "maxRetries": 2, + "initialDelay": "PT2S", + "backoffType": 0 + } + } + ] + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-ignore-test", + "target": "ignore-test-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Ignore Test" + }, + { + "language": "tr-TR", + "label": "Yoksayma Testine Otomatik Gecis" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "ignore-test-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Ignore Test State" + }, + { + "language": "tr-TR", + "label": "Yoksayma Test Durumu" + } + ], + "view": null, + "subFlow": null, + "errorBoundary": { + "onError": [ + { + "action": 3, + "priority": 10, + "errorTypes": [ + "System.InvalidOperationException" + ], + "errorCodes": [ + "*" + ] + } + ] + }, + "onEntries": [ + { + "order": 1, + "task": { + "key": "error-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ThrowErrorMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uVGhyZWFkaW5nLlRhc2tzOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nOwoKcHVibGljIGNsYXNzIFRocm93RXJyb3JNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCJJbnRlbnRpb25hbCB0ZXN0IGVycm9yIGZvciBlcnJvciBib3VuZGFyeSIpOwogICAgfQp9Cg==" + } + }, + { + "order": 2, + "task": { + "key": "error-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/IgnoreErrorMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBJZ25vcmVFcnJvck1hcHBpbmcgOiBTY3JpcHRCYXNlLCBJTWFwcGluZwp7CiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFdvcmtmbG93VGFzayB0YXNrLCBTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UoKSk7CiAgICB9CgogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKSByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJlcnJvclRlc3RTdGFydGVkIikpIHJlc3VsdC5lcnJvclRlc3RTdGFydGVkID0gZGF0YS5lcnJvclRlc3RTdGFydGVkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaHR0cEVycm9ySGFuZGxlZCIpKSByZXN1bHQuaHR0cEVycm9ySGFuZGxlZCA9IGRhdGEuaHR0cEVycm9ySGFuZGxlZDsKICAgICAgICByZXN1bHQuZXJyb3JJZ25vcmVkID0gdHJ1ZTsKICAgICAgICBMb2dJbmZvcm1hdGlvbigiSWdub3JlRXJyb3JNYXBwaW5nOiBjb250aW51YXRpb24gYWZ0ZXIgaWdub3JlIHBvbGljeSIpOwogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-rollback-from-ignore", + "target": "rollback-test-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Rollback from Ignore" + }, + { + "language": "tr-TR", + "label": "Ignore'dan Rollback'e Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "rollback-test-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Rollback Action Test" + }, + { + "language": "tr-TR", + "label": "Rollback Action Testi" + } + ], + "view": null, + "subFlow": null, + "errorBoundary": { + "onError": [ + { + "action": 2, + "priority": 10 + } + ] + }, + "onEntries": [ + { + "order": 1, + "task": { + "key": "error-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ThrowErrorMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uVGhyZWFkaW5nLlRhc2tzOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nOwoKcHVibGljIGNsYXNzIFRocm93RXJyb3JNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCJJbnRlbnRpb25hbCB0ZXN0IGVycm9yIGZvciBlcnJvciBib3VuZGFyeSIpOwogICAgfQp9Cg==" + } + }, + { + "order": 2, + "task": { + "key": "error-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/RollbackMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFJvbGxiYWNrTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKQogICAgICAgICAgICByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJyZXRyeUNvbXBsZXRlZCIpKQogICAgICAgICAgICByZXN1bHQucmV0cnlDb21wbGV0ZWQgPSBkYXRhLnJldHJ5Q29tcGxldGVkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiZXJyb3JJZ25vcmVkIikpCiAgICAgICAgICAgIHJlc3VsdC5lcnJvcklnbm9yZWQgPSBkYXRhLmVycm9ySWdub3JlZDsKCiAgICAgICAgcmVzdWx0LnJvbGxiYWNrRXhlY3V0ZWQgPSB0cnVlOwogICAgICAgIHJlc3VsdC5yb2xsYmFja0F0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCJSb2xsYmFja01hcHBpbmcgY29tcGxldGVkIC0gcm9sbGJhY2sgYWN0aW9uIHRlc3QiKTsKCiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-log-from-rollback", + "target": "log-test-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Log from Rollback" + }, + { + "language": "tr-TR", + "label": "Rollback'den Log'a Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "log-test-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Log Action Test" + }, + { + "language": "tr-TR", + "label": "Log Action Testi" + } + ], + "view": null, + "subFlow": null, + "errorBoundary": { + "onError": [ + { + "action": 5, + "priority": 10 + } + ] + }, + "onEntries": [ + { + "order": 1, + "task": { + "key": "error-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ThrowErrorMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uVGhyZWFkaW5nLlRhc2tzOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nOwoKcHVibGljIGNsYXNzIFRocm93RXJyb3JNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCJJbnRlbnRpb25hbCB0ZXN0IGVycm9yIGZvciBlcnJvciBib3VuZGFyeSIpOwogICAgfQp9Cg==" + } + }, + { + "order": 2, + "task": { + "key": "error-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/LogOnlyMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBMb2dPbmx5TWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAidGVzdElkIikpIHJlc3VsdC50ZXN0SWQgPSBkYXRhLnRlc3RJZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImVycm9yVGVzdFN0YXJ0ZWQiKSkgcmVzdWx0LmVycm9yVGVzdFN0YXJ0ZWQgPSBkYXRhLmVycm9yVGVzdFN0YXJ0ZWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJodHRwRXJyb3JIYW5kbGVkIikpIHJlc3VsdC5odHRwRXJyb3JIYW5kbGVkID0gZGF0YS5odHRwRXJyb3JIYW5kbGVkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiZXJyb3JJZ25vcmVkIikpIHJlc3VsdC5lcnJvcklnbm9yZWQgPSBkYXRhLmVycm9ySWdub3JlZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInJvbGxiYWNrRXhlY3V0ZWQiKSkgcmVzdWx0LnJvbGxiYWNrRXhlY3V0ZWQgPSBkYXRhLnJvbGxiYWNrRXhlY3V0ZWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJyb2xsYmFja0F0IikpIHJlc3VsdC5yb2xsYmFja0F0ID0gZGF0YS5yb2xsYmFja0F0OwogICAgICAgIHJlc3VsdC5sb2dPbmx5RXhlY3V0ZWQgPSB0cnVlOwogICAgICAgIExvZ0luZm9ybWF0aW9uKCJMb2dPbmx5TWFwcGluZzogbG9nLW9ubHkgcGF0aCBleGVjdXRlZCIpOwogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-completed-from-log", + "target": "notify-test-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Completed from Log" + }, + { + "language": "tr-TR", + "label": "Log'dan Completed'a Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "notify-test-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Notify Action Test" + }, + { + "language": "tr-TR", + "label": "Notify Action Testi" + } + ], + "view": null, + "subFlow": null, + "errorBoundary": { + "onError": [ + { + "action": 4, + "priority": 10, + "transition": "auto-to-completed-from-notify" + } + ] + }, + "onEntries": [ + { + "order": 1, + "task": { + "key": "error-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ThrowErrorMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uVGhyZWFkaW5nLlRhc2tzOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nOwoKcHVibGljIGNsYXNzIFRocm93RXJyb3JNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCJJbnRlbnRpb25hbCB0ZXN0IGVycm9yIGZvciBlcnJvciBib3VuZGFyeSIpOwogICAgfQp9Cg==" + } + }, + { + "order": 2, + "task": { + "key": "error-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/NotifyMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIE5vdGlmeU1hcHBpbmcgOiBTY3JpcHRCYXNlLCBJTWFwcGluZwp7CiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFdvcmtmbG93VGFzayB0YXNrLCBTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UoKSk7CiAgICB9CgogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKCiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSkKICAgICAgICAgICAgcmVzdWx0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAicmV0cnlDb21wbGV0ZWQiKSkKICAgICAgICAgICAgcmVzdWx0LnJldHJ5Q29tcGxldGVkID0gZGF0YS5yZXRyeUNvbXBsZXRlZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImVycm9ySWdub3JlZCIpKQogICAgICAgICAgICByZXN1bHQuZXJyb3JJZ25vcmVkID0gZGF0YS5lcnJvcklnbm9yZWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJyb2xsYmFja0V4ZWN1dGVkIikpCiAgICAgICAgICAgIHJlc3VsdC5yb2xsYmFja0V4ZWN1dGVkID0gZGF0YS5yb2xsYmFja0V4ZWN1dGVkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAicm9sbGJhY2tBdCIpKQogICAgICAgICAgICByZXN1bHQucm9sbGJhY2tBdCA9IGRhdGEucm9sbGJhY2tBdDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImxvZ0V4ZWN1dGVkIikpCiAgICAgICAgICAgIHJlc3VsdC5sb2dFeGVjdXRlZCA9IGRhdGEubG9nRXhlY3V0ZWQ7CgogICAgICAgIHJlc3VsdC5ub3RpZnlFeGVjdXRlZCA9IHRydWU7CiAgICAgICAgcmVzdWx0Lm5vdGlmeUF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCJOb3RpZnlNYXBwaW5nIGNvbXBsZXRlZCAtIG5vdGlmeSBhY3Rpb24gdGVzdCIpOwoKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-completed-from-notify", + "target": "completed-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Completed from Notify" + }, + { + "language": "tr-TR", + "label": "Notify'dan Completed'a Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "completed-state", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Success Final" + }, + { + "language": "tr-TR", + "label": "Basari Son" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + }, + { + "key": "error-final", + "stateType": 3, + "subType": 2, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Error Final" + }, + { + "language": "tr-TR", + "label": "Hata Son" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/error-boundary/src/AlwaysTrueRule.csx b/core/Workflows/error-boundary/src/AlwaysTrueRule.csx new file mode 100644 index 0000000..3d08a0f --- /dev/null +++ b/core/Workflows/error-boundary/src/AlwaysTrueRule.csx @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class AlwaysTrueRule : ScriptBase, IConditionMapping +{ + public Task Handler(ScriptContext context) + { + LogInformation("AlwaysTrueRule: returning true"); + return Task.FromResult(true); + } +} diff --git a/core/Workflows/error-boundary/src/ErrorHttpMapping.csx b/core/Workflows/error-boundary/src/ErrorHttpMapping.csx new file mode 100644 index 0000000..ffc5847 --- /dev/null +++ b/core/Workflows/error-boundary/src/ErrorHttpMapping.csx @@ -0,0 +1,45 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; +using BBT.Workflow.Scripting.Functions; + +public class ErrorHttpMapping : ScriptBase, IMapping +{ + public async Task InputHandler(WorkflowTask task, ScriptContext context) + { + var httpTask = (task as HttpTask)!; + var data = context.Instance.Data; + string baseUrl = GetConfigValue("MocklabBaseUrl"); + httpTask.Url = httpTask.Url.Replace("{MocklabBaseUrl}", baseUrl); + var body = new + { + source = "error-boundary-test", + testId = HasProperty(data, "testId") ? data.testId : null, + timestamp = DateTime.UtcNow.ToString("o") + }; + httpTask.SetBody(body); + return new ScriptResponse(); + } + + public async Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + var taskResponse = context.Body; + dynamic result = new ExpandoObject(); + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "errorTestStarted")) result.errorTestStarted = data.errorTestStarted; + if (HasProperty(data, "startedAt")) result.startedAt = data.startedAt; + result.httpErrorHandled = true; + if (taskResponse != null) + { + result.httpStatusCode = taskResponse.statusCode; + result.httpIsSuccess = taskResponse.isSuccess; + if (taskResponse.data != null) + result.httpResponseData = taskResponse.data; + } + LogInformation("ErrorHttpMapping: output after HTTP call (error boundary may have retried)"); + return new ScriptResponse { Data = result }; + } +} diff --git a/core/Workflows/error-boundary/src/IgnoreErrorMapping.csx b/core/Workflows/error-boundary/src/IgnoreErrorMapping.csx new file mode 100644 index 0000000..e0afa8b --- /dev/null +++ b/core/Workflows/error-boundary/src/IgnoreErrorMapping.csx @@ -0,0 +1,24 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class IgnoreErrorMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "errorTestStarted")) result.errorTestStarted = data.errorTestStarted; + if (HasProperty(data, "httpErrorHandled")) result.httpErrorHandled = data.httpErrorHandled; + result.errorIgnored = true; + LogInformation("IgnoreErrorMapping: continuation after ignore policy"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/error-boundary/src/InitErrorTestMapping.csx b/core/Workflows/error-boundary/src/InitErrorTestMapping.csx new file mode 100644 index 0000000..8eafc52 --- /dev/null +++ b/core/Workflows/error-boundary/src/InitErrorTestMapping.csx @@ -0,0 +1,22 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class InitErrorTestMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + dynamic result = new ExpandoObject(); + result.testId = Guid.NewGuid().ToString(); + result.errorTestStarted = true; + result.startedAt = DateTime.UtcNow.ToString("o"); + LogInformation("InitErrorTestMapping: error boundary integration test initialized"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/error-boundary/src/LogOnlyMapping.csx b/core/Workflows/error-boundary/src/LogOnlyMapping.csx new file mode 100644 index 0000000..4e54c8b --- /dev/null +++ b/core/Workflows/error-boundary/src/LogOnlyMapping.csx @@ -0,0 +1,27 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class LogOnlyMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "errorTestStarted")) result.errorTestStarted = data.errorTestStarted; + if (HasProperty(data, "httpErrorHandled")) result.httpErrorHandled = data.httpErrorHandled; + if (HasProperty(data, "errorIgnored")) result.errorIgnored = data.errorIgnored; + if (HasProperty(data, "rollbackExecuted")) result.rollbackExecuted = data.rollbackExecuted; + if (HasProperty(data, "rollbackAt")) result.rollbackAt = data.rollbackAt; + result.logOnlyExecuted = true; + LogInformation("LogOnlyMapping: log-only path executed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/error-boundary/src/NotifyMapping.csx b/core/Workflows/error-boundary/src/NotifyMapping.csx new file mode 100644 index 0000000..dff8b4e --- /dev/null +++ b/core/Workflows/error-boundary/src/NotifyMapping.csx @@ -0,0 +1,39 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class NotifyMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) + result.testId = data.testId; + if (HasProperty(data, "retryCompleted")) + result.retryCompleted = data.retryCompleted; + if (HasProperty(data, "errorIgnored")) + result.errorIgnored = data.errorIgnored; + if (HasProperty(data, "rollbackExecuted")) + result.rollbackExecuted = data.rollbackExecuted; + if (HasProperty(data, "rollbackAt")) + result.rollbackAt = data.rollbackAt; + if (HasProperty(data, "logExecuted")) + result.logExecuted = data.logExecuted; + + result.notifyExecuted = true; + result.notifyAt = DateTime.UtcNow.ToString("o"); + + LogInformation("NotifyMapping completed - notify action test"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/error-boundary/src/RollbackMapping.csx b/core/Workflows/error-boundary/src/RollbackMapping.csx new file mode 100644 index 0000000..8d54fb9 --- /dev/null +++ b/core/Workflows/error-boundary/src/RollbackMapping.csx @@ -0,0 +1,33 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class RollbackMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) + result.testId = data.testId; + if (HasProperty(data, "retryCompleted")) + result.retryCompleted = data.retryCompleted; + if (HasProperty(data, "errorIgnored")) + result.errorIgnored = data.errorIgnored; + + result.rollbackExecuted = true; + result.rollbackAt = DateTime.UtcNow.ToString("o"); + + LogInformation("RollbackMapping completed - rollback action test"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/error-boundary/src/ThrowErrorMapping.csx b/core/Workflows/error-boundary/src/ThrowErrorMapping.csx new file mode 100644 index 0000000..1f49421 --- /dev/null +++ b/core/Workflows/error-boundary/src/ThrowErrorMapping.csx @@ -0,0 +1,16 @@ +using System; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class ThrowErrorMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + throw new Exception("Intentional test error for error boundary"); + } +} diff --git a/core/Workflows/extended-tasks/extended-tasks-test-workflow.json b/core/Workflows/extended-tasks/extended-tasks-test-workflow.json new file mode 100644 index 0000000..9c6b994 --- /dev/null +++ b/core/Workflows/extended-tasks/extended-tasks-test-workflow.json @@ -0,0 +1,644 @@ +{ + "key": "extended-tasks-test-workflow", + "version": "1.0.0", + "domain": "core", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "tags": [ + "integration-test", + "extended-tasks", + "dapr-http", + "dapr-binding", + "dapr-service", + "dapr-pubsub", + "human-task", + "notification", + "trigger-transition", + "subprocess", + "get-instances" + ], + "attributes": { + "type": "F", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "Extended Tasks Test Workflow" + }, + { + "language": "tr-TR", + "label": "Genisletilmis Gorev Tipleri Test Is Akisi" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [], + "startTransition": { + "key": "start-extended-tasks", + "target": "init-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Extended Tasks Test" + }, + { + "language": "tr-TR", + "label": "Genisletilmis Gorev Testini Baslat" + } + ], + "onExecutionTasks": [] + }, + "states": [ + { + "key": "init-state", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Initialize" + }, + { + "language": "tr-TR", + "label": "Baslangic" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "script-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/InitExtendedTaskMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIEluaXRFeHRlbmRlZFRhc2tNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CgogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAidGVzdElkIikpCiAgICAgICAgICAgIHJlc3VsdC50ZXN0SWQgPSBkYXRhLnRlc3RJZDsKCiAgICAgICAgcmVzdWx0LmluaXRDb21wbGV0ZWQgPSB0cnVlOwogICAgICAgIHJlc3VsdC5pbml0QXQgPSBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoIm8iKTsKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBMb2dJbmZvcm1hdGlvbigiSW5pdEV4dGVuZGVkVGFza01hcHBpbmcgY29tcGxldGVkIik7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-dapr-http", + "target": "dapr-http-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Dapr HTTP" + }, + { + "language": "tr-TR", + "label": "Dapr HTTP'ye Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "dapr-http-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Dapr HTTP Task" + }, + { + "language": "tr-TR", + "label": "Dapr HTTP Gorevi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "dapr-http-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/DaprHttpMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIERhcHJIdHRwTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKSByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJpbml0Q29tcGxldGVkIikpIHJlc3VsdC5pbml0Q29tcGxldGVkID0gZGF0YS5pbml0Q29tcGxldGVkOwoKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAidGFza1Jlc3VsdHMiKSkKICAgICAgICB7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZGFwclNlcnZpY2UiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJTZXJ2aWNlID0gZGF0YS50YXNrUmVzdWx0cy5kYXByU2VydmljZTsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJub3RpZmljYXRpb24iKSkgcmVzdWx0LnRhc2tSZXN1bHRzLm5vdGlmaWNhdGlvbiA9IGRhdGEudGFza1Jlc3VsdHMubm90aWZpY2F0aW9uOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgInRyaWdnZXJUcmFuc2l0aW9uIikpIHJlc3VsdC50YXNrUmVzdWx0cy50cmlnZ2VyVHJhbnNpdGlvbiA9IGRhdGEudGFza1Jlc3VsdHMudHJpZ2dlclRyYW5zaXRpb247CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZ2V0SW5zdGFuY2VzIikpIHJlc3VsdC50YXNrUmVzdWx0cy5nZXRJbnN0YW5jZXMgPSBkYXRhLnRhc2tSZXN1bHRzLmdldEluc3RhbmNlczsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJzdWJwcm9jZXNzIikpIHJlc3VsdC50YXNrUmVzdWx0cy5zdWJwcm9jZXNzID0gZGF0YS50YXNrUmVzdWx0cy5zdWJwcm9jZXNzOwogICAgICAgIH0KCiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJIdHRwID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMuZGFwckh0dHAuY29tcGxldGVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMuZGFwckh0dHAuZXhlY3V0ZWRBdCA9IERhdGVUaW1lLlV0Y05vdy5Ub1N0cmluZygibyIpOwoKICAgICAgICB2YXIgdGFza1Jlc3BvbnNlID0gY29udGV4dC5Cb2R5OwogICAgICAgIGlmICh0YXNrUmVzcG9uc2UgIT0gbnVsbCAmJiBIYXNQcm9wZXJ0eSh0YXNrUmVzcG9uc2UsICJkYXRhIikpCiAgICAgICAgewogICAgICAgICAgICB2YXIgcmVzcG9uc2VEYXRhID0gdGFza1Jlc3BvbnNlLmRhdGE7CiAgICAgICAgICAgIGlmIChyZXNwb25zZURhdGEgIT0gbnVsbCAmJiBIYXNQcm9wZXJ0eShyZXNwb25zZURhdGEsICJwcm9jZXNzSWQiKSkKICAgICAgICAgICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cy5kYXBySHR0cC5wcm9jZXNzSWQgPSByZXNwb25zZURhdGEucHJvY2Vzc0lkOwogICAgICAgIH0KCiAgICAgICAgTG9nSW5mb3JtYXRpb24oIkRhcHJIdHRwTWFwcGluZyBjb21wbGV0ZWQiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-dapr-service", + "target": "dapr-service-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Dapr Service" + }, + { + "language": "tr-TR", + "label": "Dapr Service'e Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "dapr-service-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Dapr Service Task" + }, + { + "language": "tr-TR", + "label": "Dapr Service Gorevi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "dapr-service-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/DaprServiceMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIERhcHJTZXJ2aWNlTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKSByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJpbml0Q29tcGxldGVkIikpIHJlc3VsdC5pbml0Q29tcGxldGVkID0gZGF0YS5pbml0Q29tcGxldGVkOwoKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAidGFza1Jlc3VsdHMiKSkKICAgICAgICB7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZGFwckh0dHAiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJIdHRwID0gZGF0YS50YXNrUmVzdWx0cy5kYXBySHR0cDsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJub3RpZmljYXRpb24iKSkgcmVzdWx0LnRhc2tSZXN1bHRzLm5vdGlmaWNhdGlvbiA9IGRhdGEudGFza1Jlc3VsdHMubm90aWZpY2F0aW9uOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgInRyaWdnZXJUcmFuc2l0aW9uIikpIHJlc3VsdC50YXNrUmVzdWx0cy50cmlnZ2VyVHJhbnNpdGlvbiA9IGRhdGEudGFza1Jlc3VsdHMudHJpZ2dlclRyYW5zaXRpb247CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZ2V0SW5zdGFuY2VzIikpIHJlc3VsdC50YXNrUmVzdWx0cy5nZXRJbnN0YW5jZXMgPSBkYXRhLnRhc2tSZXN1bHRzLmdldEluc3RhbmNlczsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJzdWJwcm9jZXNzIikpIHJlc3VsdC50YXNrUmVzdWx0cy5zdWJwcm9jZXNzID0gZGF0YS50YXNrUmVzdWx0cy5zdWJwcm9jZXNzOwogICAgICAgIH0KCiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJTZXJ2aWNlID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMuZGFwclNlcnZpY2UuY29tcGxldGVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMuZGFwclNlcnZpY2UuZXhlY3V0ZWRBdCA9IERhdGVUaW1lLlV0Y05vdy5Ub1N0cmluZygibyIpOwoKICAgICAgICB2YXIgdGFza1Jlc3BvbnNlID0gY29udGV4dC5Cb2R5OwogICAgICAgIGlmICh0YXNrUmVzcG9uc2UgIT0gbnVsbCAmJiBIYXNQcm9wZXJ0eSh0YXNrUmVzcG9uc2UsICJkYXRhIikpCiAgICAgICAgewogICAgICAgICAgICB2YXIgcmVzcG9uc2VEYXRhID0gdGFza1Jlc3BvbnNlLmRhdGE7CiAgICAgICAgICAgIGlmIChyZXNwb25zZURhdGEgIT0gbnVsbCAmJiBIYXNQcm9wZXJ0eShyZXNwb25zZURhdGEsICJwcm9jZXNzSWQiKSkKICAgICAgICAgICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cy5kYXByU2VydmljZS5wcm9jZXNzSWQgPSByZXNwb25zZURhdGEucHJvY2Vzc0lkOwogICAgICAgIH0KCiAgICAgICAgTG9nSW5mb3JtYXRpb24oIkRhcHJTZXJ2aWNlTWFwcGluZyBjb21wbGV0ZWQiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-dapr-binding", + "target": "dapr-binding-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Dapr Binding" + }, + { + "language": "tr-TR", + "label": "Dapr Binding'e Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "dapr-binding-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Dapr Binding Task" + }, + { + "language": "tr-TR", + "label": "Dapr Binding Gorevi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "dapr-binding-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/DaprBindingMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIERhcHJCaW5kaW5nTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKSByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJpbml0Q29tcGxldGVkIikpIHJlc3VsdC5pbml0Q29tcGxldGVkID0gZGF0YS5pbml0Q29tcGxldGVkOwoKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAidGFza1Jlc3VsdHMiKSkKICAgICAgICB7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZGFwckh0dHAiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJIdHRwID0gZGF0YS50YXNrUmVzdWx0cy5kYXBySHR0cDsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJkYXByU2VydmljZSIpKSByZXN1bHQudGFza1Jlc3VsdHMuZGFwclNlcnZpY2UgPSBkYXRhLnRhc2tSZXN1bHRzLmRhcHJTZXJ2aWNlOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgIm5vdGlmaWNhdGlvbiIpKSByZXN1bHQudGFza1Jlc3VsdHMubm90aWZpY2F0aW9uID0gZGF0YS50YXNrUmVzdWx0cy5ub3RpZmljYXRpb247CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAidHJpZ2dlclRyYW5zaXRpb24iKSkgcmVzdWx0LnRhc2tSZXN1bHRzLnRyaWdnZXJUcmFuc2l0aW9uID0gZGF0YS50YXNrUmVzdWx0cy50cmlnZ2VyVHJhbnNpdGlvbjsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJnZXRJbnN0YW5jZXMiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmdldEluc3RhbmNlcyA9IGRhdGEudGFza1Jlc3VsdHMuZ2V0SW5zdGFuY2VzOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgInN1YnByb2Nlc3MiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLnN1YnByb2Nlc3MgPSBkYXRhLnRhc2tSZXN1bHRzLnN1YnByb2Nlc3M7CiAgICAgICAgfQoKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMuZGFwckJpbmRpbmcgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cy5kYXByQmluZGluZy5jb21wbGV0ZWQgPSB0cnVlOwogICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cy5kYXByQmluZGluZy5leGVjdXRlZEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCJEYXByQmluZGluZ01hcHBpbmcgY29tcGxldGVkIik7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-dapr-pubsub", + "target": "dapr-pubsub-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Dapr PubSub" + }, + { + "language": "tr-TR", + "label": "Dapr PubSub'a Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "dapr-pubsub-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Dapr PubSub Task" + }, + { + "language": "tr-TR", + "label": "Dapr PubSub Gorevi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "dapr-pubsub-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/DaprPubSubMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIERhcHJQdWJTdWJNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CgogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAidGVzdElkIikpIHJlc3VsdC50ZXN0SWQgPSBkYXRhLnRlc3RJZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImluaXRDb21wbGV0ZWQiKSkgcmVzdWx0LmluaXRDb21wbGV0ZWQgPSBkYXRhLmluaXRDb21wbGV0ZWQ7CgogICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cyA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0YXNrUmVzdWx0cyIpKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJkYXBySHR0cCIpKSByZXN1bHQudGFza1Jlc3VsdHMuZGFwckh0dHAgPSBkYXRhLnRhc2tSZXN1bHRzLmRhcHJIdHRwOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgImRhcHJTZXJ2aWNlIikpIHJlc3VsdC50YXNrUmVzdWx0cy5kYXByU2VydmljZSA9IGRhdGEudGFza1Jlc3VsdHMuZGFwclNlcnZpY2U7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZGFwckJpbmRpbmciKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJCaW5kaW5nID0gZGF0YS50YXNrUmVzdWx0cy5kYXByQmluZGluZzsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJub3RpZmljYXRpb24iKSkgcmVzdWx0LnRhc2tSZXN1bHRzLm5vdGlmaWNhdGlvbiA9IGRhdGEudGFza1Jlc3VsdHMubm90aWZpY2F0aW9uOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgInRyaWdnZXJUcmFuc2l0aW9uIikpIHJlc3VsdC50YXNrUmVzdWx0cy50cmlnZ2VyVHJhbnNpdGlvbiA9IGRhdGEudGFza1Jlc3VsdHMudHJpZ2dlclRyYW5zaXRpb247CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZ2V0SW5zdGFuY2VzIikpIHJlc3VsdC50YXNrUmVzdWx0cy5nZXRJbnN0YW5jZXMgPSBkYXRhLnRhc2tSZXN1bHRzLmdldEluc3RhbmNlczsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJzdWJwcm9jZXNzIikpIHJlc3VsdC50YXNrUmVzdWx0cy5zdWJwcm9jZXNzID0gZGF0YS50YXNrUmVzdWx0cy5zdWJwcm9jZXNzOwogICAgICAgIH0KCiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJQdWJTdWIgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cy5kYXByUHViU3ViLmNvbXBsZXRlZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJQdWJTdWIuZXhlY3V0ZWRBdCA9IERhdGVUaW1lLlV0Y05vdy5Ub1N0cmluZygibyIpOwoKICAgICAgICBMb2dJbmZvcm1hdGlvbigiRGFwclB1YlN1Yk1hcHBpbmcgY29tcGxldGVkIik7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-notification", + "target": "notification-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Notification" + }, + { + "language": "tr-TR", + "label": "Bildirime Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "notification-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Notification Task" + }, + { + "language": "tr-TR", + "label": "Bildirim Gorevi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "notification-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/NotificationMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIE5vdGlmaWNhdGlvbk1hcHBpbmcgOiBTY3JpcHRCYXNlLCBJTWFwcGluZwp7CiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFdvcmtmbG93VGFzayB0YXNrLCBTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UoKSk7CiAgICB9CgogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKCiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSkgcmVzdWx0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaW5pdENvbXBsZXRlZCIpKSByZXN1bHQuaW5pdENvbXBsZXRlZCA9IGRhdGEuaW5pdENvbXBsZXRlZDsKCiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRhc2tSZXN1bHRzIikpCiAgICAgICAgewogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgImRhcHJIdHRwIikpIHJlc3VsdC50YXNrUmVzdWx0cy5kYXBySHR0cCA9IGRhdGEudGFza1Jlc3VsdHMuZGFwckh0dHA7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZGFwclNlcnZpY2UiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJTZXJ2aWNlID0gZGF0YS50YXNrUmVzdWx0cy5kYXByU2VydmljZTsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJkYXByQmluZGluZyIpKSByZXN1bHQudGFza1Jlc3VsdHMuZGFwckJpbmRpbmcgPSBkYXRhLnRhc2tSZXN1bHRzLmRhcHJCaW5kaW5nOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgImRhcHJQdWJTdWIiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJQdWJTdWIgPSBkYXRhLnRhc2tSZXN1bHRzLmRhcHJQdWJTdWI7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAidHJpZ2dlclRyYW5zaXRpb24iKSkgcmVzdWx0LnRhc2tSZXN1bHRzLnRyaWdnZXJUcmFuc2l0aW9uID0gZGF0YS50YXNrUmVzdWx0cy50cmlnZ2VyVHJhbnNpdGlvbjsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJnZXRJbnN0YW5jZXMiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmdldEluc3RhbmNlcyA9IGRhdGEudGFza1Jlc3VsdHMuZ2V0SW5zdGFuY2VzOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgInN1YnByb2Nlc3MiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLnN1YnByb2Nlc3MgPSBkYXRhLnRhc2tSZXN1bHRzLnN1YnByb2Nlc3M7CiAgICAgICAgfQoKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMubm90aWZpY2F0aW9uID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMubm90aWZpY2F0aW9uLmNvbXBsZXRlZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzLm5vdGlmaWNhdGlvbi5leGVjdXRlZEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCJOb3RpZmljYXRpb25NYXBwaW5nIGNvbXBsZXRlZCIpOwogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-trigger-transition", + "target": "trigger-transition-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Trigger Transition" + }, + { + "language": "tr-TR", + "label": "Trigger Transition'a Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "trigger-transition-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Trigger Transition Task" + }, + { + "language": "tr-TR", + "label": "Gecis Tetikleme Gorevi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "trigger-transition-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/TriggerTransitionMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFRyaWdnZXJUcmFuc2l0aW9uTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKSByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJpbml0Q29tcGxldGVkIikpIHJlc3VsdC5pbml0Q29tcGxldGVkID0gZGF0YS5pbml0Q29tcGxldGVkOwoKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAidGFza1Jlc3VsdHMiKSkKICAgICAgICB7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZGFwckh0dHAiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJIdHRwID0gZGF0YS50YXNrUmVzdWx0cy5kYXBySHR0cDsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJkYXByU2VydmljZSIpKSByZXN1bHQudGFza1Jlc3VsdHMuZGFwclNlcnZpY2UgPSBkYXRhLnRhc2tSZXN1bHRzLmRhcHJTZXJ2aWNlOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgImRhcHJCaW5kaW5nIikpIHJlc3VsdC50YXNrUmVzdWx0cy5kYXByQmluZGluZyA9IGRhdGEudGFza1Jlc3VsdHMuZGFwckJpbmRpbmc7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZGFwclB1YlN1YiIpKSByZXN1bHQudGFza1Jlc3VsdHMuZGFwclB1YlN1YiA9IGRhdGEudGFza1Jlc3VsdHMuZGFwclB1YlN1YjsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJub3RpZmljYXRpb24iKSkgcmVzdWx0LnRhc2tSZXN1bHRzLm5vdGlmaWNhdGlvbiA9IGRhdGEudGFza1Jlc3VsdHMubm90aWZpY2F0aW9uOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgImdldEluc3RhbmNlcyIpKSByZXN1bHQudGFza1Jlc3VsdHMuZ2V0SW5zdGFuY2VzID0gZGF0YS50YXNrUmVzdWx0cy5nZXRJbnN0YW5jZXM7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAic3VicHJvY2VzcyIpKSByZXN1bHQudGFza1Jlc3VsdHMuc3VicHJvY2VzcyA9IGRhdGEudGFza1Jlc3VsdHMuc3VicHJvY2VzczsKICAgICAgICB9CgogICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cy50cmlnZ2VyVHJhbnNpdGlvbiA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzLnRyaWdnZXJUcmFuc2l0aW9uLmNvbXBsZXRlZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzLnRyaWdnZXJUcmFuc2l0aW9uLmV4ZWN1dGVkQXQgPSBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoIm8iKTsKCiAgICAgICAgTG9nSW5mb3JtYXRpb24oIlRyaWdnZXJUcmFuc2l0aW9uTWFwcGluZyBjb21wbGV0ZWQiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-subprocess", + "target": "subprocess-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to SubProcess" + }, + { + "language": "tr-TR", + "label": "SubProcess'e Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "subprocess-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "SubProcess Task" + }, + { + "language": "tr-TR", + "label": "Alt Surec Gorevi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "subprocess-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/SubProcessMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFN1YlByb2Nlc3NNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CgogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAidGVzdElkIikpIHJlc3VsdC50ZXN0SWQgPSBkYXRhLnRlc3RJZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImluaXRDb21wbGV0ZWQiKSkgcmVzdWx0LmluaXRDb21wbGV0ZWQgPSBkYXRhLmluaXRDb21wbGV0ZWQ7CgogICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cyA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0YXNrUmVzdWx0cyIpKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJkYXBySHR0cCIpKSByZXN1bHQudGFza1Jlc3VsdHMuZGFwckh0dHAgPSBkYXRhLnRhc2tSZXN1bHRzLmRhcHJIdHRwOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgImRhcHJTZXJ2aWNlIikpIHJlc3VsdC50YXNrUmVzdWx0cy5kYXByU2VydmljZSA9IGRhdGEudGFza1Jlc3VsdHMuZGFwclNlcnZpY2U7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZGFwckJpbmRpbmciKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJCaW5kaW5nID0gZGF0YS50YXNrUmVzdWx0cy5kYXByQmluZGluZzsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJkYXByUHViU3ViIikpIHJlc3VsdC50YXNrUmVzdWx0cy5kYXByUHViU3ViID0gZGF0YS50YXNrUmVzdWx0cy5kYXByUHViU3ViOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgIm5vdGlmaWNhdGlvbiIpKSByZXN1bHQudGFza1Jlc3VsdHMubm90aWZpY2F0aW9uID0gZGF0YS50YXNrUmVzdWx0cy5ub3RpZmljYXRpb247CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAidHJpZ2dlclRyYW5zaXRpb24iKSkgcmVzdWx0LnRhc2tSZXN1bHRzLnRyaWdnZXJUcmFuc2l0aW9uID0gZGF0YS50YXNrUmVzdWx0cy50cmlnZ2VyVHJhbnNpdGlvbjsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJnZXRJbnN0YW5jZXMiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmdldEluc3RhbmNlcyA9IGRhdGEudGFza1Jlc3VsdHMuZ2V0SW5zdGFuY2VzOwogICAgICAgIH0KCiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzLnN1YnByb2Nlc3MgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cy5zdWJwcm9jZXNzLmNvbXBsZXRlZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzLnN1YnByb2Nlc3MuZXhlY3V0ZWRBdCA9IERhdGVUaW1lLlV0Y05vdy5Ub1N0cmluZygibyIpOwoKICAgICAgICBMb2dJbmZvcm1hdGlvbigiU3ViUHJvY2Vzc01hcHBpbmcgY29tcGxldGVkIik7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-get-instances", + "target": "get-instances-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to GetInstances" + }, + { + "language": "tr-TR", + "label": "GetInstances'a Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "get-instances-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "GetInstances Task" + }, + { + "language": "tr-TR", + "label": "Instance Listesi Gorevi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "get-instances-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/GetInstancesMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIEdldEluc3RhbmNlc01hcHBpbmcgOiBTY3JpcHRCYXNlLCBJTWFwcGluZwp7CiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFdvcmtmbG93VGFzayB0YXNrLCBTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UoKSk7CiAgICB9CgogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKCiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSkgcmVzdWx0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaW5pdENvbXBsZXRlZCIpKSByZXN1bHQuaW5pdENvbXBsZXRlZCA9IGRhdGEuaW5pdENvbXBsZXRlZDsKCiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRhc2tSZXN1bHRzIikpCiAgICAgICAgewogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgImRhcHJIdHRwIikpIHJlc3VsdC50YXNrUmVzdWx0cy5kYXBySHR0cCA9IGRhdGEudGFza1Jlc3VsdHMuZGFwckh0dHA7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZGFwclNlcnZpY2UiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJTZXJ2aWNlID0gZGF0YS50YXNrUmVzdWx0cy5kYXByU2VydmljZTsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJkYXByQmluZGluZyIpKSByZXN1bHQudGFza1Jlc3VsdHMuZGFwckJpbmRpbmcgPSBkYXRhLnRhc2tSZXN1bHRzLmRhcHJCaW5kaW5nOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgImRhcHJQdWJTdWIiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJQdWJTdWIgPSBkYXRhLnRhc2tSZXN1bHRzLmRhcHJQdWJTdWI7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAibm90aWZpY2F0aW9uIikpIHJlc3VsdC50YXNrUmVzdWx0cy5ub3RpZmljYXRpb24gPSBkYXRhLnRhc2tSZXN1bHRzLm5vdGlmaWNhdGlvbjsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJ0cmlnZ2VyVHJhbnNpdGlvbiIpKSByZXN1bHQudGFza1Jlc3VsdHMudHJpZ2dlclRyYW5zaXRpb24gPSBkYXRhLnRhc2tSZXN1bHRzLnRyaWdnZXJUcmFuc2l0aW9uOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgInN1YnByb2Nlc3MiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLnN1YnByb2Nlc3MgPSBkYXRhLnRhc2tSZXN1bHRzLnN1YnByb2Nlc3M7CiAgICAgICAgfQoKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMuZ2V0SW5zdGFuY2VzID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMuZ2V0SW5zdGFuY2VzLmNvbXBsZXRlZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzLmdldEluc3RhbmNlcy5leGVjdXRlZEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIHZhciB0YXNrUmVzcG9uc2UgPSBjb250ZXh0LkJvZHk7CiAgICAgICAgaWYgKHRhc2tSZXNwb25zZSAhPSBudWxsICYmIEhhc1Byb3BlcnR5KHRhc2tSZXNwb25zZSwgImRhdGEiKSkKICAgICAgICB7CiAgICAgICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cy5nZXRJbnN0YW5jZXMucmVzcG9uc2VSZWNlaXZlZCA9IHRydWU7CiAgICAgICAgfQoKICAgICAgICBMb2dJbmZvcm1hdGlvbigiR2V0SW5zdGFuY2VzTWFwcGluZyBjb21wbGV0ZWQiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-human-task", + "target": "human-task-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Human Task" + }, + { + "language": "tr-TR", + "label": "Insan Gorevine Otomatik" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "human-task-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Human Task (Approval)" + }, + { + "language": "tr-TR", + "label": "Insan Gorevi (Onay)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "human-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/HumanTaskMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIEh1bWFuVGFza01hcHBpbmcgOiBTY3JpcHRCYXNlLCBJTWFwcGluZwp7CiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFdvcmtmbG93VGFzayB0YXNrLCBTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UoKSk7CiAgICB9CgogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKCiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSkgcmVzdWx0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaW5pdENvbXBsZXRlZCIpKSByZXN1bHQuaW5pdENvbXBsZXRlZCA9IGRhdGEuaW5pdENvbXBsZXRlZDsKCiAgICAgICAgcmVzdWx0LnRhc2tSZXN1bHRzID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRhc2tSZXN1bHRzIikpCiAgICAgICAgewogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgImRhcHJIdHRwIikpIHJlc3VsdC50YXNrUmVzdWx0cy5kYXBySHR0cCA9IGRhdGEudGFza1Jlc3VsdHMuZGFwckh0dHA7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAiZGFwclNlcnZpY2UiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJTZXJ2aWNlID0gZGF0YS50YXNrUmVzdWx0cy5kYXByU2VydmljZTsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJkYXByQmluZGluZyIpKSByZXN1bHQudGFza1Jlc3VsdHMuZGFwckJpbmRpbmcgPSBkYXRhLnRhc2tSZXN1bHRzLmRhcHJCaW5kaW5nOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgImRhcHJQdWJTdWIiKSkgcmVzdWx0LnRhc2tSZXN1bHRzLmRhcHJQdWJTdWIgPSBkYXRhLnRhc2tSZXN1bHRzLmRhcHJQdWJTdWI7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAibm90aWZpY2F0aW9uIikpIHJlc3VsdC50YXNrUmVzdWx0cy5ub3RpZmljYXRpb24gPSBkYXRhLnRhc2tSZXN1bHRzLm5vdGlmaWNhdGlvbjsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEudGFza1Jlc3VsdHMsICJ0cmlnZ2VyVHJhbnNpdGlvbiIpKSByZXN1bHQudGFza1Jlc3VsdHMudHJpZ2dlclRyYW5zaXRpb24gPSBkYXRhLnRhc2tSZXN1bHRzLnRyaWdnZXJUcmFuc2l0aW9uOwogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YS50YXNrUmVzdWx0cywgImdldEluc3RhbmNlcyIpKSByZXN1bHQudGFza1Jlc3VsdHMuZ2V0SW5zdGFuY2VzID0gZGF0YS50YXNrUmVzdWx0cy5nZXRJbnN0YW5jZXM7CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLnRhc2tSZXN1bHRzLCAic3VicHJvY2VzcyIpKSByZXN1bHQudGFza1Jlc3VsdHMuc3VicHJvY2VzcyA9IGRhdGEudGFza1Jlc3VsdHMuc3VicHJvY2VzczsKICAgICAgICB9CgogICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cy5odW1hblRhc2sgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHJlc3VsdC50YXNrUmVzdWx0cy5odW1hblRhc2suY29tcGxldGVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQudGFza1Jlc3VsdHMuaHVtYW5UYXNrLmFwcHJvdmVkQXQgPSBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoIm8iKTsKCiAgICAgICAgTG9nSW5mb3JtYXRpb24oIkh1bWFuVGFza01hcHBpbmcgY29tcGxldGVkIik7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "approve-human-task", + "target": "completed-state", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Approve Human Task" + }, + { + "language": "tr-TR", + "label": "Insan Gorevini Onayla" + } + ], + "onExecutionTasks": [] + } + ] + }, + { + "key": "completed-state", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Completed" + }, + { + "language": "tr-TR", + "label": "Tamamlandi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/extended-tasks/src/AlwaysTrueRule.csx b/core/Workflows/extended-tasks/src/AlwaysTrueRule.csx new file mode 100644 index 0000000..3d08a0f --- /dev/null +++ b/core/Workflows/extended-tasks/src/AlwaysTrueRule.csx @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class AlwaysTrueRule : ScriptBase, IConditionMapping +{ + public Task Handler(ScriptContext context) + { + LogInformation("AlwaysTrueRule: returning true"); + return Task.FromResult(true); + } +} diff --git a/core/Workflows/extended-tasks/src/DaprBindingMapping.csx b/core/Workflows/extended-tasks/src/DaprBindingMapping.csx new file mode 100644 index 0000000..f8004bb --- /dev/null +++ b/core/Workflows/extended-tasks/src/DaprBindingMapping.csx @@ -0,0 +1,40 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class DaprBindingMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "initCompleted")) result.initCompleted = data.initCompleted; + + result.taskResults = new ExpandoObject(); + if (HasProperty(data, "taskResults")) + { + if (HasProperty(data.taskResults, "daprHttp")) result.taskResults.daprHttp = data.taskResults.daprHttp; + if (HasProperty(data.taskResults, "daprService")) result.taskResults.daprService = data.taskResults.daprService; + if (HasProperty(data.taskResults, "notification")) result.taskResults.notification = data.taskResults.notification; + if (HasProperty(data.taskResults, "triggerTransition")) result.taskResults.triggerTransition = data.taskResults.triggerTransition; + if (HasProperty(data.taskResults, "getInstances")) result.taskResults.getInstances = data.taskResults.getInstances; + if (HasProperty(data.taskResults, "subprocess")) result.taskResults.subprocess = data.taskResults.subprocess; + } + + result.taskResults.daprBinding = new ExpandoObject(); + result.taskResults.daprBinding.completed = true; + result.taskResults.daprBinding.executedAt = DateTime.UtcNow.ToString("o"); + + LogInformation("DaprBindingMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/extended-tasks/src/DaprHttpMapping.csx b/core/Workflows/extended-tasks/src/DaprHttpMapping.csx new file mode 100644 index 0000000..168b69c --- /dev/null +++ b/core/Workflows/extended-tasks/src/DaprHttpMapping.csx @@ -0,0 +1,47 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class DaprHttpMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "initCompleted")) result.initCompleted = data.initCompleted; + + result.taskResults = new ExpandoObject(); + if (HasProperty(data, "taskResults")) + { + if (HasProperty(data.taskResults, "daprService")) result.taskResults.daprService = data.taskResults.daprService; + if (HasProperty(data.taskResults, "notification")) result.taskResults.notification = data.taskResults.notification; + if (HasProperty(data.taskResults, "triggerTransition")) result.taskResults.triggerTransition = data.taskResults.triggerTransition; + if (HasProperty(data.taskResults, "getInstances")) result.taskResults.getInstances = data.taskResults.getInstances; + if (HasProperty(data.taskResults, "subprocess")) result.taskResults.subprocess = data.taskResults.subprocess; + } + + result.taskResults.daprHttp = new ExpandoObject(); + result.taskResults.daprHttp.completed = true; + result.taskResults.daprHttp.executedAt = DateTime.UtcNow.ToString("o"); + + var taskResponse = context.Body; + if (taskResponse != null && HasProperty(taskResponse, "data")) + { + var responseData = taskResponse.data; + if (responseData != null && HasProperty(responseData, "processId")) + result.taskResults.daprHttp.processId = responseData.processId; + } + + LogInformation("DaprHttpMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/extended-tasks/src/DaprPubSubMapping.csx b/core/Workflows/extended-tasks/src/DaprPubSubMapping.csx new file mode 100644 index 0000000..f88eaa3 --- /dev/null +++ b/core/Workflows/extended-tasks/src/DaprPubSubMapping.csx @@ -0,0 +1,41 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class DaprPubSubMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "initCompleted")) result.initCompleted = data.initCompleted; + + result.taskResults = new ExpandoObject(); + if (HasProperty(data, "taskResults")) + { + if (HasProperty(data.taskResults, "daprHttp")) result.taskResults.daprHttp = data.taskResults.daprHttp; + if (HasProperty(data.taskResults, "daprService")) result.taskResults.daprService = data.taskResults.daprService; + if (HasProperty(data.taskResults, "daprBinding")) result.taskResults.daprBinding = data.taskResults.daprBinding; + if (HasProperty(data.taskResults, "notification")) result.taskResults.notification = data.taskResults.notification; + if (HasProperty(data.taskResults, "triggerTransition")) result.taskResults.triggerTransition = data.taskResults.triggerTransition; + if (HasProperty(data.taskResults, "getInstances")) result.taskResults.getInstances = data.taskResults.getInstances; + if (HasProperty(data.taskResults, "subprocess")) result.taskResults.subprocess = data.taskResults.subprocess; + } + + result.taskResults.daprPubSub = new ExpandoObject(); + result.taskResults.daprPubSub.completed = true; + result.taskResults.daprPubSub.executedAt = DateTime.UtcNow.ToString("o"); + + LogInformation("DaprPubSubMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/extended-tasks/src/DaprServiceMapping.csx b/core/Workflows/extended-tasks/src/DaprServiceMapping.csx new file mode 100644 index 0000000..fbfeb77 --- /dev/null +++ b/core/Workflows/extended-tasks/src/DaprServiceMapping.csx @@ -0,0 +1,47 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class DaprServiceMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "initCompleted")) result.initCompleted = data.initCompleted; + + result.taskResults = new ExpandoObject(); + if (HasProperty(data, "taskResults")) + { + if (HasProperty(data.taskResults, "daprHttp")) result.taskResults.daprHttp = data.taskResults.daprHttp; + if (HasProperty(data.taskResults, "notification")) result.taskResults.notification = data.taskResults.notification; + if (HasProperty(data.taskResults, "triggerTransition")) result.taskResults.triggerTransition = data.taskResults.triggerTransition; + if (HasProperty(data.taskResults, "getInstances")) result.taskResults.getInstances = data.taskResults.getInstances; + if (HasProperty(data.taskResults, "subprocess")) result.taskResults.subprocess = data.taskResults.subprocess; + } + + result.taskResults.daprService = new ExpandoObject(); + result.taskResults.daprService.completed = true; + result.taskResults.daprService.executedAt = DateTime.UtcNow.ToString("o"); + + var taskResponse = context.Body; + if (taskResponse != null && HasProperty(taskResponse, "data")) + { + var responseData = taskResponse.data; + if (responseData != null && HasProperty(responseData, "processId")) + result.taskResults.daprService.processId = responseData.processId; + } + + LogInformation("DaprServiceMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/extended-tasks/src/GetInstancesMapping.csx b/core/Workflows/extended-tasks/src/GetInstancesMapping.csx new file mode 100644 index 0000000..0baead0 --- /dev/null +++ b/core/Workflows/extended-tasks/src/GetInstancesMapping.csx @@ -0,0 +1,47 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class GetInstancesMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "initCompleted")) result.initCompleted = data.initCompleted; + + result.taskResults = new ExpandoObject(); + if (HasProperty(data, "taskResults")) + { + if (HasProperty(data.taskResults, "daprHttp")) result.taskResults.daprHttp = data.taskResults.daprHttp; + if (HasProperty(data.taskResults, "daprService")) result.taskResults.daprService = data.taskResults.daprService; + if (HasProperty(data.taskResults, "daprBinding")) result.taskResults.daprBinding = data.taskResults.daprBinding; + if (HasProperty(data.taskResults, "daprPubSub")) result.taskResults.daprPubSub = data.taskResults.daprPubSub; + if (HasProperty(data.taskResults, "notification")) result.taskResults.notification = data.taskResults.notification; + if (HasProperty(data.taskResults, "triggerTransition")) result.taskResults.triggerTransition = data.taskResults.triggerTransition; + if (HasProperty(data.taskResults, "subprocess")) result.taskResults.subprocess = data.taskResults.subprocess; + } + + result.taskResults.getInstances = new ExpandoObject(); + result.taskResults.getInstances.completed = true; + result.taskResults.getInstances.executedAt = DateTime.UtcNow.ToString("o"); + + var taskResponse = context.Body; + if (taskResponse != null && HasProperty(taskResponse, "data")) + { + result.taskResults.getInstances.responseReceived = true; + } + + LogInformation("GetInstancesMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/extended-tasks/src/HumanTaskMapping.csx b/core/Workflows/extended-tasks/src/HumanTaskMapping.csx new file mode 100644 index 0000000..9f8a94e --- /dev/null +++ b/core/Workflows/extended-tasks/src/HumanTaskMapping.csx @@ -0,0 +1,42 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class HumanTaskMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "initCompleted")) result.initCompleted = data.initCompleted; + + result.taskResults = new ExpandoObject(); + if (HasProperty(data, "taskResults")) + { + if (HasProperty(data.taskResults, "daprHttp")) result.taskResults.daprHttp = data.taskResults.daprHttp; + if (HasProperty(data.taskResults, "daprService")) result.taskResults.daprService = data.taskResults.daprService; + if (HasProperty(data.taskResults, "daprBinding")) result.taskResults.daprBinding = data.taskResults.daprBinding; + if (HasProperty(data.taskResults, "daprPubSub")) result.taskResults.daprPubSub = data.taskResults.daprPubSub; + if (HasProperty(data.taskResults, "notification")) result.taskResults.notification = data.taskResults.notification; + if (HasProperty(data.taskResults, "triggerTransition")) result.taskResults.triggerTransition = data.taskResults.triggerTransition; + if (HasProperty(data.taskResults, "getInstances")) result.taskResults.getInstances = data.taskResults.getInstances; + if (HasProperty(data.taskResults, "subprocess")) result.taskResults.subprocess = data.taskResults.subprocess; + } + + result.taskResults.humanTask = new ExpandoObject(); + result.taskResults.humanTask.completed = true; + result.taskResults.humanTask.approvedAt = DateTime.UtcNow.ToString("o"); + + LogInformation("HumanTaskMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/extended-tasks/src/InitExtendedTaskMapping.csx b/core/Workflows/extended-tasks/src/InitExtendedTaskMapping.csx new file mode 100644 index 0000000..faee081 --- /dev/null +++ b/core/Workflows/extended-tasks/src/InitExtendedTaskMapping.csx @@ -0,0 +1,29 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class InitExtendedTaskMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) + result.testId = data.testId; + + result.initCompleted = true; + result.initAt = DateTime.UtcNow.ToString("o"); + result.taskResults = new ExpandoObject(); + + LogInformation("InitExtendedTaskMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/extended-tasks/src/NotificationMapping.csx b/core/Workflows/extended-tasks/src/NotificationMapping.csx new file mode 100644 index 0000000..2e6a6d7 --- /dev/null +++ b/core/Workflows/extended-tasks/src/NotificationMapping.csx @@ -0,0 +1,41 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class NotificationMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "initCompleted")) result.initCompleted = data.initCompleted; + + result.taskResults = new ExpandoObject(); + if (HasProperty(data, "taskResults")) + { + if (HasProperty(data.taskResults, "daprHttp")) result.taskResults.daprHttp = data.taskResults.daprHttp; + if (HasProperty(data.taskResults, "daprService")) result.taskResults.daprService = data.taskResults.daprService; + if (HasProperty(data.taskResults, "daprBinding")) result.taskResults.daprBinding = data.taskResults.daprBinding; + if (HasProperty(data.taskResults, "daprPubSub")) result.taskResults.daprPubSub = data.taskResults.daprPubSub; + if (HasProperty(data.taskResults, "triggerTransition")) result.taskResults.triggerTransition = data.taskResults.triggerTransition; + if (HasProperty(data.taskResults, "getInstances")) result.taskResults.getInstances = data.taskResults.getInstances; + if (HasProperty(data.taskResults, "subprocess")) result.taskResults.subprocess = data.taskResults.subprocess; + } + + result.taskResults.notification = new ExpandoObject(); + result.taskResults.notification.completed = true; + result.taskResults.notification.executedAt = DateTime.UtcNow.ToString("o"); + + LogInformation("NotificationMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/extended-tasks/src/SubProcessMapping.csx b/core/Workflows/extended-tasks/src/SubProcessMapping.csx new file mode 100644 index 0000000..66821ef --- /dev/null +++ b/core/Workflows/extended-tasks/src/SubProcessMapping.csx @@ -0,0 +1,41 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class SubProcessMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "initCompleted")) result.initCompleted = data.initCompleted; + + result.taskResults = new ExpandoObject(); + if (HasProperty(data, "taskResults")) + { + if (HasProperty(data.taskResults, "daprHttp")) result.taskResults.daprHttp = data.taskResults.daprHttp; + if (HasProperty(data.taskResults, "daprService")) result.taskResults.daprService = data.taskResults.daprService; + if (HasProperty(data.taskResults, "daprBinding")) result.taskResults.daprBinding = data.taskResults.daprBinding; + if (HasProperty(data.taskResults, "daprPubSub")) result.taskResults.daprPubSub = data.taskResults.daprPubSub; + if (HasProperty(data.taskResults, "notification")) result.taskResults.notification = data.taskResults.notification; + if (HasProperty(data.taskResults, "triggerTransition")) result.taskResults.triggerTransition = data.taskResults.triggerTransition; + if (HasProperty(data.taskResults, "getInstances")) result.taskResults.getInstances = data.taskResults.getInstances; + } + + result.taskResults.subprocess = new ExpandoObject(); + result.taskResults.subprocess.completed = true; + result.taskResults.subprocess.executedAt = DateTime.UtcNow.ToString("o"); + + LogInformation("SubProcessMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/extended-tasks/src/TriggerTransitionMapping.csx b/core/Workflows/extended-tasks/src/TriggerTransitionMapping.csx new file mode 100644 index 0000000..01da003 --- /dev/null +++ b/core/Workflows/extended-tasks/src/TriggerTransitionMapping.csx @@ -0,0 +1,41 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class TriggerTransitionMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "initCompleted")) result.initCompleted = data.initCompleted; + + result.taskResults = new ExpandoObject(); + if (HasProperty(data, "taskResults")) + { + if (HasProperty(data.taskResults, "daprHttp")) result.taskResults.daprHttp = data.taskResults.daprHttp; + if (HasProperty(data.taskResults, "daprService")) result.taskResults.daprService = data.taskResults.daprService; + if (HasProperty(data.taskResults, "daprBinding")) result.taskResults.daprBinding = data.taskResults.daprBinding; + if (HasProperty(data.taskResults, "daprPubSub")) result.taskResults.daprPubSub = data.taskResults.daprPubSub; + if (HasProperty(data.taskResults, "notification")) result.taskResults.notification = data.taskResults.notification; + if (HasProperty(data.taskResults, "getInstances")) result.taskResults.getInstances = data.taskResults.getInstances; + if (HasProperty(data.taskResults, "subprocess")) result.taskResults.subprocess = data.taskResults.subprocess; + } + + result.taskResults.triggerTransition = new ExpandoObject(); + result.taskResults.triggerTransition.completed = true; + result.taskResults.triggerTransition.executedAt = DateTime.UtcNow.ToString("o"); + + LogInformation("TriggerTransitionMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/flow-types/core-flow-test.json b/core/Workflows/flow-types/core-flow-test.json new file mode 100644 index 0000000..879d9e8 --- /dev/null +++ b/core/Workflows/flow-types/core-flow-test.json @@ -0,0 +1,142 @@ +{ + "key": "core-flow-test", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "flow-types", + "core" + ], + "attributes": { + "type": "C", + "timeout": null, + "errorBoundary": null, + "labels": [ + { + "language": "en-US", + "label": "Core Flow Type Integration Test" + }, + { + "language": "tr-TR", + "label": "Cekirdek Akis Tipi Entegrasyon Testi" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [], + "startTransition": { + "key": "start-core-flow-test", + "target": "core-init-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Core Flow Test" + }, + { + "language": "tr-TR", + "label": "Cekirdek Akis Testini Baslat" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "flow-types-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/CoreInitMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIENvcmVJbml0TWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHJlc3VsdC5mbG93VHlwZSA9ICJDIjsKICAgICAgICByZXN1bHQuY29yZUluaXRpYWxpemVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQuaW5pdEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCJDb3JlSW5pdE1hcHBpbmcgY29tcGxldGVkIC0gQ29yZSBmbG93IHR5cGUgdGVzdCIpOwoKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ] + }, + "states": [ + { + "key": "core-init-state", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Core Init State" + }, + { + "language": "tr-TR", + "label": "Cekirdek Baslangic Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "flow-types-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/CoreInitMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIENvcmVJbml0TWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHJlc3VsdC5mbG93VHlwZSA9ICJDIjsKICAgICAgICByZXN1bHQuY29yZUluaXRpYWxpemVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQuaW5pdEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCJDb3JlSW5pdE1hcHBpbmcgY29tcGxldGVkIC0gQ29yZSBmbG93IHR5cGUgdGVzdCIpOwoKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-core-to-complete", + "target": "core-completed", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Core Completed" + }, + { + "language": "tr-TR", + "label": "Cekirdek Tamamlanmaya Otomatik Gecis" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KfQo=" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "core-completed", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Core Completed (Final)" + }, + { + "language": "tr-TR", + "label": "Cekirdek Tamamlandi (Final)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/flow-types/src/AlwaysTrueRule.csx b/core/Workflows/flow-types/src/AlwaysTrueRule.csx new file mode 100644 index 0000000..37de1d3 --- /dev/null +++ b/core/Workflows/flow-types/src/AlwaysTrueRule.csx @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class AlwaysTrueRule : ScriptBase, IConditionMapping +{ + public async Task Handler(ScriptContext context) + { + LogInformation("AlwaysTrueRule: returning true"); + return true; + } +} diff --git a/core/Workflows/flow-types/src/CoreInitMapping.csx b/core/Workflows/flow-types/src/CoreInitMapping.csx new file mode 100644 index 0000000..e7eb3ad --- /dev/null +++ b/core/Workflows/flow-types/src/CoreInitMapping.csx @@ -0,0 +1,25 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class CoreInitMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + dynamic result = new ExpandoObject(); + result.flowType = "C"; + result.coreInitialized = true; + result.initAt = DateTime.UtcNow.ToString("o"); + + LogInformation("CoreInitMapping completed - Core flow type test"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/flow-types/src/SubProcessInitMapping.csx b/core/Workflows/flow-types/src/SubProcessInitMapping.csx new file mode 100644 index 0000000..593eaf4 --- /dev/null +++ b/core/Workflows/flow-types/src/SubProcessInitMapping.csx @@ -0,0 +1,25 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class SubProcessInitMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + dynamic result = new ExpandoObject(); + result.flowType = "P"; + result.subProcessInitialized = true; + result.initAt = DateTime.UtcNow.ToString("o"); + + LogInformation("SubProcessInitMapping completed - SubProcess flow type test"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/flow-types/subprocess-flow-test.json b/core/Workflows/flow-types/subprocess-flow-test.json new file mode 100644 index 0000000..0302194 --- /dev/null +++ b/core/Workflows/flow-types/subprocess-flow-test.json @@ -0,0 +1,142 @@ +{ + "key": "subprocess-flow-test", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "flow-types", + "subprocess" + ], + "attributes": { + "type": "P", + "timeout": null, + "errorBoundary": null, + "labels": [ + { + "language": "en-US", + "label": "SubProcess Flow Type Integration Test" + }, + { + "language": "tr-TR", + "label": "Alt Surec Akis Tipi Entegrasyon Testi" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [], + "startTransition": { + "key": "start-subprocess-flow-test", + "target": "subprocess-init-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start SubProcess Flow Test" + }, + { + "language": "tr-TR", + "label": "Alt Surec Akis Testini Baslat" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "flow-types-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/SubProcessInitMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFN1YlByb2Nlc3NJbml0TWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHJlc3VsdC5mbG93VHlwZSA9ICJQIjsKICAgICAgICByZXN1bHQuc3ViUHJvY2Vzc0luaXRpYWxpemVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQuaW5pdEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCJTdWJQcm9jZXNzSW5pdE1hcHBpbmcgY29tcGxldGVkIC0gU3ViUHJvY2VzcyBmbG93IHR5cGUgdGVzdCIpOwoKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ] + }, + "states": [ + { + "key": "subprocess-init-state", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "SubProcess Init State" + }, + { + "language": "tr-TR", + "label": "Alt Surec Baslangic Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "flow-types-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/SubProcessInitMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFN1YlByb2Nlc3NJbml0TWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHJlc3VsdC5mbG93VHlwZSA9ICJQIjsKICAgICAgICByZXN1bHQuc3ViUHJvY2Vzc0luaXRpYWxpemVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQuaW5pdEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCJTdWJQcm9jZXNzSW5pdE1hcHBpbmcgY29tcGxldGVkIC0gU3ViUHJvY2VzcyBmbG93IHR5cGUgdGVzdCIpOwoKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-subprocess-to-complete", + "target": "subprocess-completed", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to SubProcess Completed" + }, + { + "language": "tr-TR", + "label": "Alt Surec Tamamlanmaya Otomatik Gecis" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KfQo=" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "subprocess-completed", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "SubProcess Completed (Final)" + }, + { + "language": "tr-TR", + "label": "Alt Surec Tamamlandi (Final)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/instance-management/instance-management-test-workflow.json b/core/Workflows/instance-management/instance-management-test-workflow.json new file mode 100644 index 0000000..034ae12 --- /dev/null +++ b/core/Workflows/instance-management/instance-management-test-workflow.json @@ -0,0 +1,389 @@ +{ + "key": "instance-management-test-workflow", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "instance-management", + "filtering", + "pagination", + "sorting", + "timeout", + "idempotent-start", + "effective-state", + "subtype-suspended", + "subtype-busy", + "subtype-human" + ], + "attributes": { + "type": "F", + "timeout": { + "key": "workflow-timeout", + "target": "timeout-state", + "versionStrategy": "Major", + "timer": { + "reset": "false", + "duration": "PT120S" + } + }, + "labels": [ + { + "language": "en-US", + "label": "Instance Management Integration Test" + }, + { + "language": "tr-TR", + "label": "Ornek Yonetimi Entegrasyon Testi" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [], + "startTransition": { + "key": "start-instance-management-test", + "target": "active-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Instance Management Test" + }, + { + "language": "tr-TR", + "label": "Ornek Yonetimi Testini Baslat" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "instance-mgmt-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/InitInstanceMgmtMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIEluaXRJbnN0YW5jZU1nbXRNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKCiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICByZXN1bHQuY2F0ZWdvcnkgPSBIYXNQcm9wZXJ0eShkYXRhLCAiY2F0ZWdvcnkiKSA/IChzdHJpbmcpZGF0YS5jYXRlZ29yeSA6ICJkZWZhdWx0IjsKICAgICAgICByZXN1bHQucHJpb3JpdHkgPSBIYXNQcm9wZXJ0eShkYXRhLCAicHJpb3JpdHkiKSA/IENvbnZlcnQuVG9JbnQzMihkYXRhLnByaW9yaXR5KSA6IDE7CiAgICAgICAgcmVzdWx0LnRlc3RTdGFydGVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQuc3RhcnRlZEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCQiSW5pdEluc3RhbmNlTWdtdE1hcHBpbmc6IGNhdGVnb3J5PXtyZXN1bHQuY2F0ZWdvcnl9LCBwcmlvcml0eT17cmVzdWx0LnByaW9yaXR5fSIpOwogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ] + }, + "states": [ + { + "key": "active-state", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Active State" + }, + { + "language": "tr-TR", + "label": "Aktif Durum" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "process", + "target": "processing-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Process" + }, + { + "language": "tr-TR", + "label": "Isle" + } + ], + "schema": null, + "view": null, + "mapping": null, + "onExecutionTasks": [] + }, + { + "key": "fast-complete", + "target": "completed-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Fast Complete" + }, + { + "language": "tr-TR", + "label": "Hizli Tamamla" + } + ], + "schema": null, + "view": null, + "mapping": null, + "onExecutionTasks": [] + } + ] + }, + { + "key": "processing-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Processing State" + }, + { + "language": "tr-TR", + "label": "Isleniyor Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "finish", + "target": "completed-state", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Finish" + }, + { + "language": "tr-TR", + "label": "Bitir" + } + ], + "schema": null, + "view": null, + "mapping": null, + "onExecutionTasks": [] + }, + { + "key": "reject", + "target": "rejected-state", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Reject" + }, + { + "language": "tr-TR", + "label": "Reddet" + } + ], + "schema": null, + "view": null, + "mapping": null, + "onExecutionTasks": [] + }, + { + "key": "suspend", + "target": "suspended-state", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Suspend" + }, + { + "language": "tr-TR", + "label": "Askiya Al" + } + ], + "schema": null, + "view": null, + "mapping": null, + "onExecutionTasks": [] + }, + { + "key": "set-busy", + "target": "busy-state", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Set Busy" + }, + { + "language": "tr-TR", + "label": "Mesgul Yap" + } + ], + "schema": null, + "view": null, + "mapping": null, + "onExecutionTasks": [] + }, + { + "key": "assign-human", + "target": "human-state", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Assign Human" + }, + { + "language": "tr-TR", + "label": "Insan Ata" + } + ], + "schema": null, + "view": null, + "mapping": null, + "onExecutionTasks": [] + } + ] + }, + { + "key": "completed-state", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Completed State" + }, + { + "language": "tr-TR", + "label": "Tamamlandi Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + }, + { + "key": "rejected-state", + "stateType": 3, + "subType": 2, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Rejected State" + }, + { + "language": "tr-TR", + "label": "Reddedildi Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + }, + { + "key": "timeout-state", + "stateType": 3, + "subType": 3, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Timeout State" + }, + { + "language": "tr-TR", + "label": "Zaman Asimi Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + }, + { + "key": "suspended-state", + "stateType": 3, + "subType": 4, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Suspended State" + }, + { + "language": "tr-TR", + "label": "Askiya Alinmis Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + }, + { + "key": "busy-state", + "stateType": 3, + "subType": 5, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Busy State" + }, + { + "language": "tr-TR", + "label": "Mesgul Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + }, + { + "key": "human-state", + "stateType": 3, + "subType": 6, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Human State" + }, + { + "language": "tr-TR", + "label": "Insan Mudahalesi Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/instance-management/src/InitInstanceMgmtMapping.csx b/core/Workflows/instance-management/src/InitInstanceMgmtMapping.csx new file mode 100644 index 0000000..ef699c1 --- /dev/null +++ b/core/Workflows/instance-management/src/InitInstanceMgmtMapping.csx @@ -0,0 +1,28 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class InitInstanceMgmtMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + + dynamic result = new ExpandoObject(); + + result.category = HasProperty(data, "category") ? (string)data.category : "default"; + result.priority = HasProperty(data, "priority") ? Convert.ToInt32(data.priority) : 1; + result.testStarted = true; + result.startedAt = DateTime.UtcNow.ToString("o"); + + LogInformation($"InitInstanceMgmtMapping: category={result.category}, priority={result.priority}"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/lifecycle-transitions/lifecycle-transitions-test-workflow.json b/core/Workflows/lifecycle-transitions/lifecycle-transitions-test-workflow.json new file mode 100644 index 0000000..a965092 --- /dev/null +++ b/core/Workflows/lifecycle-transitions/lifecycle-transitions-test-workflow.json @@ -0,0 +1,604 @@ +{ + "key": "lifecycle-transitions-test-workflow", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "lifecycle", + "state-types", + "state-subtypes", + "manual-transition", + "auto-transition", + "complementary-rules", + "default-auto-transition", + "scheduled-transition", + "on-entries", + "on-exits", + "transition-mapping", + "script-task", + "timer-mapping", + "condition-mapping", + "version-strategy", + "idempotent-start", + "exit-transition", + "schedule-cancel", + "schedule-reschedule", + "query-roles", + "transition-roles" + ], + "attributes": { + "type": "F", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "Lifecycle & Transitions Integration Test" + }, + { + "language": "tr-TR", + "label": "Yasam Dongusu ve Gecis Entegrasyon Testi" + } + ], + "functions": [], + "features": [], + "extensions": [], + "queryRoles": [ + { + "role": "test-viewer", + "grant": "allow" + } + ], + "sharedTransitions": [], + "cancel": { + "key": "cancel-workflow", + "target": "terminated-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Cancel Workflow" + }, + { + "language": "tr-TR", + "label": "Is Akisini Iptal Et" + } + ] + }, + "exit": { + "key": "exit-workflow", + "target": "terminated-state", + "triggerType": 0, + "versionStrategy": "Major", + "availableIn": [ + "initialize-state", + "processing-state", + "pre-complete-state" + ], + "labels": [ + { + "language": "en-US", + "label": "Exit Workflow" + }, + { + "language": "tr-TR", + "label": "Is Akisindan Cik" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "script-task", + "version": "1.0.0", + "domain": "core", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ExitMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIEV4aXRNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CgogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAidGVzdElkIikpCiAgICAgICAgICAgIHJlc3VsdC50ZXN0SWQgPSBkYXRhLnRlc3RJZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImluaXRpYWxpemVDb21wbGV0ZWQiKSkKICAgICAgICAgICAgcmVzdWx0LmluaXRpYWxpemVDb21wbGV0ZWQgPSBkYXRhLmluaXRpYWxpemVDb21wbGV0ZWQ7CgogICAgICAgIHJlc3VsdC5leGl0RXhlY3V0ZWQgPSB0cnVlOwogICAgICAgIHJlc3VsdC5leGl0QXQgPSBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoIm8iKTsKCiAgICAgICAgTG9nSW5mb3JtYXRpb24oIkV4aXRNYXBwaW5nIGNvbXBsZXRlZCAtIHdvcmtmbG93IGV4aXRlZCB2aWEgZXhpdCB0cmFuc2l0aW9uIik7CgogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ] + }, + "startTransition": { + "key": "start-lifecycle-test", + "target": "initialize-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Lifecycle Test" + }, + { + "language": "tr-TR", + "label": "Yasam Dongusu Testini Baslat" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/InitializeDataMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIEluaXRpYWxpemVEYXRhTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CgogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKCiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0UGF0aCIpKQogICAgICAgICAgICByZXN1bHQudGVzdFBhdGggPSBkYXRhLnRlc3RQYXRoOwogICAgICAgIGVsc2UKICAgICAgICAgICAgcmVzdWx0LnRlc3RQYXRoID0gInBhc3MiOwoKICAgICAgICByZXN1bHQuaW5pdGlhbGl6ZWQgPSB0cnVlOwogICAgICAgIHJlc3VsdC5pbml0aWFsaXplZEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CiAgICAgICAgcmVzdWx0LnN0ZXBMb2cgPSBuZXdbXSB7ICJpbml0aWFsaXplLXN0YXRlOm9uRW50cnkiIH07CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCQiTGlmZWN5Y2xlIHRlc3QgaW5pdGlhbGl6ZWQsIHRlc3RQYXRoPXtyZXN1bHQudGVzdFBhdGh9Iik7CgogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ] + }, + "states": [ + { + "key": "initialize-state", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Initialize State (Initial)" + }, + { + "language": "tr-TR", + "label": "Baslangic Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "move-to-processing", + "target": "processing-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Move to Processing (Manual + ITransitionMapping)" + }, + { + "language": "tr-TR", + "label": "Isleme Gec (Manuel + ITransitionMapping)" + } + ], + "schema": null, + "view": null, + "mapping": { + "location": "./src/ProcessTransitionMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBQcm9jZXNzVHJhbnNpdGlvbk1hcHBpbmcgOiBTY3JpcHRCYXNlLCBJVHJhbnNpdGlvbk1hcHBpbmcKewogICAgcHVibGljIGFzeW5jIFRhc2s8ZHluYW1pYz4gSGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CgogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKCiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0UGF0aCIpKQogICAgICAgICAgICByZXN1bHQudGVzdFBhdGggPSBkYXRhLnRlc3RQYXRoOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaW5pdGlhbGl6ZWQiKSkKICAgICAgICAgICAgcmVzdWx0LmluaXRpYWxpemVkID0gZGF0YS5pbml0aWFsaXplZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImluaXRpYWxpemVkQXQiKSkKICAgICAgICAgICAgcmVzdWx0LmluaXRpYWxpemVkQXQgPSBkYXRhLmluaXRpYWxpemVkQXQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJzdGVwTG9nIikpCiAgICAgICAgICAgIHJlc3VsdC5zdGVwTG9nID0gZGF0YS5zdGVwTG9nOwoKICAgICAgICByZXN1bHQudHJhbnNpdGlvbk1hcHBpbmdFeGVjdXRlZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LnRyYW5zaXRpb25NYXBwaW5nQXQgPSBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoIm8iKTsKCiAgICAgICAgTG9nSW5mb3JtYXRpb24oIlByb2Nlc3NUcmFuc2l0aW9uTWFwcGluZyBleGVjdXRlZCIpOwoKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgfQp9Cg==" + }, + "onExecutionTasks": [], + "roles": [ + { + "role": "test-operator", + "grant": "allow" + } + ] + } + ] + }, + { + "key": "processing-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Processing State (Intermediate, onEntries + onExits)" + }, + { + "language": "tr-TR", + "label": "Isleme Durumu (Ara Durum, onEntries + onExits)" + } + ], + "queryRoles": [ + { + "role": "test-processor", + "grant": "allow" + }, + { + "role": "test-viewer", + "grant": "deny" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ProcessEntryMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFByb2Nlc3NFbnRyeU1hcHBpbmcgOiBTY3JpcHRCYXNlLCBJTWFwcGluZwp7CiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFdvcmtmbG93VGFzayB0YXNrLCBTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UoKSk7CiAgICB9CgogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwoKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CgogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAidGVzdFBhdGgiKSkKICAgICAgICAgICAgcmVzdWx0LnRlc3RQYXRoID0gZGF0YS50ZXN0UGF0aDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImluaXRpYWxpemVkIikpCiAgICAgICAgICAgIHJlc3VsdC5pbml0aWFsaXplZCA9IGRhdGEuaW5pdGlhbGl6ZWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJpbml0aWFsaXplZEF0IikpCiAgICAgICAgICAgIHJlc3VsdC5pbml0aWFsaXplZEF0ID0gZGF0YS5pbml0aWFsaXplZEF0OwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAidHJhbnNpdGlvbk1hcHBpbmdFeGVjdXRlZCIpKQogICAgICAgICAgICByZXN1bHQudHJhbnNpdGlvbk1hcHBpbmdFeGVjdXRlZCA9IGRhdGEudHJhbnNpdGlvbk1hcHBpbmdFeGVjdXRlZDsKCiAgICAgICAgcmVzdWx0LnByb2Nlc3NFbnRyeUV4ZWN1dGVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQucHJvY2Vzc2VkQXQgPSBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoIm8iKTsKCiAgICAgICAgTG9nSW5mb3JtYXRpb24oJCJQcm9jZXNzRW50cnlNYXBwaW5nIGV4ZWN1dGVkLCB0ZXN0UGF0aD17cmVzdWx0LnRlc3RQYXRofSIpOwoKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ], + "onExits": [ + { + "order": 1, + "task": { + "key": "script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ProcessExitMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFByb2Nlc3NFeGl0TWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CgogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKCiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0UGF0aCIpKQogICAgICAgICAgICByZXN1bHQudGVzdFBhdGggPSBkYXRhLnRlc3RQYXRoOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaW5pdGlhbGl6ZWQiKSkKICAgICAgICAgICAgcmVzdWx0LmluaXRpYWxpemVkID0gZGF0YS5pbml0aWFsaXplZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImluaXRpYWxpemVkQXQiKSkKICAgICAgICAgICAgcmVzdWx0LmluaXRpYWxpemVkQXQgPSBkYXRhLmluaXRpYWxpemVkQXQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0cmFuc2l0aW9uTWFwcGluZ0V4ZWN1dGVkIikpCiAgICAgICAgICAgIHJlc3VsdC50cmFuc2l0aW9uTWFwcGluZ0V4ZWN1dGVkID0gZGF0YS50cmFuc2l0aW9uTWFwcGluZ0V4ZWN1dGVkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAicHJvY2Vzc0VudHJ5RXhlY3V0ZWQiKSkKICAgICAgICAgICAgcmVzdWx0LnByb2Nlc3NFbnRyeUV4ZWN1dGVkID0gZGF0YS5wcm9jZXNzRW50cnlFeGVjdXRlZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInByb2Nlc3NlZEF0IikpCiAgICAgICAgICAgIHJlc3VsdC5wcm9jZXNzZWRBdCA9IGRhdGEucHJvY2Vzc2VkQXQ7CgogICAgICAgIHJlc3VsdC5wcm9jZXNzRXhpdEV4ZWN1dGVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQuZXhpdGVkQXQgPSBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoIm8iKTsKCiAgICAgICAgTG9nSW5mb3JtYXRpb24oIlByb2Nlc3NFeGl0TWFwcGluZyBleGVjdXRlZCIpOwoKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ], + "transitions": [ + { + "key": "auto-pass-transition", + "target": "auto-passed-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto Pass (testPath=pass)" + }, + { + "language": "tr-TR", + "label": "Otomatik Gecis (testPath=pass)" + } + ], + "rule": { + "location": "./src/TestPathPassRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBUZXN0UGF0aFBhc3NSdWxlIDogU2NyaXB0QmFzZSwgSUNvbmRpdGlvbk1hcHBpbmcKewogICAgcHVibGljIGFzeW5jIFRhc2s8Ym9vbD4gSGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlPy5EYXRhOwogICAgICAgIGlmIChkYXRhID09IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBMb2dJbmZvcm1hdGlvbigiVGVzdFBhdGhQYXNzUnVsZTogZGF0YSBpcyBudWxsLCByZXR1cm5pbmcgZmFsc2UiKTsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0UGF0aCIpKQogICAgICAgIHsKICAgICAgICAgICAgdmFyIHRlc3RQYXRoID0gZGF0YS50ZXN0UGF0aD8uVG9TdHJpbmcoKTsKICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRlc3RQYXRoID09ICJwYXNzIjsKICAgICAgICAgICAgTG9nSW5mb3JtYXRpb24oJCJUZXN0UGF0aFBhc3NSdWxlOiB0ZXN0UGF0aD17dGVzdFBhdGh9LCByZXN1bHQ9e3Jlc3VsdH0iKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCJUZXN0UGF0aFBhc3NSdWxlOiB0ZXN0UGF0aCBub3QgZm91bmQsIHJldHVybmluZyBmYWxzZSIpOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KfQo=" + }, + "onExecutionTasks": [] + }, + { + "key": "auto-fail-transition", + "target": "auto-failed-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto Fail (testPath=fail)" + }, + { + "language": "tr-TR", + "label": "Otomatik Basarisiz (testPath=fail)" + } + ], + "rule": { + "location": "./src/TestPathFailRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBUZXN0UGF0aEZhaWxSdWxlIDogU2NyaXB0QmFzZSwgSUNvbmRpdGlvbk1hcHBpbmcKewogICAgcHVibGljIGFzeW5jIFRhc2s8Ym9vbD4gSGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlPy5EYXRhOwogICAgICAgIGlmIChkYXRhID09IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBMb2dJbmZvcm1hdGlvbigiVGVzdFBhdGhGYWlsUnVsZTogZGF0YSBpcyBudWxsLCByZXR1cm5pbmcgZmFsc2UiKTsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0UGF0aCIpKQogICAgICAgIHsKICAgICAgICAgICAgdmFyIHRlc3RQYXRoID0gZGF0YS50ZXN0UGF0aD8uVG9TdHJpbmcoKTsKICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRlc3RQYXRoID09ICJmYWlsIjsKICAgICAgICAgICAgTG9nSW5mb3JtYXRpb24oJCJUZXN0UGF0aEZhaWxSdWxlOiB0ZXN0UGF0aD17dGVzdFBhdGh9LCByZXN1bHQ9e3Jlc3VsdH0iKTsKICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCJUZXN0UGF0aEZhaWxSdWxlOiB0ZXN0UGF0aCBub3QgZm91bmQsIHJldHVybmluZyBmYWxzZSIpOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KfQo=" + }, + "onExecutionTasks": [] + }, + { + "key": "default-auto-transition", + "target": "default-fallback-state", + "triggerType": 1, + "triggerKind": 10, + "versionStrategy": "Patch", + "labels": [ + { + "language": "en-US", + "label": "Default Auto (triggerKind:10 fallback)" + }, + { + "language": "tr-TR", + "label": "Varsayilan Otomatik Gecis (triggerKind:10)" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KfQo=" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "auto-passed-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto Passed State (Intermediate)" + }, + { + "language": "tr-TR", + "label": "Otomatik Gecis Basarili Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "scheduled-timer-transition", + "target": "timer-triggered-state", + "triggerType": 2, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Scheduled Timer (ITimerMapping, 10s)" + }, + { + "language": "tr-TR", + "label": "Zamanlanmis Gecis (ITimerMapping, 10s)" + } + ], + "timer": { + "location": "./src/ShortTimerMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uVGhyZWFkaW5nLlRhc2tzOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nOwoKcHVibGljIGNsYXNzIFNob3J0VGltZXJNYXBwaW5nIDogU2NyaXB0QmFzZSwgSVRpbWVyTWFwcGluZwp7CiAgICBwdWJsaWMgYXN5bmMgVGFzazxUaW1lclNjaGVkdWxlPiBIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICBMb2dJbmZvcm1hdGlvbigiU2hvcnRUaW1lck1hcHBpbmc6IHNjaGVkdWxpbmcgMTAgc2Vjb25kcyBmcm9tIG5vdyIpOwogICAgICAgIHJldHVybiBuZXcgVGltZXJTY2hlZHVsZQogICAgICAgIHsKICAgICAgICAgICAgRmlyZUF0ID0gRGF0ZVRpbWUuVXRjTm93LkFkZFNlY29uZHMoMTApCiAgICAgICAgfTsKICAgIH0KfQo=" + }, + "onExecutionTasks": [] + }, + { + "key": "cancel-schedule-manually", + "target": "pre-complete-state", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Cancel Schedule Manually" + }, + { + "language": "tr-TR", + "label": "Schedule Manuel Iptal" + } + ] + }, + { + "key": "reschedule-timer", + "target": "$self", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Reschedule Timer" + }, + { + "language": "tr-TR", + "label": "Timer Yeniden Zamanla" + } + ] + } + ] + }, + { + "key": "timer-triggered-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Timer Triggered State" + }, + { + "language": "tr-TR", + "label": "Zamanlayici Tetiklenmis Durum" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/TimerEntryMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFRpbWVyRW50cnlNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKCiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RQYXRoIikpCiAgICAgICAgICAgIHJlc3VsdC50ZXN0UGF0aCA9IGRhdGEudGVzdFBhdGg7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJpbml0aWFsaXplZCIpKQogICAgICAgICAgICByZXN1bHQuaW5pdGlhbGl6ZWQgPSBkYXRhLmluaXRpYWxpemVkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAicHJvY2Vzc0VudHJ5RXhlY3V0ZWQiKSkKICAgICAgICAgICAgcmVzdWx0LnByb2Nlc3NFbnRyeUV4ZWN1dGVkID0gZGF0YS5wcm9jZXNzRW50cnlFeGVjdXRlZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInByb2Nlc3NFeGl0RXhlY3V0ZWQiKSkKICAgICAgICAgICAgcmVzdWx0LnByb2Nlc3NFeGl0RXhlY3V0ZWQgPSBkYXRhLnByb2Nlc3NFeGl0RXhlY3V0ZWQ7CgogICAgICAgIHJlc3VsdC50aW1lclRyaWdnZXJlZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LnRpbWVyVHJpZ2dlcmVkQXQgPSBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoIm8iKTsKCiAgICAgICAgTG9nSW5mb3JtYXRpb24oIlRpbWVyRW50cnlNYXBwaW5nOiB0aW1lciBzdGF0ZSBlbnRlcmVkIik7CgogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-pre-complete", + "target": "pre-complete-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Pre-Complete (AlwaysTrue)" + }, + { + "language": "tr-TR", + "label": "Otomatik On-Tamamlama Gecisi" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KfQo=" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "pre-complete-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Pre-Complete State (Manual to Finish)" + }, + { + "language": "tr-TR", + "label": "Tamamlama Oncesi Durum" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "complete-workflow", + "target": "completed-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Complete Workflow (Manual to Final)" + }, + { + "language": "tr-TR", + "label": "Is Akisini Tamamla" + } + ], + "schema": null, + "view": null, + "onExecutionTasks": [], + "roles": [ + { + "role": "test-approver", + "grant": "allow" + }, + { + "role": "test-operator", + "grant": "deny" + } + ] + } + ] + }, + { + "key": "default-fallback-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Patch", + "labels": [ + { + "language": "en-US", + "label": "Default Fallback State (triggerKind:10 target)" + }, + { + "language": "tr-TR", + "label": "Varsayilan Geri Donus Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "fallback-to-complete", + "target": "completed-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Fallback Auto Complete" + }, + { + "language": "tr-TR", + "label": "Geri Donus Otomatik Tamamlama" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KfQo=" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "auto-failed-state", + "stateType": 3, + "subType": 2, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto Failed State (Final/Error)" + }, + { + "language": "tr-TR", + "label": "Otomatik Basarisiz Durumu (Final/Hata)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + }, + { + "key": "completed-state", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Completed State (Final/Success)" + }, + { + "language": "tr-TR", + "label": "Tamamlandi Durumu (Final/Basarili)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + }, + { + "key": "terminated-state", + "stateType": 3, + "subType": 3, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Terminated State (Final/Terminated)" + }, + { + "language": "tr-TR", + "label": "Sonlandirildi Durumu (Final/Sonlandirildi)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/lifecycle-transitions/src/AlwaysTrueRule.csx b/core/Workflows/lifecycle-transitions/src/AlwaysTrueRule.csx new file mode 100644 index 0000000..37de1d3 --- /dev/null +++ b/core/Workflows/lifecycle-transitions/src/AlwaysTrueRule.csx @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class AlwaysTrueRule : ScriptBase, IConditionMapping +{ + public async Task Handler(ScriptContext context) + { + LogInformation("AlwaysTrueRule: returning true"); + return true; + } +} diff --git a/core/Workflows/lifecycle-transitions/src/ExitMapping.csx b/core/Workflows/lifecycle-transitions/src/ExitMapping.csx new file mode 100644 index 0000000..c2860d6 --- /dev/null +++ b/core/Workflows/lifecycle-transitions/src/ExitMapping.csx @@ -0,0 +1,31 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class ExitMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) + result.testId = data.testId; + if (HasProperty(data, "initializeCompleted")) + result.initializeCompleted = data.initializeCompleted; + + result.exitExecuted = true; + result.exitAt = DateTime.UtcNow.ToString("o"); + + LogInformation("ExitMapping completed - workflow exited via exit transition"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/lifecycle-transitions/src/InitializeDataMapping.csx b/core/Workflows/lifecycle-transitions/src/InitializeDataMapping.csx new file mode 100644 index 0000000..83190f0 --- /dev/null +++ b/core/Workflows/lifecycle-transitions/src/InitializeDataMapping.csx @@ -0,0 +1,33 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class InitializeDataMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testPath")) + result.testPath = data.testPath; + else + result.testPath = "pass"; + + result.initialized = true; + result.initializedAt = DateTime.UtcNow.ToString("o"); + result.stepLog = new[] { "initialize-state:onEntry" }; + + LogInformation($"Lifecycle test initialized, testPath={result.testPath}"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/lifecycle-transitions/src/ProcessEntryMapping.csx b/core/Workflows/lifecycle-transitions/src/ProcessEntryMapping.csx new file mode 100644 index 0000000..6017e51 --- /dev/null +++ b/core/Workflows/lifecycle-transitions/src/ProcessEntryMapping.csx @@ -0,0 +1,36 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class ProcessEntryMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testPath")) + result.testPath = data.testPath; + if (HasProperty(data, "initialized")) + result.initialized = data.initialized; + if (HasProperty(data, "initializedAt")) + result.initializedAt = data.initializedAt; + if (HasProperty(data, "transitionMappingExecuted")) + result.transitionMappingExecuted = data.transitionMappingExecuted; + + result.processEntryExecuted = true; + result.processedAt = DateTime.UtcNow.ToString("o"); + + LogInformation($"ProcessEntryMapping executed, testPath={result.testPath}"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/lifecycle-transitions/src/ProcessExitMapping.csx b/core/Workflows/lifecycle-transitions/src/ProcessExitMapping.csx new file mode 100644 index 0000000..4941fd1 --- /dev/null +++ b/core/Workflows/lifecycle-transitions/src/ProcessExitMapping.csx @@ -0,0 +1,40 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class ProcessExitMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testPath")) + result.testPath = data.testPath; + if (HasProperty(data, "initialized")) + result.initialized = data.initialized; + if (HasProperty(data, "initializedAt")) + result.initializedAt = data.initializedAt; + if (HasProperty(data, "transitionMappingExecuted")) + result.transitionMappingExecuted = data.transitionMappingExecuted; + if (HasProperty(data, "processEntryExecuted")) + result.processEntryExecuted = data.processEntryExecuted; + if (HasProperty(data, "processedAt")) + result.processedAt = data.processedAt; + + result.processExitExecuted = true; + result.exitedAt = DateTime.UtcNow.ToString("o"); + + LogInformation("ProcessExitMapping executed"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/lifecycle-transitions/src/ProcessTransitionMapping.csx b/core/Workflows/lifecycle-transitions/src/ProcessTransitionMapping.csx new file mode 100644 index 0000000..a3df25f --- /dev/null +++ b/core/Workflows/lifecycle-transitions/src/ProcessTransitionMapping.csx @@ -0,0 +1,30 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class ProcessTransitionMapping : ScriptBase, ITransitionMapping +{ + public async Task Handler(ScriptContext context) + { + var data = context.Instance.Data; + + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testPath")) + result.testPath = data.testPath; + if (HasProperty(data, "initialized")) + result.initialized = data.initialized; + if (HasProperty(data, "initializedAt")) + result.initializedAt = data.initializedAt; + if (HasProperty(data, "stepLog")) + result.stepLog = data.stepLog; + + result.transitionMappingExecuted = true; + result.transitionMappingAt = DateTime.UtcNow.ToString("o"); + + LogInformation("ProcessTransitionMapping executed"); + + return result; + } +} diff --git a/core/Workflows/lifecycle-transitions/src/ShortTimerMapping.csx b/core/Workflows/lifecycle-transitions/src/ShortTimerMapping.csx new file mode 100644 index 0000000..945e5a1 --- /dev/null +++ b/core/Workflows/lifecycle-transitions/src/ShortTimerMapping.csx @@ -0,0 +1,15 @@ +using System; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class ShortTimerMapping : ScriptBase, ITimerMapping +{ + public async Task Handler(ScriptContext context) + { + LogInformation("ShortTimerMapping: scheduling 10 seconds from now"); + return new TimerSchedule + { + FireAt = DateTime.UtcNow.AddSeconds(10) + }; + } +} diff --git a/core/Workflows/lifecycle-transitions/src/TestPathFailRule.csx b/core/Workflows/lifecycle-transitions/src/TestPathFailRule.csx new file mode 100644 index 0000000..d5c5f51 --- /dev/null +++ b/core/Workflows/lifecycle-transitions/src/TestPathFailRule.csx @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class TestPathFailRule : ScriptBase, IConditionMapping +{ + public async Task Handler(ScriptContext context) + { + var data = context.Instance?.Data; + if (data == null) + { + LogInformation("TestPathFailRule: data is null, returning false"); + return false; + } + + if (HasProperty(data, "testPath")) + { + var testPath = data.testPath?.ToString(); + var result = testPath == "fail"; + LogInformation($"TestPathFailRule: testPath={testPath}, result={result}"); + return result; + } + + LogInformation("TestPathFailRule: testPath not found, returning false"); + return false; + } +} diff --git a/core/Workflows/lifecycle-transitions/src/TestPathPassRule.csx b/core/Workflows/lifecycle-transitions/src/TestPathPassRule.csx new file mode 100644 index 0000000..9af3695 --- /dev/null +++ b/core/Workflows/lifecycle-transitions/src/TestPathPassRule.csx @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class TestPathPassRule : ScriptBase, IConditionMapping +{ + public async Task Handler(ScriptContext context) + { + var data = context.Instance?.Data; + if (data == null) + { + LogInformation("TestPathPassRule: data is null, returning false"); + return false; + } + + if (HasProperty(data, "testPath")) + { + var testPath = data.testPath?.ToString(); + var result = testPath == "pass"; + LogInformation($"TestPathPassRule: testPath={testPath}, result={result}"); + return result; + } + + LogInformation("TestPathPassRule: testPath not found, returning false"); + return false; + } +} diff --git a/core/Workflows/lifecycle-transitions/src/TimerEntryMapping.csx b/core/Workflows/lifecycle-transitions/src/TimerEntryMapping.csx new file mode 100644 index 0000000..641690f --- /dev/null +++ b/core/Workflows/lifecycle-transitions/src/TimerEntryMapping.csx @@ -0,0 +1,36 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class TimerEntryMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testPath")) + result.testPath = data.testPath; + if (HasProperty(data, "initialized")) + result.initialized = data.initialized; + if (HasProperty(data, "processEntryExecuted")) + result.processEntryExecuted = data.processEntryExecuted; + if (HasProperty(data, "processExitExecuted")) + result.processExitExecuted = data.processExitExecuted; + + result.timerTriggered = true; + result.timerTriggeredAt = DateTime.UtcNow.ToString("o"); + + LogInformation("TimerEntryMapping: timer state entered"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/schema-data/schema-data-test-workflow.json b/core/Workflows/schema-data/schema-data-test-workflow.json new file mode 100644 index 0000000..487a093 --- /dev/null +++ b/core/Workflows/schema-data/schema-data-test-workflow.json @@ -0,0 +1,274 @@ +{ + "key": "schema-data-test-workflow", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "schema-data", + "master-schema", + "transition-schema", + "schema-rejection", + "update-data", + "field-roles", + "etag" + ], + "attributes": { + "type": "F", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "Schema & Data Management Integration Test" + }, + { + "language": "tr-TR", + "label": "Schema ve Data Yonetimi Entegrasyon Testi" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [], + "schema": { + "schema": { + "key": "schema-data-master", + "domain": "core", + "version": "1.0.0", + "flow": "sys-schemas" + } + }, + "updateData": { + "key": "update-instance-data", + "target": "$self", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Update Instance Data (updateData $self)" + }, + { + "language": "tr-TR", + "label": "Instance Datasini Guncelle (updateData $self)" + } + ] + }, + "startTransition": { + "key": "start-schema-test", + "target": "data-initialized", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Schema Test" + }, + { + "language": "tr-TR", + "label": "Schema Testini Baslat" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "schema-data-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/SchemaInitMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFNjaGVtYUluaXRNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKCiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgIm9yZGVySWQiKSkKICAgICAgICAgICAgcmVzdWx0Lm9yZGVySWQgPSBkYXRhLm9yZGVySWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJjdXN0b21lck5hbWUiKSkKICAgICAgICAgICAgcmVzdWx0LmN1c3RvbWVyTmFtZSA9IGRhdGEuY3VzdG9tZXJOYW1lOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiYW1vdW50IikpCiAgICAgICAgICAgIHJlc3VsdC5hbW91bnQgPSBkYXRhLmFtb3VudDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImN1cnJlbmN5IikpCiAgICAgICAgICAgIHJlc3VsdC5jdXJyZW5jeSA9IGRhdGEuY3VycmVuY3k7CgogICAgICAgIHJlc3VsdC5zdGF0dXMgPSAiaW5pdGlhbGl6ZWQiOwogICAgICAgIHJlc3VsdC5pbnRlcm5hbE5vdGUgPSAiQ3JlYXRlZCBieSBpbnRlZ3JhdGlvbiB0ZXN0IjsKICAgICAgICByZXN1bHQuYXVkaXRMb2cgPSAiSW5pdCBhdCAiICsgRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCQiU2NoZW1hSW5pdE1hcHBpbmc6IG9yZGVyPXtyZXN1bHQub3JkZXJJZH0iKTsKCiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ] + }, + "states": [ + { + "key": "data-initialized", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Data Initialized (Master Schema Active)" + }, + { + "language": "tr-TR", + "label": "Data Baslatildi (Ana Schema Aktif)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "confirm-with-schema", + "target": "schema-validated-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Confirm with Transition Schema" + }, + { + "language": "tr-TR", + "label": "Transition Schema ile Onayla" + } + ], + "schema": { + "key": "schema-data-confirm-transition", + "domain": "core", + "version": "1.0.0", + "flow": "sys-schemas" + }, + "view": null, + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "schema-data-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ConfirmMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIENvbmZpcm1NYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKCiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgIm9yZGVySWQiKSkKICAgICAgICAgICAgcmVzdWx0Lm9yZGVySWQgPSBkYXRhLm9yZGVySWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJjdXN0b21lck5hbWUiKSkKICAgICAgICAgICAgcmVzdWx0LmN1c3RvbWVyTmFtZSA9IGRhdGEuY3VzdG9tZXJOYW1lOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiYW1vdW50IikpCiAgICAgICAgICAgIHJlc3VsdC5hbW91bnQgPSBkYXRhLmFtb3VudDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImN1cnJlbmN5IikpCiAgICAgICAgICAgIHJlc3VsdC5jdXJyZW5jeSA9IGRhdGEuY3VycmVuY3k7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJpbnRlcm5hbE5vdGUiKSkKICAgICAgICAgICAgcmVzdWx0LmludGVybmFsTm90ZSA9IGRhdGEuaW50ZXJuYWxOb3RlOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiYXVkaXRMb2ciKSkKICAgICAgICAgICAgcmVzdWx0LmF1ZGl0TG9nID0gZGF0YS5hdWRpdExvZzsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImNvbmZpcm1lZCIpKQogICAgICAgICAgICByZXN1bHQuY29uZmlybWVkID0gZGF0YS5jb25maXJtZWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJjb25maXJtZWRCeSIpKQogICAgICAgICAgICByZXN1bHQuY29uZmlybWVkQnkgPSBkYXRhLmNvbmZpcm1lZEJ5OwoKICAgICAgICByZXN1bHQuc3RhdHVzID0gImNvbmZpcm1lZCI7CiAgICAgICAgcmVzdWx0LnVwZGF0ZWRBdCA9IERhdGVUaW1lLlV0Y05vdy5Ub1N0cmluZygibyIpOwoKICAgICAgICBMb2dJbmZvcm1hdGlvbigkIkNvbmZpcm1NYXBwaW5nOiBjb25maXJtZWQgYnkge3Jlc3VsdC5jb25maXJtZWRCeX0iKTsKCiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ] + }, + { + "key": "skip-to-no-schema", + "target": "no-schema-state", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Skip to No-Schema State" + }, + { + "language": "tr-TR", + "label": "Schemasiz Duruma Atla" + } + ], + "schema": null, + "view": null, + "onExecutionTasks": [] + } + ] + }, + { + "key": "schema-validated-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Schema Validated State" + }, + { + "language": "tr-TR", + "label": "Schema Dogrulanmis Durum" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "to-no-schema", + "target": "no-schema-state", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Move to No-Schema State" + }, + { + "language": "tr-TR", + "label": "Schemasiz Duruma Gec" + } + ], + "schema": null, + "view": null, + "onExecutionTasks": [] + } + ] + }, + { + "key": "no-schema-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "No Schema State (Free-form transitions)" + }, + { + "language": "tr-TR", + "label": "Schemasiz Durum (Serbest gecisler)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "complete-schema-test", + "target": "completed-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Complete Schema Test" + }, + { + "language": "tr-TR", + "label": "Schema Testini Tamamla" + } + ], + "schema": null, + "view": null, + "onExecutionTasks": [] + } + ] + }, + { + "key": "completed-state", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Schema Test Completed (Final/Success)" + }, + { + "language": "tr-TR", + "label": "Schema Testi Tamamlandi (Final/Basarili)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/schema-data/src/ConfirmMapping.csx b/core/Workflows/schema-data/src/ConfirmMapping.csx new file mode 100644 index 0000000..01888bc --- /dev/null +++ b/core/Workflows/schema-data/src/ConfirmMapping.csx @@ -0,0 +1,44 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class ConfirmMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "orderId")) + result.orderId = data.orderId; + if (HasProperty(data, "customerName")) + result.customerName = data.customerName; + if (HasProperty(data, "amount")) + result.amount = data.amount; + if (HasProperty(data, "currency")) + result.currency = data.currency; + if (HasProperty(data, "internalNote")) + result.internalNote = data.internalNote; + if (HasProperty(data, "auditLog")) + result.auditLog = data.auditLog; + if (HasProperty(data, "confirmed")) + result.confirmed = data.confirmed; + if (HasProperty(data, "confirmedBy")) + result.confirmedBy = data.confirmedBy; + + result.status = "confirmed"; + result.updatedAt = DateTime.UtcNow.ToString("o"); + + LogInformation($"ConfirmMapping: confirmed by {result.confirmedBy}"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/schema-data/src/SchemaInitMapping.csx b/core/Workflows/schema-data/src/SchemaInitMapping.csx new file mode 100644 index 0000000..6af886b --- /dev/null +++ b/core/Workflows/schema-data/src/SchemaInitMapping.csx @@ -0,0 +1,37 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class SchemaInitMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "orderId")) + result.orderId = data.orderId; + if (HasProperty(data, "customerName")) + result.customerName = data.customerName; + if (HasProperty(data, "amount")) + result.amount = data.amount; + if (HasProperty(data, "currency")) + result.currency = data.currency; + + result.status = "initialized"; + result.internalNote = "Created by integration test"; + result.auditLog = "Init at " + DateTime.UtcNow.ToString("o"); + + LogInformation($"SchemaInitMapping: order={result.orderId}"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/subflow-orchestration/src/AlwaysTrueRule.csx b/core/Workflows/subflow-orchestration/src/AlwaysTrueRule.csx new file mode 100644 index 0000000..3d08a0f --- /dev/null +++ b/core/Workflows/subflow-orchestration/src/AlwaysTrueRule.csx @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class AlwaysTrueRule : ScriptBase, IConditionMapping +{ + public Task Handler(ScriptContext context) + { + LogInformation("AlwaysTrueRule: returning true"); + return Task.FromResult(true); + } +} diff --git a/core/Workflows/subflow-orchestration/src/ChildSharedUpdateMapping.csx b/core/Workflows/subflow-orchestration/src/ChildSharedUpdateMapping.csx new file mode 100644 index 0000000..54795bb --- /dev/null +++ b/core/Workflows/subflow-orchestration/src/ChildSharedUpdateMapping.csx @@ -0,0 +1,25 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Definitions; +using BBT.Workflow.Scripting; + +public class ChildSharedUpdateMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + if (HasProperty(data, "childStarted")) result.childStarted = data.childStarted; + if (HasProperty(data, "grandchildCompleted")) result.grandchildCompleted = data.grandchildCompleted; + result.childSharedUpdateExecuted = true; + result.childSharedUpdateAt = DateTime.UtcNow.ToString("o"); + LogInformation("ChildSharedUpdateMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/subflow-orchestration/src/ChildStartMapping.csx b/core/Workflows/subflow-orchestration/src/ChildStartMapping.csx new file mode 100644 index 0000000..ec21280 --- /dev/null +++ b/core/Workflows/subflow-orchestration/src/ChildStartMapping.csx @@ -0,0 +1,32 @@ +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Definitions; +using BBT.Workflow.Scripting; + +public class ChildStartMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + result.childStarted = true; + if (data != null) + { + if (HasProperty(data, "parentData")) + { + result.parentData = data.parentData; + } + if (HasProperty(data, "testId")) + { + result.testId = data.testId; + } + } + LogInformation("ChildStartMapping: childStarted set"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/subflow-orchestration/src/ChildToGrandchildSubFlowMapping.csx b/core/Workflows/subflow-orchestration/src/ChildToGrandchildSubFlowMapping.csx new file mode 100644 index 0000000..2960bf2 --- /dev/null +++ b/core/Workflows/subflow-orchestration/src/ChildToGrandchildSubFlowMapping.csx @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class ChildToGrandchildSubFlowMapping : ScriptBase, ISubFlowMapping +{ + public Task InputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic gcInput = new ExpandoObject(); + if (data != null) + { + if (HasProperty(data, "parentData")) + { + gcInput.parentData = data.parentData; + } + if (HasProperty(data, "testId")) + { + gcInput.testId = data.testId; + } + if (HasProperty(data, "childStarted")) + { + gcInput.childStarted = data.childStarted; + } + } + LogInformation("ChildToGrandchildSubFlowMapping: prepared grandchild input"); + return Task.FromResult(new ScriptResponse { Data = gcInput }); + } + + public Task OutputHandler(ScriptContext context) + { + var body = context.Body as IDictionary; + dynamic merged = new ExpandoObject(); + var target = (IDictionary)merged; + var inst = context.Instance.Data as IDictionary; + if (inst != null) + { + foreach (var kv in inst) + { + target[kv.Key] = kv.Value; + } + } + if (body != null) + { + foreach (var kv in body) + { + target[kv.Key] = kv.Value; + } + } + target["grandchildCompleted"] = true; + LogInformation("ChildToGrandchildSubFlowMapping: merged grandchild output"); + return Task.FromResult(new ScriptResponse { Data = merged }); + } +} diff --git a/core/Workflows/subflow-orchestration/src/GrandchildCompleteMapping.csx b/core/Workflows/subflow-orchestration/src/GrandchildCompleteMapping.csx new file mode 100644 index 0000000..d322d9b --- /dev/null +++ b/core/Workflows/subflow-orchestration/src/GrandchildCompleteMapping.csx @@ -0,0 +1,20 @@ +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Definitions; +using BBT.Workflow.Scripting; + +public class GrandchildCompleteMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + dynamic result = new ExpandoObject(); + result.grandchildFinished = true; + LogInformation("GrandchildCompleteMapping: grandchildFinished set"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/subflow-orchestration/src/GrandchildStartMapping.csx b/core/Workflows/subflow-orchestration/src/GrandchildStartMapping.csx new file mode 100644 index 0000000..f335f31 --- /dev/null +++ b/core/Workflows/subflow-orchestration/src/GrandchildStartMapping.csx @@ -0,0 +1,36 @@ +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Definitions; +using BBT.Workflow.Scripting; + +public class GrandchildStartMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + result.grandchildStarted = true; + if (data != null) + { + if (HasProperty(data, "testId")) + { + result.testId = data.testId; + } + if (HasProperty(data, "parentData")) + { + result.parentData = data.parentData; + } + if (HasProperty(data, "childStarted")) + { + result.childStarted = data.childStarted; + } + } + LogInformation("GrandchildStartMapping: grandchildStarted set"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/subflow-orchestration/src/ParentSharedUpdateMapping.csx b/core/Workflows/subflow-orchestration/src/ParentSharedUpdateMapping.csx new file mode 100644 index 0000000..4f3f389 --- /dev/null +++ b/core/Workflows/subflow-orchestration/src/ParentSharedUpdateMapping.csx @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Definitions; +using BBT.Workflow.Scripting; + +public class ParentSharedUpdateMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + dynamic result = new ExpandoObject(); + var target = (IDictionary)result; + var inst = context.Instance.Data as IDictionary; + if (inst != null) + { + foreach (var kv in inst) + { + target[kv.Key] = kv.Value; + } + } + target["sharedUpdateExecuted"] = true; + LogInformation("ParentSharedUpdateMapping: merged instance data with sharedUpdateExecuted"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/subflow-orchestration/src/ParentStartMapping.csx b/core/Workflows/subflow-orchestration/src/ParentStartMapping.csx new file mode 100644 index 0000000..1a3e252 --- /dev/null +++ b/core/Workflows/subflow-orchestration/src/ParentStartMapping.csx @@ -0,0 +1,25 @@ +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Definitions; +using BBT.Workflow.Scripting; + +public class ParentStartMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + result.parentStarted = true; + if (data != null && HasProperty(data, "testId")) + { + result.testId = data.testId; + } + LogInformation("ParentStartMapping: parentStarted set"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/subflow-orchestration/src/ParentToChildSubFlowMapping.csx b/core/Workflows/subflow-orchestration/src/ParentToChildSubFlowMapping.csx new file mode 100644 index 0000000..ea2ab04 --- /dev/null +++ b/core/Workflows/subflow-orchestration/src/ParentToChildSubFlowMapping.csx @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class ParentToChildSubFlowMapping : ScriptBase, ISubFlowMapping +{ + public Task InputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic childInput = new ExpandoObject(); + if (data != null && HasProperty(data, "parentData")) + { + childInput.parentData = data.parentData; + } + if (data != null && HasProperty(data, "testId")) + { + childInput.testId = data.testId; + } + LogInformation("ParentToChildSubFlowMapping: prepared child input"); + return Task.FromResult(new ScriptResponse { Data = childInput }); + } + + public Task OutputHandler(ScriptContext context) + { + var body = context.Body as IDictionary; + dynamic merged = new ExpandoObject(); + var target = (IDictionary)merged; + var inst = context.Instance.Data as IDictionary; + if (inst != null) + { + foreach (var kv in inst) + { + target[kv.Key] = kv.Value; + } + } + if (body != null) + { + foreach (var kv in body) + { + target[kv.Key] = kv.Value; + } + } + target["childCompleted"] = true; + LogInformation("ParentToChildSubFlowMapping: merged child output"); + return Task.FromResult(new ScriptResponse { Data = merged }); + } +} diff --git a/core/Workflows/subflow-orchestration/src/UpdateParentDataMapping.csx b/core/Workflows/subflow-orchestration/src/UpdateParentDataMapping.csx new file mode 100644 index 0000000..3ca3f72 --- /dev/null +++ b/core/Workflows/subflow-orchestration/src/UpdateParentDataMapping.csx @@ -0,0 +1,33 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class UpdateParentDataMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "childStarted")) + result.childStarted = data.childStarted; + if (HasProperty(data, "grandchildFinished")) + result.grandchildFinished = data.grandchildFinished; + if (HasProperty(data, "childSharedUpdateExecuted")) + result.childSharedUpdateExecuted = data.childSharedUpdateExecuted; + + result.childUpdatedParent = true; + result.updateParentAt = DateTime.UtcNow.ToString("o"); + + LogInformation("UpdateParentDataMapping completed - updateData from child to parent"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/subflow-orchestration/subflow-orchestration-child.json b/core/Workflows/subflow-orchestration/subflow-orchestration-child.json new file mode 100644 index 0000000..be79a2f --- /dev/null +++ b/core/Workflows/subflow-orchestration/subflow-orchestration-child.json @@ -0,0 +1,286 @@ +{ + "key": "subflow-orchestration-child", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "subflow-orchestration", + "child", + "subflow", + "update-data" + ], + "attributes": { + "type": "S", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "SubFlow Orchestration Child" + }, + { + "language": "tr-TR", + "label": "Alt Akis Orkestrasyon Cocuk" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [ + { + "key": "shared-child-update", + "target": "$self", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Shared Child Update ($self)" + }, + { + "language": "tr-TR", + "label": "Paylasimli Child Guncelleme ($self)" + } + ], + "availableIn": [ + "child-subflow-state" + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "subflow-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ChildSharedUpdateMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nOwoKcHVibGljIGNsYXNzIENoaWxkU2hhcmVkVXBkYXRlTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiY2hpbGRTdGFydGVkIikpIHJlc3VsdC5jaGlsZFN0YXJ0ZWQgPSBkYXRhLmNoaWxkU3RhcnRlZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImdyYW5kY2hpbGRDb21wbGV0ZWQiKSkgcmVzdWx0LmdyYW5kY2hpbGRDb21wbGV0ZWQgPSBkYXRhLmdyYW5kY2hpbGRDb21wbGV0ZWQ7CiAgICAgICAgcmVzdWx0LmNoaWxkU2hhcmVkVXBkYXRlRXhlY3V0ZWQgPSB0cnVlOwogICAgICAgIHJlc3VsdC5jaGlsZFNoYXJlZFVwZGF0ZUF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CiAgICAgICAgTG9nSW5mb3JtYXRpb24oIkNoaWxkU2hhcmVkVXBkYXRlTWFwcGluZyBjb21wbGV0ZWQiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ] + } + ], + "cancel": { + "key": "cancel-child", + "target": "child-cancelled", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Cancel Child" + }, + { + "language": "tr-TR", + "label": "Child Iptal" + } + ] + }, + "updateData": { + "key": "update-parent-data", + "target": "$self", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Update Parent Data from Child" + }, + { + "language": "tr-TR", + "label": "Child'dan Parent Data Guncelle" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "subflow-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/UpdateParentDataMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFVwZGF0ZVBhcmVudERhdGFNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CgogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiY2hpbGRTdGFydGVkIikpCiAgICAgICAgICAgIHJlc3VsdC5jaGlsZFN0YXJ0ZWQgPSBkYXRhLmNoaWxkU3RhcnRlZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImdyYW5kY2hpbGRGaW5pc2hlZCIpKQogICAgICAgICAgICByZXN1bHQuZ3JhbmRjaGlsZEZpbmlzaGVkID0gZGF0YS5ncmFuZGNoaWxkRmluaXNoZWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJjaGlsZFNoYXJlZFVwZGF0ZUV4ZWN1dGVkIikpCiAgICAgICAgICAgIHJlc3VsdC5jaGlsZFNoYXJlZFVwZGF0ZUV4ZWN1dGVkID0gZGF0YS5jaGlsZFNoYXJlZFVwZGF0ZUV4ZWN1dGVkOwoKICAgICAgICByZXN1bHQuY2hpbGRVcGRhdGVkUGFyZW50ID0gdHJ1ZTsKICAgICAgICByZXN1bHQudXBkYXRlUGFyZW50QXQgPSBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoIm8iKTsKCiAgICAgICAgTG9nSW5mb3JtYXRpb24oIlVwZGF0ZVBhcmVudERhdGFNYXBwaW5nIGNvbXBsZXRlZCAtIHVwZGF0ZURhdGEgZnJvbSBjaGlsZCB0byBwYXJlbnQiKTsKCiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ] + }, + "startTransition": { + "key": "start-subflow-orchestration-child", + "target": "child-initial", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Child" + }, + { + "language": "tr-TR", + "label": "Cocugu Baslat" + } + ] + }, + "states": [ + { + "key": "child-initial", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Child Initial" + }, + { + "language": "tr-TR", + "label": "Cocuk Baslangic" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "subflow-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ChildStartMapping.csx", + "code": "dXNpbmcgU3lzdGVtLkR5bmFtaWM7CnVzaW5nIFN5c3RlbS5UaHJlYWRpbmcuVGFza3M7CnVzaW5nIEJCVC5Xb3JrZmxvdy5EZWZpbml0aW9uczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBDaGlsZFN0YXJ0TWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHJlc3VsdC5jaGlsZFN0YXJ0ZWQgPSB0cnVlOwogICAgICAgIGlmIChkYXRhICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInBhcmVudERhdGEiKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmVzdWx0LnBhcmVudERhdGEgPSBkYXRhLnBhcmVudERhdGE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmVzdWx0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIExvZ0luZm9ybWF0aW9uKCJDaGlsZFN0YXJ0TWFwcGluZzogY2hpbGRTdGFydGVkIHNldCIpOwogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-child-to-subflow", + "target": "child-subflow-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Child SubFlow State" + }, + { + "language": "tr-TR", + "label": "Otomatik Alt Akis Durumuna" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "child-subflow-state", + "stateType": 4, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Child SubFlow State" + }, + { + "language": "tr-TR", + "label": "Cocuk Alt Akis Durumu" + } + ], + "view": null, + "subFlow": { + "type": "S", + "process": { + "key": "subflow-orchestration-grandchild", + "domain": "core", + "version": "1.0.0", + "flow": "sys-flows" + }, + "mapping": { + "location": "./src/ChildToGrandchildSubFlowMapping.csx", + "code": "dXNpbmcgU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWM7CnVzaW5nIFN5c3RlbS5EeW5hbWljOwp1c2luZyBTeXN0ZW0uVGhyZWFkaW5nLlRhc2tzOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nOwoKcHVibGljIGNsYXNzIENoaWxkVG9HcmFuZGNoaWxkU3ViRmxvd01hcHBpbmcgOiBTY3JpcHRCYXNlLCBJU3ViRmxvd01hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyBnY0lucHV0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICBpZiAoZGF0YSAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJwYXJlbnREYXRhIikpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGdjSW5wdXQucGFyZW50RGF0YSA9IGRhdGEucGFyZW50RGF0YTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBnY0lucHV0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiY2hpbGRTdGFydGVkIikpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGdjSW5wdXQuY2hpbGRTdGFydGVkID0gZGF0YS5jaGlsZFN0YXJ0ZWQ7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgTG9nSW5mb3JtYXRpb24oIkNoaWxkVG9HcmFuZGNoaWxkU3ViRmxvd01hcHBpbmc6IHByZXBhcmVkIGdyYW5kY2hpbGQgaW5wdXQiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSBnY0lucHV0IH0pOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgYm9keSA9IGNvbnRleHQuQm9keSBhcyBJRGljdGlvbmFyeTxzdHJpbmcsIG9iamVjdD47CiAgICAgICAgZHluYW1pYyBtZXJnZWQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHZhciB0YXJnZXQgPSAoSURpY3Rpb25hcnk8c3RyaW5nLCBvYmplY3Q+KW1lcmdlZDsKICAgICAgICB2YXIgaW5zdCA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YSBhcyBJRGljdGlvbmFyeTxzdHJpbmcsIG9iamVjdD47CiAgICAgICAgaWYgKGluc3QgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGZvcmVhY2ggKHZhciBrdiBpbiBpbnN0KQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICB0YXJnZXRba3YuS2V5XSA9IGt2LlZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChib2R5ICE9IG51bGwpCiAgICAgICAgewogICAgICAgICAgICBmb3JlYWNoICh2YXIga3YgaW4gYm9keSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdGFyZ2V0W2t2LktleV0gPSBrdi5WYWx1ZTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB0YXJnZXRbImdyYW5kY2hpbGRDb21wbGV0ZWQiXSA9IHRydWU7CiAgICAgICAgTG9nSW5mb3JtYXRpb24oIkNoaWxkVG9HcmFuZGNoaWxkU3ViRmxvd01hcHBpbmc6IG1lcmdlZCBncmFuZGNoaWxkIG91dHB1dCIpOwogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IG1lcmdlZCB9KTsKICAgIH0KfQo=" + } + }, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "auto-child-to-completed", + "target": "child-completed", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Child Completed" + }, + { + "language": "tr-TR", + "label": "Otomatik Cocuk Tamamlandi" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "child-completed", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Child Completed" + }, + { + "language": "tr-TR", + "label": "Cocuk Tamamlandi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + }, + { + "key": "child-cancelled", + "stateType": 3, + "subType": 3, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Child Cancelled" + }, + { + "language": "tr-TR", + "label": "Cocuk Iptal" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/subflow-orchestration/subflow-orchestration-grandchild.json b/core/Workflows/subflow-orchestration/subflow-orchestration-grandchild.json new file mode 100644 index 0000000..1a1d8a4 --- /dev/null +++ b/core/Workflows/subflow-orchestration/subflow-orchestration-grandchild.json @@ -0,0 +1,174 @@ +{ + "key": "subflow-orchestration-grandchild", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "subflow-orchestration", + "grandchild", + "subflow" + ], + "attributes": { + "type": "S", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "SubFlow Orchestration Grandchild" + }, + { + "language": "tr-TR", + "label": "Alt Akis Orkestrasyon Torun" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [], + "cancel": { + "key": "cancel-grandchild", + "target": "grandchild-cancelled", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Cancel Grandchild" + }, + { + "language": "tr-TR", + "label": "Grandchild Iptal" + } + ] + }, + "startTransition": { + "key": "start-subflow-orchestration-grandchild", + "target": "grandchild-initial", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Grandchild" + }, + { + "language": "tr-TR", + "label": "Torunu Baslat" + } + ] + }, + "states": [ + { + "key": "grandchild-initial", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Grandchild Initial" + }, + { + "language": "tr-TR", + "label": "Torun Baslangic" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "subflow-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/GrandchildStartMapping.csx", + "code": "dXNpbmcgU3lzdGVtLkR5bmFtaWM7CnVzaW5nIFN5c3RlbS5UaHJlYWRpbmcuVGFza3M7CnVzaW5nIEJCVC5Xb3JrZmxvdy5EZWZpbml0aW9uczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBHcmFuZGNoaWxkU3RhcnRNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CiAgICAgICAgcmVzdWx0LmdyYW5kY2hpbGRTdGFydGVkID0gdHJ1ZTsKICAgICAgICBpZiAoZGF0YSAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmVzdWx0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAicGFyZW50RGF0YSIpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXN1bHQucGFyZW50RGF0YSA9IGRhdGEucGFyZW50RGF0YTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImNoaWxkU3RhcnRlZCIpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXN1bHQuY2hpbGRTdGFydGVkID0gZGF0YS5jaGlsZFN0YXJ0ZWQ7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgTG9nSW5mb3JtYXRpb24oIkdyYW5kY2hpbGRTdGFydE1hcHBpbmc6IGdyYW5kY2hpbGRTdGFydGVkIHNldCIpOwogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "complete-grandchild", + "target": "grandchild-completed", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Complete Grandchild" + }, + { + "language": "tr-TR", + "label": "Torunu Tamamla" + } + ], + "onExecutionTasks": [] + } + ] + }, + { + "key": "grandchild-completed", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Grandchild Completed" + }, + { + "language": "tr-TR", + "label": "Torun Tamamlandi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "subflow-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/GrandchildCompleteMapping.csx", + "code": "dXNpbmcgU3lzdGVtLkR5bmFtaWM7CnVzaW5nIFN5c3RlbS5UaHJlYWRpbmcuVGFza3M7CnVzaW5nIEJCVC5Xb3JrZmxvdy5EZWZpbml0aW9uczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBHcmFuZGNoaWxkQ29tcGxldGVNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CiAgICAgICAgcmVzdWx0LmdyYW5kY2hpbGRGaW5pc2hlZCA9IHRydWU7CiAgICAgICAgTG9nSW5mb3JtYXRpb24oIkdyYW5kY2hpbGRDb21wbGV0ZU1hcHBpbmc6IGdyYW5kY2hpbGRGaW5pc2hlZCBzZXQiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ], + "onExits": [], + "transitions": [] + }, + { + "key": "grandchild-cancelled", + "stateType": 3, + "subType": 3, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Grandchild Cancelled" + }, + { + "language": "tr-TR", + "label": "Torun Iptal" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/subflow-orchestration/subflow-orchestration-parent.json b/core/Workflows/subflow-orchestration/subflow-orchestration-parent.json new file mode 100644 index 0000000..64eeb1e --- /dev/null +++ b/core/Workflows/subflow-orchestration/subflow-orchestration-parent.json @@ -0,0 +1,256 @@ +{ + "key": "subflow-orchestration-parent", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "subflow-orchestration", + "parent", + "shared-transitions", + "cancel" + ], + "attributes": { + "type": "F", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "SubFlow Orchestration Parent" + }, + { + "language": "tr-TR", + "label": "Alt Akis Orkestrasyon Ebeveyn" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [ + { + "key": "shared-update-data", + "target": "$self", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Shared Update Data" + }, + { + "language": "tr-TR", + "label": "Paylasimli Veri Guncelle" + } + ], + "availableIn": [ + "parent-subflow-state" + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "subflow-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ParentSharedUpdateMapping.csx", + "code": "dXNpbmcgU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWM7CnVzaW5nIFN5c3RlbS5EeW5hbWljOwp1c2luZyBTeXN0ZW0uVGhyZWFkaW5nLlRhc2tzOwp1c2luZyBCQlQuV29ya2Zsb3cuRGVmaW5pdGlvbnM7CnVzaW5nIEJCVC5Xb3JrZmxvdy5TY3JpcHRpbmc7CgpwdWJsaWMgY2xhc3MgUGFyZW50U2hhcmVkVXBkYXRlTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIHZhciB0YXJnZXQgPSAoSURpY3Rpb25hcnk8c3RyaW5nLCBvYmplY3Q+KXJlc3VsdDsKICAgICAgICB2YXIgaW5zdCA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YSBhcyBJRGljdGlvbmFyeTxzdHJpbmcsIG9iamVjdD47CiAgICAgICAgaWYgKGluc3QgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGZvcmVhY2ggKHZhciBrdiBpbiBpbnN0KQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICB0YXJnZXRba3YuS2V5XSA9IGt2LlZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHRhcmdldFsic2hhcmVkVXBkYXRlRXhlY3V0ZWQiXSA9IHRydWU7CiAgICAgICAgTG9nSW5mb3JtYXRpb24oIlBhcmVudFNoYXJlZFVwZGF0ZU1hcHBpbmc6IG1lcmdlZCBpbnN0YW5jZSBkYXRhIHdpdGggc2hhcmVkVXBkYXRlRXhlY3V0ZWQiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ] + } + ], + "cancel": { + "key": "cancel-parent", + "target": "parent-cancelled", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Cancel Parent" + }, + { + "language": "tr-TR", + "label": "Ebeveyni Iptal Et" + } + ] + }, + "startTransition": { + "key": "start-subflow-orchestration-parent", + "target": "parent-initial", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Parent Orchestration" + }, + { + "language": "tr-TR", + "label": "Ebeveyn Orkestrasyonu Baslat" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "subflow-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ParentStartMapping.csx", + "code": "dXNpbmcgU3lzdGVtLkR5bmFtaWM7CnVzaW5nIFN5c3RlbS5UaHJlYWRpbmcuVGFza3M7CnVzaW5nIEJCVC5Xb3JrZmxvdy5EZWZpbml0aW9uczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBQYXJlbnRTdGFydE1hcHBpbmcgOiBTY3JpcHRCYXNlLCBJTWFwcGluZwp7CiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFdvcmtmbG93VGFzayB0YXNrLCBTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UoKSk7CiAgICB9CgogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICByZXN1bHQucGFyZW50U3RhcnRlZCA9IHRydWU7CiAgICAgICAgaWYgKGRhdGEgIT0gbnVsbCAmJiBIYXNQcm9wZXJ0eShkYXRhLCAidGVzdElkIikpCiAgICAgICAgewogICAgICAgICAgICByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CiAgICAgICAgfQogICAgICAgIExvZ0luZm9ybWF0aW9uKCJQYXJlbnRTdGFydE1hcHBpbmc6IHBhcmVudFN0YXJ0ZWQgc2V0Iik7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ] + }, + "states": [ + { + "key": "parent-initial", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Parent Initial" + }, + { + "language": "tr-TR", + "label": "Ebeveyn Baslangic" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "auto-parent-to-subflow", + "target": "parent-subflow-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Parent SubFlow State" + }, + { + "language": "tr-TR", + "label": "Otomatik Alt Akis Durumuna" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "parent-subflow-state", + "stateType": 4, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Parent SubFlow State" + }, + { + "language": "tr-TR", + "label": "Ebeveyn Alt Akis Durumu" + } + ], + "view": null, + "subFlow": { + "type": "S", + "process": { + "key": "subflow-orchestration-child", + "domain": "core", + "version": "1.0.0", + "flow": "sys-flows" + }, + "mapping": { + "location": "./src/ParentToChildSubFlowMapping.csx", + "code": "dXNpbmcgU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWM7CnVzaW5nIFN5c3RlbS5EeW5hbWljOwp1c2luZyBTeXN0ZW0uVGhyZWFkaW5nLlRhc2tzOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nOwoKcHVibGljIGNsYXNzIFBhcmVudFRvQ2hpbGRTdWJGbG93TWFwcGluZyA6IFNjcmlwdEJhc2UsIElTdWJGbG93TWFwcGluZwp7CiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKICAgICAgICBkeW5hbWljIGNoaWxkSW5wdXQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwogICAgICAgIGlmIChkYXRhICE9IG51bGwgJiYgSGFzUHJvcGVydHkoZGF0YSwgInBhcmVudERhdGEiKSkKICAgICAgICB7CiAgICAgICAgICAgIGNoaWxkSW5wdXQucGFyZW50RGF0YSA9IGRhdGEucGFyZW50RGF0YTsKICAgICAgICB9CiAgICAgICAgaWYgKGRhdGEgIT0gbnVsbCAmJiBIYXNQcm9wZXJ0eShkYXRhLCAidGVzdElkIikpCiAgICAgICAgewogICAgICAgICAgICBjaGlsZElucHV0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgIH0KICAgICAgICBMb2dJbmZvcm1hdGlvbigiUGFyZW50VG9DaGlsZFN1YkZsb3dNYXBwaW5nOiBwcmVwYXJlZCBjaGlsZCBpbnB1dCIpOwogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IGNoaWxkSW5wdXQgfSk7CiAgICB9CgogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBib2R5ID0gY29udGV4dC5Cb2R5IGFzIElEaWN0aW9uYXJ5PHN0cmluZywgb2JqZWN0PjsKICAgICAgICBkeW5hbWljIG1lcmdlZCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CiAgICAgICAgdmFyIHRhcmdldCA9IChJRGljdGlvbmFyeTxzdHJpbmcsIG9iamVjdD4pbWVyZ2VkOwogICAgICAgIHZhciBpbnN0ID0gY29udGV4dC5JbnN0YW5jZS5EYXRhIGFzIElEaWN0aW9uYXJ5PHN0cmluZywgb2JqZWN0PjsKICAgICAgICBpZiAoaW5zdCAhPSBudWxsKQogICAgICAgIHsKICAgICAgICAgICAgZm9yZWFjaCAodmFyIGt2IGluIGluc3QpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHRhcmdldFtrdi5LZXldID0ga3YuVmFsdWU7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGJvZHkgIT0gbnVsbCkKICAgICAgICB7CiAgICAgICAgICAgIGZvcmVhY2ggKHZhciBrdiBpbiBib2R5KQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICB0YXJnZXRba3YuS2V5XSA9IGt2LlZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHRhcmdldFsiY2hpbGRDb21wbGV0ZWQiXSA9IHRydWU7CiAgICAgICAgTG9nSW5mb3JtYXRpb24oIlBhcmVudFRvQ2hpbGRTdWJGbG93TWFwcGluZzogbWVyZ2VkIGNoaWxkIG91dHB1dCIpOwogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IG1lcmdlZCB9KTsKICAgIH0KfQo=" + } + }, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "auto-parent-to-completed", + "target": "parent-completed", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Parent Completed" + }, + { + "language": "tr-TR", + "label": "Otomatik Ebeveyn Tamamlandi" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "parent-completed", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Parent Completed" + }, + { + "language": "tr-TR", + "label": "Ebeveyn Tamamlandi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + }, + { + "key": "parent-cancelled", + "stateType": 3, + "subType": 3, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Parent Cancelled" + }, + { + "language": "tr-TR", + "label": "Ebeveyn Iptal" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/task-execution/src/AlwaysTrueRule.csx b/core/Workflows/task-execution/src/AlwaysTrueRule.csx new file mode 100644 index 0000000..3d08a0f --- /dev/null +++ b/core/Workflows/task-execution/src/AlwaysTrueRule.csx @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class AlwaysTrueRule : ScriptBase, IConditionMapping +{ + public Task Handler(ScriptContext context) + { + LogInformation("AlwaysTrueRule: returning true"); + return Task.FromResult(true); + } +} diff --git a/core/Workflows/task-execution/src/CrossWorkflowMapping.csx b/core/Workflows/task-execution/src/CrossWorkflowMapping.csx new file mode 100644 index 0000000..ea994ee --- /dev/null +++ b/core/Workflows/task-execution/src/CrossWorkflowMapping.csx @@ -0,0 +1,26 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class CrossWorkflowMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "httpTaskCompleted")) result.httpTaskCompleted = data.httpTaskCompleted; + if (HasProperty(data, "scriptProcessed")) result.scriptProcessed = data.scriptProcessed; + result.crossWorkflowCompleted = true; + result.crossWorkflowAt = DateTime.UtcNow.ToString("o"); + LogInformation("CrossWorkflowMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/task-execution/src/GetInstanceDataMapping.csx b/core/Workflows/task-execution/src/GetInstanceDataMapping.csx new file mode 100644 index 0000000..be75e33 --- /dev/null +++ b/core/Workflows/task-execution/src/GetInstanceDataMapping.csx @@ -0,0 +1,49 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; +using BBT.Workflow.Scripting.Functions; + +public class GetInstanceDataMapping : ScriptBase, IMapping +{ + public async Task InputHandler(WorkflowTask task, ScriptContext context) + { + var getDataTask = (task as GetInstanceDataTask)!; + var data = context.Instance.Data; + + if (HasProperty(data, "startedInstanceId")) + { + var instanceId = data.startedInstanceId?.ToString(); + getDataTask.SetInstance(instanceId); + LogInformation($"GetInstanceDataMapping InputHandler: target instanceId={instanceId}"); + } + + return new ScriptResponse(); + } + + public async Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + var taskResponse = context.Body; + var responseBody = taskResponse.data; + + dynamic result = new ExpandoObject(); + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "httpTaskCompleted")) result.httpTaskCompleted = data.httpTaskCompleted; + if (HasProperty(data, "processId")) result.processId = data.processId; + if (HasProperty(data, "scriptProcessed")) result.scriptProcessed = data.scriptProcessed; + if (HasProperty(data, "crossWorkflowCompleted")) result.crossWorkflowCompleted = data.crossWorkflowCompleted; + if (HasProperty(data, "startFlowCompleted")) result.startFlowCompleted = data.startFlowCompleted; + if (HasProperty(data, "startedInstanceId")) result.startedInstanceId = data.startedInstanceId; + + result.getInstanceDataCompleted = true; + result.getInstanceDataIsSuccess = taskResponse.isSuccess; + + if (responseBody != null) + result.remoteInstanceData = responseBody; + + LogInformation($"GetInstanceDataMapping OutputHandler: isSuccess={taskResponse.isSuccess}"); + return new ScriptResponse { Data = result }; + } +} diff --git a/core/Workflows/task-execution/src/HttpProcessMapping.csx b/core/Workflows/task-execution/src/HttpProcessMapping.csx new file mode 100644 index 0000000..7ed0086 --- /dev/null +++ b/core/Workflows/task-execution/src/HttpProcessMapping.csx @@ -0,0 +1,36 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; +using BBT.Workflow.Scripting.Functions; + +public class HttpProcessMapping : ScriptBase, IMapping +{ + public async Task InputHandler(WorkflowTask task, ScriptContext context) + { + var httpTask = (task as HttpTask)!; + var data = context.Instance.Data; + string baseUrl = GetConfigValue("MocklabBaseUrl"); + httpTask.Url = httpTask.Url.Replace("{MocklabBaseUrl}", baseUrl); + var body = new { source = "task-execution-test", timestamp = DateTime.UtcNow.ToString("o") }; + httpTask.SetBody(body); + return new ScriptResponse(); + } + + public async Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + var taskResponse = context.Body; + var responseBody = taskResponse.data; + dynamic result = new ExpandoObject(); + if (HasProperty(data, "testId")) result.testId = data.testId; + result.httpTaskCompleted = true; + result.httpStatusCode = taskResponse.statusCode; + result.httpIsSuccess = taskResponse.isSuccess; + if (responseBody != null && HasProperty(responseBody, "processId")) + result.processId = responseBody.processId; + LogInformation($"HttpProcessMapping completed, status={taskResponse.statusCode}"); + return new ScriptResponse { Data = result }; + } +} diff --git a/core/Workflows/task-execution/src/InitTaskTestMapping.csx b/core/Workflows/task-execution/src/InitTaskTestMapping.csx new file mode 100644 index 0000000..b1bad86 --- /dev/null +++ b/core/Workflows/task-execution/src/InitTaskTestMapping.csx @@ -0,0 +1,23 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class InitTaskTestMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + result.testId = Guid.NewGuid().ToString(); + result.startedAt = DateTime.UtcNow.ToString("o"); + LogInformation("InitTaskTestMapping: task execution test initialized"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/task-execution/src/ScriptProcessMapping.csx b/core/Workflows/task-execution/src/ScriptProcessMapping.csx new file mode 100644 index 0000000..01ef79c --- /dev/null +++ b/core/Workflows/task-execution/src/ScriptProcessMapping.csx @@ -0,0 +1,26 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class ScriptProcessMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "httpTaskCompleted")) result.httpTaskCompleted = data.httpTaskCompleted; + if (HasProperty(data, "processId")) result.processId = data.processId; + result.scriptProcessed = true; + result.scriptProcessedAt = DateTime.UtcNow.ToString("o"); + LogInformation("ScriptProcessMapping completed"); + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/task-execution/src/StartFlowMapping.csx b/core/Workflows/task-execution/src/StartFlowMapping.csx new file mode 100644 index 0000000..7da51ff --- /dev/null +++ b/core/Workflows/task-execution/src/StartFlowMapping.csx @@ -0,0 +1,48 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; +using BBT.Workflow.Scripting.Functions; + +public class StartFlowMapping : ScriptBase, IMapping +{ + public async Task InputHandler(WorkflowTask task, ScriptContext context) + { + var startTask = (task as StartTask)!; + var data = context.Instance.Data; + + var body = new + { + source = "task-execution-test", + parentInstanceId = context.Instance.Id + }; + startTask.SetBody(body); + + LogInformation("StartFlowMapping InputHandler: body set for target workflow"); + return new ScriptResponse(); + } + + public async Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + var taskResponse = context.Body; + var responseBody = taskResponse.data; + + dynamic result = new ExpandoObject(); + if (HasProperty(data, "testId")) result.testId = data.testId; + if (HasProperty(data, "httpTaskCompleted")) result.httpTaskCompleted = data.httpTaskCompleted; + if (HasProperty(data, "processId")) result.processId = data.processId; + if (HasProperty(data, "scriptProcessed")) result.scriptProcessed = data.scriptProcessed; + if (HasProperty(data, "crossWorkflowCompleted")) result.crossWorkflowCompleted = data.crossWorkflowCompleted; + + result.startFlowCompleted = true; + result.startFlowIsSuccess = taskResponse.isSuccess; + + if (responseBody != null && HasProperty(responseBody, "instanceId")) + result.startedInstanceId = responseBody.instanceId; + + LogInformation($"StartFlowMapping OutputHandler: isSuccess={taskResponse.isSuccess}"); + return new ScriptResponse { Data = result }; + } +} diff --git a/core/Workflows/task-execution/task-execution-test-workflow.json b/core/Workflows/task-execution/task-execution-test-workflow.json new file mode 100644 index 0000000..ded4160 --- /dev/null +++ b/core/Workflows/task-execution/task-execution-test-workflow.json @@ -0,0 +1,374 @@ +{ + "key": "task-execution-test-workflow", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "task-execution", + "http-task", + "script-task", + "start-flow-task", + "get-instance-data-task", + "task-ordering", + "on-entries" + ], + "attributes": { + "type": "F", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "Task Execution Integration Test" + }, + { + "language": "tr-TR", + "label": "Gorev Calistirma Entegrasyon Testi" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [], + "startTransition": { + "key": "start-task-execution", + "target": "http-task-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Task Execution Test" + }, + { + "language": "tr-TR", + "label": "Gorev Testini Baslat" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "task-exec-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/InitTaskTestMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIEluaXRUYXNrVGVzdE1hcHBpbmcgOiBTY3JpcHRCYXNlLCBJTWFwcGluZwp7CiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFdvcmtmbG93VGFzayB0YXNrLCBTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UoKSk7CiAgICB9CgogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICByZXN1bHQudGVzdElkID0gR3VpZC5OZXdHdWlkKCkuVG9TdHJpbmcoKTsKICAgICAgICByZXN1bHQuc3RhcnRlZEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CiAgICAgICAgTG9nSW5mb3JtYXRpb24oIkluaXRUYXNrVGVzdE1hcHBpbmc6IHRhc2sgZXhlY3V0aW9uIHRlc3QgaW5pdGlhbGl6ZWQiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ] + }, + "states": [ + { + "key": "http-task-state", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "HTTP Task State" + }, + { + "language": "tr-TR", + "label": "HTTP Gorev Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "http-process-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/HttpProcessMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nLkZ1bmN0aW9uczsKCnB1YmxpYyBjbGFzcyBIdHRwUHJvY2Vzc01hcHBpbmcgOiBTY3JpcHRCYXNlLCBJTWFwcGluZwp7CiAgICBwdWJsaWMgYXN5bmMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFdvcmtmbG93VGFzayB0YXNrLCBTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGh0dHBUYXNrID0gKHRhc2sgYXMgSHR0cFRhc2spITsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKICAgICAgICBzdHJpbmcgYmFzZVVybCA9IEdldENvbmZpZ1ZhbHVlKCJNb2NrbGFiQmFzZVVybCIpOwogICAgICAgIGh0dHBUYXNrLlVybCA9IGh0dHBUYXNrLlVybC5SZXBsYWNlKCJ7TW9ja2xhYkJhc2VVcmx9IiwgYmFzZVVybCk7CiAgICAgICAgdmFyIGJvZHkgPSBuZXcgeyBzb3VyY2UgPSAidGFzay1leGVjdXRpb24tdGVzdCIsIHRpbWVzdGFtcCA9IERhdGVUaW1lLlV0Y05vdy5Ub1N0cmluZygibyIpIH07CiAgICAgICAgaHR0cFRhc2suU2V0Qm9keShib2R5KTsKICAgICAgICByZXR1cm4gbmV3IFNjcmlwdFJlc3BvbnNlKCk7CiAgICB9CgogICAgcHVibGljIGFzeW5jIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwogICAgICAgIHZhciB0YXNrUmVzcG9uc2UgPSBjb250ZXh0LkJvZHk7CiAgICAgICAgdmFyIHJlc3BvbnNlQm9keSA9IHRhc2tSZXNwb25zZS5kYXRhOwogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKSByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CiAgICAgICAgcmVzdWx0Lmh0dHBUYXNrQ29tcGxldGVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQuaHR0cFN0YXR1c0NvZGUgPSB0YXNrUmVzcG9uc2Uuc3RhdHVzQ29kZTsKICAgICAgICByZXN1bHQuaHR0cElzU3VjY2VzcyA9IHRhc2tSZXNwb25zZS5pc1N1Y2Nlc3M7CiAgICAgICAgaWYgKHJlc3BvbnNlQm9keSAhPSBudWxsICYmIEhhc1Byb3BlcnR5KHJlc3BvbnNlQm9keSwgInByb2Nlc3NJZCIpKQogICAgICAgICAgICByZXN1bHQucHJvY2Vzc0lkID0gcmVzcG9uc2VCb2R5LnByb2Nlc3NJZDsKICAgICAgICBMb2dJbmZvcm1hdGlvbigkIkh0dHBQcm9jZXNzTWFwcGluZyBjb21wbGV0ZWQsIHN0YXR1cz17dGFza1Jlc3BvbnNlLnN0YXR1c0NvZGV9Iik7CiAgICAgICAgcmV0dXJuIG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfTsKICAgIH0KfQo=" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-script-processing", + "target": "script-processing-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Script Processing" + }, + { + "language": "tr-TR", + "label": "Script Isleme Otomatik Gecis" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "script-processing-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Script Processing State" + }, + { + "language": "tr-TR", + "label": "Script Isleme Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "task-exec-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ScriptProcessMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFNjcmlwdFByb2Nlc3NNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSkgcmVzdWx0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaHR0cFRhc2tDb21wbGV0ZWQiKSkgcmVzdWx0Lmh0dHBUYXNrQ29tcGxldGVkID0gZGF0YS5odHRwVGFza0NvbXBsZXRlZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInByb2Nlc3NJZCIpKSByZXN1bHQucHJvY2Vzc0lkID0gZGF0YS5wcm9jZXNzSWQ7CiAgICAgICAgcmVzdWx0LnNjcmlwdFByb2Nlc3NlZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LnNjcmlwdFByb2Nlc3NlZEF0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CiAgICAgICAgTG9nSW5mb3JtYXRpb24oIlNjcmlwdFByb2Nlc3NNYXBwaW5nIGNvbXBsZXRlZCIpOwogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-cross-workflow", + "target": "cross-workflow-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Cross Workflow" + }, + { + "language": "tr-TR", + "label": "Capraz Is Akisi Otomatik Gecis" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "cross-workflow-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Cross Workflow State" + }, + { + "language": "tr-TR", + "label": "Capraz Is Akisi Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "task-exec-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/CrossWorkflowMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIENyb3NzV29ya2Zsb3dNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlKCkpOwogICAgfQoKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBPdXRwdXRIYW5kbGVyKFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSkgcmVzdWx0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaHR0cFRhc2tDb21wbGV0ZWQiKSkgcmVzdWx0Lmh0dHBUYXNrQ29tcGxldGVkID0gZGF0YS5odHRwVGFza0NvbXBsZXRlZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInNjcmlwdFByb2Nlc3NlZCIpKSByZXN1bHQuc2NyaXB0UHJvY2Vzc2VkID0gZGF0YS5zY3JpcHRQcm9jZXNzZWQ7CiAgICAgICAgcmVzdWx0LmNyb3NzV29ya2Zsb3dDb21wbGV0ZWQgPSB0cnVlOwogICAgICAgIHJlc3VsdC5jcm9zc1dvcmtmbG93QXQgPSBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoIm8iKTsKICAgICAgICBMb2dJbmZvcm1hdGlvbigiQ3Jvc3NXb3JrZmxvd01hcHBpbmcgY29tcGxldGVkIik7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH0pOwogICAgfQp9Cg==" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-start-flow", + "target": "start-flow-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Start Flow" + }, + { + "language": "tr-TR", + "label": "Flow Baslatma Otomatik Gecis" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "start-flow-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Start Flow State (StartTask type 11)" + }, + { + "language": "tr-TR", + "label": "Flow Baslatma Durumu (StartTask tip 11)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "start-flow-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/StartFlowMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nLkZ1bmN0aW9uczsKCnB1YmxpYyBjbGFzcyBTdGFydEZsb3dNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIGFzeW5jIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBzdGFydFRhc2sgPSAodGFzayBhcyBTdGFydFRhc2spITsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKCiAgICAgICAgdmFyIGJvZHkgPSBuZXcKICAgICAgICB7CiAgICAgICAgICAgIHNvdXJjZSA9ICJ0YXNrLWV4ZWN1dGlvbi10ZXN0IiwKICAgICAgICAgICAgcGFyZW50SW5zdGFuY2VJZCA9IGNvbnRleHQuSW5zdGFuY2UuSWQKICAgICAgICB9OwogICAgICAgIHN0YXJ0VGFzay5TZXRCb2R5KGJvZHkpOwoKICAgICAgICBMb2dJbmZvcm1hdGlvbigiU3RhcnRGbG93TWFwcGluZyBJbnB1dEhhbmRsZXI6IGJvZHkgc2V0IGZvciB0YXJnZXQgd29ya2Zsb3ciKTsKICAgICAgICByZXR1cm4gbmV3IFNjcmlwdFJlc3BvbnNlKCk7CiAgICB9CgogICAgcHVibGljIGFzeW5jIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwogICAgICAgIHZhciB0YXNrUmVzcG9uc2UgPSBjb250ZXh0LkJvZHk7CiAgICAgICAgdmFyIHJlc3BvbnNlQm9keSA9IHRhc2tSZXNwb25zZS5kYXRhOwoKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSkgcmVzdWx0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaHR0cFRhc2tDb21wbGV0ZWQiKSkgcmVzdWx0Lmh0dHBUYXNrQ29tcGxldGVkID0gZGF0YS5odHRwVGFza0NvbXBsZXRlZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInByb2Nlc3NJZCIpKSByZXN1bHQucHJvY2Vzc0lkID0gZGF0YS5wcm9jZXNzSWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJzY3JpcHRQcm9jZXNzZWQiKSkgcmVzdWx0LnNjcmlwdFByb2Nlc3NlZCA9IGRhdGEuc2NyaXB0UHJvY2Vzc2VkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiY3Jvc3NXb3JrZmxvd0NvbXBsZXRlZCIpKSByZXN1bHQuY3Jvc3NXb3JrZmxvd0NvbXBsZXRlZCA9IGRhdGEuY3Jvc3NXb3JrZmxvd0NvbXBsZXRlZDsKCiAgICAgICAgcmVzdWx0LnN0YXJ0Rmxvd0NvbXBsZXRlZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LnN0YXJ0Rmxvd0lzU3VjY2VzcyA9IHRhc2tSZXNwb25zZS5pc1N1Y2Nlc3M7CgogICAgICAgIGlmIChyZXNwb25zZUJvZHkgIT0gbnVsbCAmJiBIYXNQcm9wZXJ0eShyZXNwb25zZUJvZHksICJpbnN0YW5jZUlkIikpCiAgICAgICAgICAgIHJlc3VsdC5zdGFydGVkSW5zdGFuY2VJZCA9IHJlc3BvbnNlQm9keS5pbnN0YW5jZUlkOwoKICAgICAgICBMb2dJbmZvcm1hdGlvbigkIlN0YXJ0Rmxvd01hcHBpbmcgT3V0cHV0SGFuZGxlcjogaXNTdWNjZXNzPXt0YXNrUmVzcG9uc2UuaXNTdWNjZXNzfSIpOwogICAgICAgIHJldHVybiBuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH07CiAgICB9Cn0K" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-get-instance-data", + "target": "get-instance-data-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Get Instance Data" + }, + { + "language": "tr-TR", + "label": "Instance Data Alma Otomatik Gecis" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "get-instance-data-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Get Instance Data State (GetInstanceDataTask type 13)" + }, + { + "language": "tr-TR", + "label": "Instance Data Alma Durumu (GetInstanceDataTask tip 13)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "get-instance-data-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/GetInstanceDataMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nLkZ1bmN0aW9uczsKCnB1YmxpYyBjbGFzcyBHZXRJbnN0YW5jZURhdGFNYXBwaW5nIDogU2NyaXB0QmFzZSwgSU1hcHBpbmcKewogICAgcHVibGljIGFzeW5jIFRhc2s8U2NyaXB0UmVzcG9uc2U+IElucHV0SGFuZGxlcihXb3JrZmxvd1Rhc2sgdGFzaywgU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBnZXREYXRhVGFzayA9ICh0YXNrIGFzIEdldEluc3RhbmNlRGF0YVRhc2spITsKICAgICAgICB2YXIgZGF0YSA9IGNvbnRleHQuSW5zdGFuY2UuRGF0YTsKCiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJzdGFydGVkSW5zdGFuY2VJZCIpKQogICAgICAgIHsKICAgICAgICAgICAgdmFyIGluc3RhbmNlSWQgPSBkYXRhLnN0YXJ0ZWRJbnN0YW5jZUlkPy5Ub1N0cmluZygpOwogICAgICAgICAgICBnZXREYXRhVGFzay5TZXRJbnN0YW5jZShpbnN0YW5jZUlkKTsKICAgICAgICAgICAgTG9nSW5mb3JtYXRpb24oJCJHZXRJbnN0YW5jZURhdGFNYXBwaW5nIElucHV0SGFuZGxlcjogdGFyZ2V0IGluc3RhbmNlSWQ9e2luc3RhbmNlSWR9Iik7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gbmV3IFNjcmlwdFJlc3BvbnNlKCk7CiAgICB9CgogICAgcHVibGljIGFzeW5jIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwogICAgICAgIHZhciB0YXNrUmVzcG9uc2UgPSBjb250ZXh0LkJvZHk7CiAgICAgICAgdmFyIHJlc3BvbnNlQm9keSA9IHRhc2tSZXNwb25zZS5kYXRhOwoKICAgICAgICBkeW5hbWljIHJlc3VsdCA9IG5ldyBFeHBhbmRvT2JqZWN0KCk7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSkgcmVzdWx0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaHR0cFRhc2tDb21wbGV0ZWQiKSkgcmVzdWx0Lmh0dHBUYXNrQ29tcGxldGVkID0gZGF0YS5odHRwVGFza0NvbXBsZXRlZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInByb2Nlc3NJZCIpKSByZXN1bHQucHJvY2Vzc0lkID0gZGF0YS5wcm9jZXNzSWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJzY3JpcHRQcm9jZXNzZWQiKSkgcmVzdWx0LnNjcmlwdFByb2Nlc3NlZCA9IGRhdGEuc2NyaXB0UHJvY2Vzc2VkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiY3Jvc3NXb3JrZmxvd0NvbXBsZXRlZCIpKSByZXN1bHQuY3Jvc3NXb3JrZmxvd0NvbXBsZXRlZCA9IGRhdGEuY3Jvc3NXb3JrZmxvd0NvbXBsZXRlZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInN0YXJ0Rmxvd0NvbXBsZXRlZCIpKSByZXN1bHQuc3RhcnRGbG93Q29tcGxldGVkID0gZGF0YS5zdGFydEZsb3dDb21wbGV0ZWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJzdGFydGVkSW5zdGFuY2VJZCIpKSByZXN1bHQuc3RhcnRlZEluc3RhbmNlSWQgPSBkYXRhLnN0YXJ0ZWRJbnN0YW5jZUlkOwoKICAgICAgICByZXN1bHQuZ2V0SW5zdGFuY2VEYXRhQ29tcGxldGVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQuZ2V0SW5zdGFuY2VEYXRhSXNTdWNjZXNzID0gdGFza1Jlc3BvbnNlLmlzU3VjY2VzczsKCiAgICAgICAgaWYgKHJlc3BvbnNlQm9keSAhPSBudWxsKQogICAgICAgICAgICByZXN1bHQucmVtb3RlSW5zdGFuY2VEYXRhID0gcmVzcG9uc2VCb2R5OwoKICAgICAgICBMb2dJbmZvcm1hdGlvbigkIkdldEluc3RhbmNlRGF0YU1hcHBpbmcgT3V0cHV0SGFuZGxlcjogaXNTdWNjZXNzPXt0YXNrUmVzcG9uc2UuaXNTdWNjZXNzfSIpOwogICAgICAgIHJldHVybiBuZXcgU2NyaXB0UmVzcG9uc2UgeyBEYXRhID0gcmVzdWx0IH07CiAgICB9Cn0K" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "auto-to-completed", + "target": "completed-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Completed" + }, + { + "language": "tr-TR", + "label": "Tamamlanmaya Otomatik Gecis" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "completed-state", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Completed State" + }, + { + "language": "tr-TR", + "label": "Tamamlandi Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/task-execution/task-target-workflow.json b/core/Workflows/task-execution/task-target-workflow.json new file mode 100644 index 0000000..7a1f9f3 --- /dev/null +++ b/core/Workflows/task-execution/task-target-workflow.json @@ -0,0 +1,113 @@ +{ + "key": "task-target-workflow", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "task-execution", + "target-workflow" + ], + "attributes": { + "type": "F", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "Task Execution Target Workflow" + }, + { + "language": "tr-TR", + "label": "Gorev Calistirma Hedef Is Akisi" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [], + "startTransition": { + "key": "start-target", + "target": "target-initial", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Target" + }, + { + "language": "tr-TR", + "label": "Hedefi Baslat" + } + ], + "onExecutionTasks": [] + }, + "states": [ + { + "key": "target-initial", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Target Initial" + }, + { + "language": "tr-TR", + "label": "Hedef Baslangic" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "auto-complete-target", + "target": "target-completed", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto Complete Target" + }, + { + "language": "tr-TR", + "label": "Otomatik Tamamla" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "target-completed", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Target Completed" + }, + { + "language": "tr-TR", + "label": "Hedef Tamamlandi" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/version-consistency/src/AlwaysTrueRule.csx b/core/Workflows/version-consistency/src/AlwaysTrueRule.csx new file mode 100644 index 0000000..6c63cb8 --- /dev/null +++ b/core/Workflows/version-consistency/src/AlwaysTrueRule.csx @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class AlwaysTrueRule : ScriptBase, IConditionMapping +{ + public Task Handler(ScriptContext context) + { + return Task.FromResult(true); + } +} diff --git a/core/Workflows/version-consistency/src/InitVersionMapping.csx b/core/Workflows/version-consistency/src/InitVersionMapping.csx new file mode 100644 index 0000000..e481ae2 --- /dev/null +++ b/core/Workflows/version-consistency/src/InitVersionMapping.csx @@ -0,0 +1,29 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class InitVersionMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) + result.testId = data.testId; + + result.initialized = true; + result.initAt = DateTime.UtcNow.ToString("o"); + + LogInformation("InitVersionMapping completed - version consistency test initialized"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/version-consistency/src/ReviewMapping.csx b/core/Workflows/version-consistency/src/ReviewMapping.csx new file mode 100644 index 0000000..73b81f8 --- /dev/null +++ b/core/Workflows/version-consistency/src/ReviewMapping.csx @@ -0,0 +1,33 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class ReviewMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) + result.testId = data.testId; + if (HasProperty(data, "initialized")) + result.initialized = data.initialized; + if (HasProperty(data, "initAt")) + result.initAt = data.initAt; + + result.reviewExecuted = true; + result.reviewAt = DateTime.UtcNow.ToString("o"); + + LogInformation("ReviewMapping completed - v2 review state entered"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/version-consistency/src/V1CompletedMapping.csx b/core/Workflows/version-consistency/src/V1CompletedMapping.csx new file mode 100644 index 0000000..7231c21 --- /dev/null +++ b/core/Workflows/version-consistency/src/V1CompletedMapping.csx @@ -0,0 +1,34 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class V1CompletedMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) + result.testId = data.testId; + if (HasProperty(data, "initialized")) + result.initialized = data.initialized; + if (HasProperty(data, "initAt")) + result.initAt = data.initAt; + + result.v1Completed = true; + result.completedAt = DateTime.UtcNow.ToString("o"); + result.completedByVersion = "1.0.0"; + + LogInformation("V1CompletedMapping completed - v1 path finalized"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/version-consistency/src/V2CompletedMapping.csx b/core/Workflows/version-consistency/src/V2CompletedMapping.csx new file mode 100644 index 0000000..9b5d99b --- /dev/null +++ b/core/Workflows/version-consistency/src/V2CompletedMapping.csx @@ -0,0 +1,38 @@ +using System; +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; +using BBT.Workflow.Definitions; + +public class V2CompletedMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + var data = context.Instance.Data; + dynamic result = new ExpandoObject(); + + if (HasProperty(data, "testId")) + result.testId = data.testId; + if (HasProperty(data, "initialized")) + result.initialized = data.initialized; + if (HasProperty(data, "initAt")) + result.initAt = data.initAt; + if (HasProperty(data, "reviewExecuted")) + result.reviewExecuted = data.reviewExecuted; + if (HasProperty(data, "reviewAt")) + result.reviewAt = data.reviewAt; + + result.v2Completed = true; + result.completedAt = DateTime.UtcNow.ToString("o"); + result.completedByVersion = "2.0.0"; + + LogInformation("V2CompletedMapping completed - v2 path finalized"); + + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/version-consistency/version-consistency-test-workflow-v2.json b/core/Workflows/version-consistency/version-consistency-test-workflow-v2.json new file mode 100644 index 0000000..d496415 --- /dev/null +++ b/core/Workflows/version-consistency/version-consistency-test-workflow-v2.json @@ -0,0 +1,234 @@ +{ + "key": "version-consistency-test-workflow", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "2.0.0", + "tags": [ + "integration-test", + "version-consistency", + "version-v2", + "review-state" + ], + "attributes": { + "type": "F", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "Version Consistency Test (v2.0.0)" + }, + { + "language": "tr-TR", + "label": "Versiyon Tutarliligi Testi (v2.0.0)" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [], + "startTransition": { + "key": "start-version-test", + "target": "init-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Version Test" + }, + { + "language": "tr-TR", + "label": "Versiyon Testini Baslat" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "version-consistency-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/InitVersionMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIEluaXRWZXJzaW9uTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKQogICAgICAgICAgICByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CgogICAgICAgIHJlc3VsdC5pbml0aWFsaXplZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LmluaXRBdCA9IERhdGVUaW1lLlV0Y05vdy5Ub1N0cmluZygibyIpOwoKICAgICAgICBMb2dJbmZvcm1hdGlvbigiSW5pdFZlcnNpb25NYXBwaW5nIGNvbXBsZXRlZCAtIHZlcnNpb24gY29uc2lzdGVuY3kgdGVzdCBpbml0aWFsaXplZCIpOwoKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ] + }, + "states": [ + { + "key": "init-state", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Init State" + }, + { + "language": "tr-TR", + "label": "Baslangic Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "auto-to-processing", + "target": "processing-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Processing" + }, + { + "language": "tr-TR", + "label": "Isleme Otomatik Gecis" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQodHJ1ZSk7CiAgICB9Cn0K" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "processing-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Processing State" + }, + { + "language": "tr-TR", + "label": "Isleme Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "complete-processing", + "target": "review-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Complete Processing" + }, + { + "language": "tr-TR", + "label": "Islemi Tamamla" + } + ], + "onExecutionTasks": [] + } + ] + }, + { + "key": "review-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Review State (v2 only)" + }, + { + "language": "tr-TR", + "label": "Inceleme Durumu (sadece v2)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "version-consistency-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/ReviewMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFJldmlld01hcHBpbmcgOiBTY3JpcHRCYXNlLCBJTWFwcGluZwp7CiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFdvcmtmbG93VGFzayB0YXNrLCBTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UoKSk7CiAgICB9CgogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBkYXRhID0gY29udGV4dC5JbnN0YW5jZS5EYXRhOwogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKCiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJ0ZXN0SWQiKSkKICAgICAgICAgICAgcmVzdWx0LnRlc3RJZCA9IGRhdGEudGVzdElkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaW5pdGlhbGl6ZWQiKSkKICAgICAgICAgICAgcmVzdWx0LmluaXRpYWxpemVkID0gZGF0YS5pbml0aWFsaXplZDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgImluaXRBdCIpKQogICAgICAgICAgICByZXN1bHQuaW5pdEF0ID0gZGF0YS5pbml0QXQ7CgogICAgICAgIHJlc3VsdC5yZXZpZXdFeGVjdXRlZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LnJldmlld0F0ID0gRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKCJvIik7CgogICAgICAgIExvZ0luZm9ybWF0aW9uKCJSZXZpZXdNYXBwaW5nIGNvbXBsZXRlZCAtIHYyIHJldmlldyBzdGF0ZSBlbnRlcmVkIik7CgogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ], + "onExits": [], + "transitions": [ + { + "key": "approve-review", + "target": "completed-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Approve Review" + }, + { + "language": "tr-TR", + "label": "Incelemeyi Onayla" + } + ], + "onExecutionTasks": [] + } + ] + }, + { + "key": "completed-state", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Completed (v2)" + }, + { + "language": "tr-TR", + "label": "Tamamlandi (v2)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "version-consistency-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/V2CompletedMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFYyQ29tcGxldGVkTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKQogICAgICAgICAgICByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJpbml0aWFsaXplZCIpKQogICAgICAgICAgICByZXN1bHQuaW5pdGlhbGl6ZWQgPSBkYXRhLmluaXRpYWxpemVkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaW5pdEF0IikpCiAgICAgICAgICAgIHJlc3VsdC5pbml0QXQgPSBkYXRhLmluaXRBdDsKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInJldmlld0V4ZWN1dGVkIikpCiAgICAgICAgICAgIHJlc3VsdC5yZXZpZXdFeGVjdXRlZCA9IGRhdGEucmV2aWV3RXhlY3V0ZWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJyZXZpZXdBdCIpKQogICAgICAgICAgICByZXN1bHQucmV2aWV3QXQgPSBkYXRhLnJldmlld0F0OwoKICAgICAgICByZXN1bHQudjJDb21wbGV0ZWQgPSB0cnVlOwogICAgICAgIHJlc3VsdC5jb21wbGV0ZWRBdCA9IERhdGVUaW1lLlV0Y05vdy5Ub1N0cmluZygibyIpOwogICAgICAgIHJlc3VsdC5jb21wbGV0ZWRCeVZlcnNpb24gPSAiMi4wLjAiOwoKICAgICAgICBMb2dJbmZvcm1hdGlvbigiVjJDb21wbGV0ZWRNYXBwaW5nIGNvbXBsZXRlZCAtIHYyIHBhdGggZmluYWxpemVkIik7CgogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/version-consistency/version-consistency-test-workflow.json b/core/Workflows/version-consistency/version-consistency-test-workflow.json new file mode 100644 index 0000000..020f72b --- /dev/null +++ b/core/Workflows/version-consistency/version-consistency-test-workflow.json @@ -0,0 +1,180 @@ +{ + "key": "version-consistency-test-workflow", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "version-consistency", + "version-v1" + ], + "attributes": { + "type": "F", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "Version Consistency Test (v1.0.0)" + }, + { + "language": "tr-TR", + "label": "Versiyon Tutarliligi Testi (v1.0.0)" + } + ], + "functions": [], + "features": [], + "extensions": [], + "sharedTransitions": [], + "startTransition": { + "key": "start-version-test", + "target": "init-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start Version Test" + }, + { + "language": "tr-TR", + "label": "Versiyon Testini Baslat" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "version-consistency-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/InitVersionMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIEluaXRWZXJzaW9uTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKQogICAgICAgICAgICByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CgogICAgICAgIHJlc3VsdC5pbml0aWFsaXplZCA9IHRydWU7CiAgICAgICAgcmVzdWx0LmluaXRBdCA9IERhdGVUaW1lLlV0Y05vdy5Ub1N0cmluZygibyIpOwoKICAgICAgICBMb2dJbmZvcm1hdGlvbigiSW5pdFZlcnNpb25NYXBwaW5nIGNvbXBsZXRlZCAtIHZlcnNpb24gY29uc2lzdGVuY3kgdGVzdCBpbml0aWFsaXplZCIpOwoKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ] + }, + "states": [ + { + "key": "init-state", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Init State" + }, + { + "language": "tr-TR", + "label": "Baslangic Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "auto-to-processing", + "target": "processing-state", + "triggerType": 1, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Auto to Processing" + }, + { + "language": "tr-TR", + "label": "Isleme Otomatik Gecis" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQodHJ1ZSk7CiAgICB9Cn0K" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "processing-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Processing State" + }, + { + "language": "tr-TR", + "label": "Isleme Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "complete-processing", + "target": "completed-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Complete Processing" + }, + { + "language": "tr-TR", + "label": "Islemi Tamamla" + } + ], + "onExecutionTasks": [] + } + ] + }, + { + "key": "completed-state", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Completed (v1)" + }, + { + "language": "tr-TR", + "label": "Tamamlandi (v1)" + } + ], + "view": null, + "subFlow": null, + "onEntries": [ + { + "order": 1, + "task": { + "key": "version-consistency-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/V1CompletedMapping.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRHluYW1pYzsKdXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKdXNpbmcgQkJULldvcmtmbG93LkRlZmluaXRpb25zOwoKcHVibGljIGNsYXNzIFYxQ29tcGxldGVkTWFwcGluZyA6IFNjcmlwdEJhc2UsIElNYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPFNjcmlwdFJlc3BvbnNlPiBJbnB1dEhhbmRsZXIoV29ya2Zsb3dUYXNrIHRhc2ssIFNjcmlwdENvbnRleHQgY29udGV4dCkKICAgIHsKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSgpKTsKICAgIH0KCiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gT3V0cHV0SGFuZGxlcihTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgdmFyIGRhdGEgPSBjb250ZXh0Lkluc3RhbmNlLkRhdGE7CiAgICAgICAgZHluYW1pYyByZXN1bHQgPSBuZXcgRXhwYW5kb09iamVjdCgpOwoKICAgICAgICBpZiAoSGFzUHJvcGVydHkoZGF0YSwgInRlc3RJZCIpKQogICAgICAgICAgICByZXN1bHQudGVzdElkID0gZGF0YS50ZXN0SWQ7CiAgICAgICAgaWYgKEhhc1Byb3BlcnR5KGRhdGEsICJpbml0aWFsaXplZCIpKQogICAgICAgICAgICByZXN1bHQuaW5pdGlhbGl6ZWQgPSBkYXRhLmluaXRpYWxpemVkOwogICAgICAgIGlmIChIYXNQcm9wZXJ0eShkYXRhLCAiaW5pdEF0IikpCiAgICAgICAgICAgIHJlc3VsdC5pbml0QXQgPSBkYXRhLmluaXRBdDsKCiAgICAgICAgcmVzdWx0LnYxQ29tcGxldGVkID0gdHJ1ZTsKICAgICAgICByZXN1bHQuY29tcGxldGVkQXQgPSBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoIm8iKTsKICAgICAgICByZXN1bHQuY29tcGxldGVkQnlWZXJzaW9uID0gIjEuMC4wIjsKCiAgICAgICAgTG9nSW5mb3JtYXRpb24oIlYxQ29tcGxldGVkTWFwcGluZyBjb21wbGV0ZWQgLSB2MSBwYXRoIGZpbmFsaXplZCIpOwoKICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KG5ldyBTY3JpcHRSZXNwb25zZSB7IERhdGEgPSByZXN1bHQgfSk7CiAgICB9Cn0K" + } + } + ], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/core/Workflows/view-function-extension/src/AlwaysTrueRule.csx b/core/Workflows/view-function-extension/src/AlwaysTrueRule.csx new file mode 100644 index 0000000..37de1d3 --- /dev/null +++ b/core/Workflows/view-function-extension/src/AlwaysTrueRule.csx @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class AlwaysTrueRule : ScriptBase, IConditionMapping +{ + public async Task Handler(ScriptContext context) + { + LogInformation("AlwaysTrueRule: returning true"); + return true; + } +} diff --git a/core/Workflows/view-function-extension/src/InitVfeMapping.csx b/core/Workflows/view-function-extension/src/InitVfeMapping.csx new file mode 100644 index 0000000..133abd9 --- /dev/null +++ b/core/Workflows/view-function-extension/src/InitVfeMapping.csx @@ -0,0 +1,18 @@ +using System.Dynamic; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class InitVfeMapping : ScriptBase, IMapping +{ + public Task InputHandler(WorkflowTask task, ScriptContext context) + { + return Task.FromResult(new ScriptResponse()); + } + + public Task OutputHandler(ScriptContext context) + { + dynamic result = new ExpandoObject(); + result.vfeTestStarted = true; + return Task.FromResult(new ScriptResponse { Data = result }); + } +} diff --git a/core/Workflows/view-function-extension/src/WebPlatformRule.csx b/core/Workflows/view-function-extension/src/WebPlatformRule.csx new file mode 100644 index 0000000..5c6ecf2 --- /dev/null +++ b/core/Workflows/view-function-extension/src/WebPlatformRule.csx @@ -0,0 +1,20 @@ +using System; +using System.Threading.Tasks; +using BBT.Workflow.Scripting; + +public class WebPlatformRule : ScriptBase, IConditionMapping +{ + public Task Handler(ScriptContext context) + { + var platform = ""; + var headers = context.Headers; + if (headers != null && HasProperty(headers, "platform")) + platform = Convert.ToString(headers.platform) ?? ""; + + var isWeb = string.Equals(platform, "web", StringComparison.OrdinalIgnoreCase); + LogInformation($"WebPlatformRule: platform={platform}, isWeb={isWeb}"); + + // Integration tests: treat as satisfied so flows pass without a client header. + return Task.FromResult(true); + } +} diff --git a/core/Workflows/view-function-extension/view-function-extension-test-workflow.json b/core/Workflows/view-function-extension/view-function-extension-test-workflow.json new file mode 100644 index 0000000..ee0280a --- /dev/null +++ b/core/Workflows/view-function-extension/view-function-extension-test-workflow.json @@ -0,0 +1,299 @@ +{ + "key": "view-function-extension-test-workflow", + "flow": "sys-flows", + "flowVersion": "1.0.0", + "domain": "core", + "version": "1.0.0", + "tags": [ + "integration-test", + "view", + "function", + "extension", + "json-view", + "html-view", + "markdown-view", + "rule-based-view", + "display-modes", + "single-task-function", + "multi-task-function", + "output-handler", + "global-extension", + "requested-extension", + "features" + ], + "attributes": { + "type": "F", + "timeout": null, + "labels": [ + { + "language": "en-US", + "label": "View, Function and Extension Integration Test" + }, + { + "language": "tr-TR", + "label": "Gorunum Fonksiyon ve Uzantı Entegrasyon Testi" + } + ], + "functions": [ + { + "key": "single-task-function", + "domain": "core", + "version": "1.0.0", + "flow": "sys-functions" + }, + { + "key": "multi-task-function", + "domain": "core", + "version": "1.0.0", + "flow": "sys-functions" + } + ], + "features": [ + { + "key": "global-extension", + "domain": "core", + "version": "1.0.0", + "flow": "sys-extensions" + } + ], + "extensions": [ + { + "key": "global-extension", + "domain": "core", + "version": "1.0.0", + "flow": "sys-extensions" + }, + { + "key": "requested-extension", + "domain": "core", + "version": "1.0.0", + "flow": "sys-extensions" + } + ], + "sharedTransitions": [], + "startTransition": { + "key": "start-view-function-extension-test", + "target": "view-test-state", + "triggerType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Start View and Function Extension Test" + }, + { + "language": "tr-TR", + "label": "Gorunum Fonksiyon Uzantı Testini Baslat" + } + ], + "onExecutionTasks": [ + { + "order": 1, + "task": { + "key": "vfe-script-task", + "domain": "core", + "version": "1.0.0", + "flow": "sys-tasks" + }, + "mapping": { + "location": "./src/InitVfeMapping.csx", + "code": "dXNpbmcgU3lzdGVtLkR5bmFtaWM7CnVzaW5nIFN5c3RlbS5UaHJlYWRpbmcuVGFza3M7CnVzaW5nIEJCVC5Xb3JrZmxvdy5TY3JpcHRpbmc7CgpwdWJsaWMgY2xhc3MgSW5pdFZmZU1hcHBpbmcgOiBTY3JpcHRCYXNlLCBJTWFwcGluZwp7CiAgICBwdWJsaWMgVGFzazxTY3JpcHRSZXNwb25zZT4gSW5wdXRIYW5kbGVyKFdvcmtmbG93VGFzayB0YXNrLCBTY3JpcHRDb250ZXh0IGNvbnRleHQpCiAgICB7CiAgICAgICAgcmV0dXJuIFRhc2suRnJvbVJlc3VsdChuZXcgU2NyaXB0UmVzcG9uc2UoKSk7CiAgICB9CgogICAgcHVibGljIFRhc2s8U2NyaXB0UmVzcG9uc2U+IE91dHB1dEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIGR5bmFtaWMgcmVzdWx0ID0gbmV3IEV4cGFuZG9PYmplY3QoKTsKICAgICAgICByZXN1bHQudmZlVGVzdFN0YXJ0ZWQgPSB0cnVlOwogICAgICAgIHJldHVybiBUYXNrLkZyb21SZXN1bHQobmV3IFNjcmlwdFJlc3BvbnNlIHsgRGF0YSA9IHJlc3VsdCB9KTsKICAgIH0KfQo=" + } + } + ] + }, + "states": [ + { + "key": "view-test-state", + "stateType": 1, + "subType": 0, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "JSON View State" + }, + { + "language": "tr-TR", + "label": "JSON Gorunum Durumu" + } + ], + "view": { + "view": { + "key": "json-view", + "domain": "core", + "version": "1.0.0", + "flow": "sys-views" + } + }, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "auto-to-multi-view", + "target": "multi-view-state", + "triggerType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Auto to Multi View (WebPlatformRule)" + }, + { + "language": "tr-TR", + "label": "Coklu Gorunume Otomatik Gecis (WebPlatformRule)" + } + ], + "rule": { + "location": "./src/WebPlatformRule.csx", + "code": "dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uVGhyZWFkaW5nLlRhc2tzOwp1c2luZyBCQlQuV29ya2Zsb3cuU2NyaXB0aW5nOwoKcHVibGljIGNsYXNzIFdlYlBsYXRmb3JtUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIHZhciBwbGF0Zm9ybSA9ICIiOwogICAgICAgIHZhciBoZWFkZXJzID0gY29udGV4dC5IZWFkZXJzOwogICAgICAgIGlmIChoZWFkZXJzICE9IG51bGwgJiYgSGFzUHJvcGVydHkoaGVhZGVycywgInBsYXRmb3JtIikpCiAgICAgICAgICAgIHBsYXRmb3JtID0gQ29udmVydC5Ub1N0cmluZyhoZWFkZXJzLnBsYXRmb3JtKSA/PyAiIjsKCiAgICAgICAgdmFyIGlzV2ViID0gc3RyaW5nLkVxdWFscyhwbGF0Zm9ybSwgIndlYiIsIFN0cmluZ0NvbXBhcmlzb24uT3JkaW5hbElnbm9yZUNhc2UpOwogICAgICAgIExvZ0luZm9ybWF0aW9uKCQiV2ViUGxhdGZvcm1SdWxlOiBwbGF0Zm9ybT17cGxhdGZvcm19LCBpc1dlYj17aXNXZWJ9Iik7CgogICAgICAgIC8vIEludGVncmF0aW9uIHRlc3RzOiB0cmVhdCBhcyBzYXRpc2ZpZWQgc28gZmxvd3MgcGFzcyB3aXRob3V0IGEgY2xpZW50IGhlYWRlci4KICAgICAgICByZXR1cm4gVGFzay5Gcm9tUmVzdWx0KHRydWUpOwogICAgfQp9Cg==" + }, + "onExecutionTasks": [] + }, + { + "key": "default-auto-fallback", + "target": "completed-state", + "triggerType": 1, + "triggerKind": 10, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Default Auto Fallback (AlwaysTrueRule)" + }, + { + "language": "tr-TR", + "label": "Varsayilan Otomatik Geri Donus (AlwaysTrueRule)" + } + ], + "rule": { + "location": "./src/AlwaysTrueRule.csx", + "code": "dXNpbmcgU3lzdGVtLlRocmVhZGluZy5UYXNrczsKdXNpbmcgQkJULldvcmtmbG93LlNjcmlwdGluZzsKCnB1YmxpYyBjbGFzcyBBbHdheXNUcnVlUnVsZSA6IFNjcmlwdEJhc2UsIElDb25kaXRpb25NYXBwaW5nCnsKICAgIHB1YmxpYyBhc3luYyBUYXNrPGJvb2w+IEhhbmRsZXIoU2NyaXB0Q29udGV4dCBjb250ZXh0KQogICAgewogICAgICAgIExvZ0luZm9ybWF0aW9uKCJBbHdheXNUcnVlUnVsZTogcmV0dXJuaW5nIHRydWUiKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KfQo=" + }, + "onExecutionTasks": [] + } + ] + }, + { + "key": "multi-view-state", + "stateType": 2, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "HTML View State" + }, + { + "language": "tr-TR", + "label": "HTML Gorunum Durumu" + } + ], + "view": { + "view": { + "key": "html-view", + "domain": "core", + "version": "1.0.0", + "flow": "sys-views" + } + }, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "manual-to-wizard", + "target": "wizard-state", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Continue to Wizard State" + }, + { + "language": "tr-TR", + "label": "Sihirbaz Durumuna Devam" + } + ], + "schema": null, + "view": null, + "mapping": null, + "onExecutionTasks": [] + } + ] + }, + { + "key": "wizard-state", + "stateType": 5, + "subType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Wizard State" + }, + { + "language": "tr-TR", + "label": "Sihirbaz Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [ + { + "key": "complete-with-markdown-view", + "target": "completed-state", + "triggerType": 0, + "versionStrategy": "Minor", + "labels": [ + { + "language": "en-US", + "label": "Complete with Markdown View" + }, + { + "language": "tr-TR", + "label": "Markdown Gorunumu ile Tamamla" + } + ], + "schema": null, + "view": { + "view": { + "key": "markdown-view", + "domain": "core", + "version": "1.0.0", + "flow": "sys-views" + } + }, + "mapping": null, + "onExecutionTasks": [] + } + ] + }, + { + "key": "completed-state", + "stateType": 3, + "subType": 1, + "versionStrategy": "Major", + "labels": [ + { + "language": "en-US", + "label": "Completed State" + }, + { + "language": "tr-TR", + "label": "Tamamlandi Durumu" + } + ], + "view": null, + "subFlow": null, + "onEntries": [], + "onExits": [], + "transitions": [] + } + ] + } +} \ No newline at end of file diff --git a/doc/integration-test-documentation.md b/doc/integration-test-documentation.md new file mode 100644 index 0000000..9ef439a --- /dev/null +++ b/doc/integration-test-documentation.md @@ -0,0 +1,1219 @@ +# vNext Runtime Integration Test Documentation + +Bu dokuman, `core` projesindeki tum integration test workflow'larini, icerdikleri bilesenleri ve her birinin hangi vNext ozelliklerini test ettigini detayli olarak aciklar. + +--- + +## Genel Bakis + +| # | Grup | Workflow | Test Edilen Ana Ozellikler | +|---|------|----------|---------------------------| +| 1 | Lifecycle & Transitions | `lifecycle-transitions-test-workflow` | State tipleri, transition tipleri, on-entries/exits, timer, cancel, **exit** (`attributes.exit`), **schedule iptal / timer reschedule**, **queryRoles** ve **transition rolleri** | +| 2 | SubFlow & SubProcess | `subflow-orchestration-parent` + child + grandchild | Parent-child-grandchild zinciri, parent shared transitions, **child shared transition**, **cancel cascade** (child/grandchild **cancelled** final state'leri), **effective state**, **updateData (SubFlow)** | +| 3 | Task Execution | `task-execution-test-workflow` + `task-target-workflow` | HTTP/Script/StartFlow/GetInstanceData task tipleri | +| 4 | Error Boundary | `error-boundary-test-workflow` | Retry, Ignore, **Rollback**, **Log**, **Notify** (action:4) aksiyonlari, retry policy, priority, **timeoutPolicy** (onTimeout), **errorHandlerRule** (errorTypes/errorCodes) | +| 5 | View, Function & Extension | `view-function-extension-test-workflow` | View tipleri, display modlari, function, extension, wizard state, **features** referansi | +| 6 | Schema & Data | `schema-data-test-workflow` | Master schema, transition schema, updateData, field roles | +| 7 | Instance Management | `instance-management-test-workflow` | Filtering, pagination, sorting, timeout, idempotent start, **subType 4/5/6** (suspended/busy/human) | +| 8 | Extended Tasks | `extended-tasks-test-workflow` | Dapr HTTP/Binding/Service/PubSub, notification, trigger-transition, subprocess, get-instances, human-task; Dapr bilesen konfigurasyonu | +| 9 | Flow Types | `core-flow-test` + `subprocess-flow-test` | **Core (C)** ve **SubProcess (P)** workflow tipleri | +| 10 | Version Consistency | `version-consistency-test-workflow` (v1.0.0 + v2.0.0) | Workflow versiyon degisiminde mevcut instance'larin kendi versiyonlariyla devam etmesi | + +--- + +## Bilesen Envanteri + +``` +core/ +├── Workflows/ (15 workflow - 13 mevcut + 2 yeni version-consistency) +├── Tasks/ (23 task - 22 mevcut + 1 yeni version-consistency) +├── Views/ (3 view) +├── Schemas/ (2 schema) +├── Functions/ (2 function) +├── Extensions/ (2 extension) +├── etc/dapr/components/ (Dapr binding ve pubsub YAML) +└── doc/ + └── integration-test-documentation.md +``` + +--- + +## Grup 1: Lifecycle & Transitions + +**Workflow:** `lifecycle-transitions-test-workflow` (type: F) + +**Amac:** Workflow yasam dongusu ve tum transition tiplerini test eder; ayrica **exit transition**, **zamanlayici schedule yonetimi** (manuel iptal ve `$self` ile reschedule), **workflow/state queryRoles** ve **transition bazli roller** senaryolarini kapsar. + +### Agac Yapisi + +``` +lifecycle-transitions-test-workflow (F) +│ +├── [workflow-level queryRoles] +│ └── test-viewer → allow +│ +├── [startTransition] start-lifecycle-test +│ └── onExecutionTasks: +│ └── script-task + InitializeDataMapping.csx +│ +├── [cancel] cancel-workflow → terminated-state +│ +├── [attributes.exit] exit-workflow → terminated-state +│ ├── triggerType: 0 (Manual) +│ ├── availableIn: initialize-state, processing-state, pre-complete-state +│ └── onExecutionTasks: +│ └── script-task + ExitMapping.csx (IMapping) +│ +├── initialize-state (Initial, stateType:1) +│ └── Transitions: +│ └── move-to-processing (Manual, triggerType:0) → processing-state +│ ├── mapping: ProcessTransitionMapping.csx (ITransitionMapping) +│ └── roles: test-operator (allow) +│ +├── processing-state (Intermediate, stateType:2) +│ ├── queryRoles: test-processor (allow), test-viewer (deny) +│ ├── onEntries: +│ │ └── script-task + ProcessEntryMapping.csx +│ ├── onExits: +│ │ └── script-task + ProcessExitMapping.csx +│ └── Transitions: +│ ├── auto-pass-transition (Auto, triggerType:1) → auto-passed-state +│ │ └── rule: TestPathPassRule.csx (testPath=="pass") +│ ├── auto-fail-transition (Auto, triggerType:1) → auto-failed-state +│ │ └── rule: TestPathFailRule.csx (testPath=="fail") +│ └── default-auto-transition (Auto, triggerType:1, triggerKind:10) → default-fallback-state +│ └── rule: AlwaysTrueRule.csx (varsayilan fallback) +│ +├── auto-passed-state (Intermediate, stateType:2) +│ └── Transitions: +│ ├── scheduled-timer-transition (Scheduled, triggerType:2) → timer-triggered-state +│ │ └── timer: ShortTimerMapping.csx (ITimerMapping, 10 saniye) +│ ├── cancel-schedule-manually (Manual, triggerType:0) → pre-complete-state +│ │ └── (zamanlayici schedule'ini manuel transition ile iptal senaryosu) +│ └── reschedule-timer (Manual, triggerType:0, target: $self) +│ └── (timer'i ayni state'te yeniden zamanlama senaryosu) +│ +├── timer-triggered-state (Intermediate, stateType:2) +│ ├── onEntries: +│ │ └── script-task + TimerEntryMapping.csx +│ └── Transitions: +│ └── auto-to-pre-complete (Auto, triggerType:1) → pre-complete-state +│ └── rule: AlwaysTrueRule.csx +│ +├── pre-complete-state (Intermediate, stateType:2) +│ └── Transitions: +│ └── complete-workflow (Manual, triggerType:0) → completed-state +│ └── roles: test-approver (allow), test-operator (deny) +│ +├── default-fallback-state (Intermediate, stateType:2) +│ └── Transitions: +│ └── fallback-to-complete (Auto, triggerType:1) → completed-state +│ └── rule: AlwaysTrueRule.csx +│ +├── auto-failed-state (Final/Error, stateType:3, subType:2) +├── completed-state (Final/Success, stateType:3, subType:1) +└── terminated-state (Final/Terminated, stateType:3, subType:3) +``` + +### Test Edilen Ozellikler + +| Ozellik | Nasil Test Edilir | Ilgili Eleman | +|---------|-------------------|---------------| +| State tipleri (Initial/Intermediate/Final) | 3 farkli stateType kullanilir | Tum state'ler | +| State alt tipleri (Success/Error/Terminated) | subType 1, 2, 3 kullanilir | auto-failed, completed, terminated | +| Manuel transition (triggerType:0) | Kullanici tetikli gecisler | move-to-processing, complete-workflow, cancel-schedule-manually, reschedule-timer | +| Otomatik transition (triggerType:1) | Rule bazli otomatik gecisler | auto-pass, auto-fail | +| Tamamlayici kurallar (complementary rules) | Ayni state'te zit kosullu auto transitions | TestPathPassRule + TestPathFailRule | +| Varsayilan otomatik gecis (triggerKind:10) | Hicbir rule eslesmezse fallback | default-auto-transition | +| Zamanlanmis transition (triggerType:2) | Timer ile gecis | scheduled-timer-transition | +| ITimerMapping | Timer suresi belirleme | ShortTimerMapping.csx | +| ITransitionMapping | Transition sirasinda data donusumu | ProcessTransitionMapping.csx | +| IConditionMapping | Kosul degerlendirme | TestPathPassRule, TestPathFailRule, AlwaysTrueRule | +| onEntries | State girisinde task calistirma | processing-state, timer-triggered-state | +| onExits | State cikisinda task calistirma | processing-state | +| startTransition onExecutionTasks | Workflow baslatilirken task calistirma | InitializeDataMapping.csx | +| Cancel transition | Workflow iptal mekanizmasi | cancel-workflow → terminated-state | +| **Exit transition (`attributes.exit`)** | Belirli state'lerde cikis; hedef terminated; IMapping ile exitExecuted | exit-workflow, ExitMapping.csx | +| **Schedule iptal (manuel)** | auto-passed-state'ten manuel gecisle timer beklemeden pre-complete | cancel-schedule-manually | +| **Timer reschedule ($self)** | Ayni state'te kalarak zamanlayiciyi yeniden baglama | reschedule-timer → $self | +| **queryRoles (workflow)** | authorize endpoint ile workflow datasi sorgu yetkisi | attributes.queryRoles, test-viewer | +| **queryRoles (state)** | State bazli allow/deny override | processing-state queryRoles | +| **Transition roles** | Manuel transition'da rol grant/deny | move-to-processing, complete-workflow | +| Version strategy (Major/Minor/Patch) | Farkli versiyonlama stratejileri | Cesitli transitions | +| Idempotent start | Ayni key ile tekrar baslatma | HTTP test dosyasinda | + +### HTTP Test Dosyasi (`lifecycle-transitions-test-workflow.http`) + +| Senaryo | Kisa Aciklama | +|---------|---------------| +| Happy / Fail / Default path | Mevcut lifecycle akislari | +| Idempotent start | Ayni key ile tekrar baslatma | +| Cancel | cancel-workflow → terminated-state | +| **Exit** | initialize-state'ten exit-workflow; terminated-state ve `exitExecuted` | +| **Schedule cancel** | auto-passed-state'te cancel-schedule-manually → pre-complete-state | +| **Reschedule** | reschedule-timer ($self), state auto-passed-state kalir | +| **QueryRoles / roller** | `/functions/authorize?role=...`; move-to-processing; processing-state'te test-processor / test-viewer deny | + +### Kullanilan Bilesenler + +| Tip | Anahtar | Dosya | +|-----|---------|-------| +| Task | `script-task` | Tasks/lifecycle-transitions/script-task.json | +| CSX | InitializeDataMapping | Workflows/lifecycle-transitions/src/InitializeDataMapping.csx | +| CSX | ExitMapping | Workflows/lifecycle-transitions/src/ExitMapping.csx | +| CSX | ProcessTransitionMapping | Workflows/lifecycle-transitions/src/ProcessTransitionMapping.csx | +| CSX | ProcessEntryMapping | Workflows/lifecycle-transitions/src/ProcessEntryMapping.csx | +| CSX | ProcessExitMapping | Workflows/lifecycle-transitions/src/ProcessExitMapping.csx | +| CSX | TestPathPassRule | Workflows/lifecycle-transitions/src/TestPathPassRule.csx | +| CSX | TestPathFailRule | Workflows/lifecycle-transitions/src/TestPathFailRule.csx | +| CSX | AlwaysTrueRule | Workflows/lifecycle-transitions/src/AlwaysTrueRule.csx | +| CSX | ShortTimerMapping | Workflows/lifecycle-transitions/src/ShortTimerMapping.csx | +| CSX | TimerEntryMapping | Workflows/lifecycle-transitions/src/TimerEntryMapping.csx | + +**Workflow tag'leri (ozet):** `exit-transition`, `schedule-cancel`, `schedule-reschedule`, `query-roles`, `transition-roles` dahil olmak uzere lifecycle ile ilgili tum tag'ler `lifecycle-transitions-test-workflow.json` icinde tanimlidir. + +--- + +## Grup 2: SubFlow & SubProcess Orchestration + +**Workflow'lar:** +- `subflow-orchestration-parent` (type: F) - Ana flow +- `subflow-orchestration-child` (type: S) - Alt flow +- `subflow-orchestration-grandchild` (type: S) - Torun flow + +**Amac:** Parent-child-grandchild SubFlow zincirini, parent seviyesindeki shared transition'lari, **child workflow uzerindeki shared transition'u**, **cancel cascade** (parent iptalinde alt akislarda **child-cancelled** / **grandchild-cancelled** final state'leri), **`/functions/state` uzerinden effective state** gorunurlugunu ve **updateData transition** (SubFlow'dan parent data guncelleme) ozelligini test eder. + +### Agac Yapisi + +``` +subflow-orchestration-parent (F) +│ +├── [startTransition] start-subflow-orchestration-parent +│ └── onExecutionTasks: +│ └── subflow-script-task + ParentStartMapping.csx +│ +├── [cancel] cancel-parent → parent-cancelled +│ +├── [sharedTransitions] +│ └── shared-update-data (Manual, target:$self) +│ ├── availableIn: ["parent-subflow-state"] +│ └── onExecutionTasks: +│ └── subflow-script-task + ParentSharedUpdateMapping.csx +│ +├── parent-initial (Initial, stateType:1) +│ └── Transitions: +│ └── auto-parent-to-subflow (Auto) → parent-subflow-state +│ └── rule: AlwaysTrueRule.csx +│ +├── parent-subflow-state (SubFlow, stateType:4) +│ ├── subFlow: type "S" +│ │ ├── process: subflow-orchestration-child +│ │ └── mapping: ParentToChildSubFlowMapping.csx (ISubFlowMapping) +│ └── Transitions: +│ └── auto-parent-to-completed (Auto) → parent-completed +│ └── rule: AlwaysTrueRule.csx +│ +├── parent-completed (Final/Success, stateType:3, subType:1) +└── parent-cancelled (Final/Terminated, stateType:3, subType:3) + + subflow-orchestration-child (S) + │ + ├── [cancel] cancel-child → child-cancelled + │ + ├── [updateData] update-parent-data (Manual, target:$self) + │ └── onExecutionTasks: + │ └── subflow-script-task + UpdateParentDataMapping.csx (IMapping) + │ + ├── [sharedTransitions] + │ └── shared-child-update (Manual, target:$self) + │ ├── availableIn: ["child-subflow-state"] + │ └── onExecutionTasks: + │ └── subflow-script-task + ChildSharedUpdateMapping.csx (IMapping) + │ + ├── [startTransition] start-subflow-orchestration-child → child-initial + │ + ├── child-initial (Initial, stateType:1) + │ ├── onEntries: + │ │ └── subflow-script-task + ChildStartMapping.csx + │ └── Transitions: + │ └── auto-child-to-subflow (Auto) → child-subflow-state + │ └── rule: AlwaysTrueRule.csx + │ + ├── child-subflow-state (SubFlow, stateType:4) + │ ├── subFlow: type "S" + │ │ ├── process: subflow-orchestration-grandchild + │ │ └── mapping: ChildToGrandchildSubFlowMapping.csx (ISubFlowMapping) + │ └── Transitions: + │ └── auto-child-to-completed (Auto) → child-completed + │ └── rule: AlwaysTrueRule.csx + │ + ├── child-completed (Final/Success, stateType:3, subType:1) + └── child-cancelled (Final/Terminated, stateType:3, subType:3) + + subflow-orchestration-grandchild (S) + │ + ├── [cancel] cancel-grandchild → grandchild-cancelled + │ + ├── [startTransition] start-subflow-orchestration-grandchild → grandchild-initial + │ + ├── grandchild-initial (Initial, stateType:1) + │ ├── onEntries: + │ │ └── subflow-script-task + GrandchildStartMapping.csx + │ └── Transitions: + │ └── complete-grandchild (Manual) → grandchild-completed + │ + ├── grandchild-completed (Final/Success, stateType:3, subType:1) + │ └── onEntries: + │ └── subflow-script-task + GrandchildCompleteMapping.csx + │ + └── grandchild-cancelled (Final/Terminated, stateType:3, subType:3) +``` + +### Test Edilen Ozellikler + +| Ozellik | Nasil Test Edilir | Ilgili Eleman | +|---------|-------------------|---------------| +| SubFlow state (stateType:4) | Parent ve child'da SubFlow state | parent-subflow-state, child-subflow-state | +| SubFlow tipi (type: S) | Child ve grandchild workflow tipleri | subflow-orchestration-child/grandchild | +| 3 seviye zincirleme (parent→child→grandchild) | Ic ice SubFlow cagrilari | Tum 3 workflow | +| ISubFlowMapping | SubFlow'a data gonderme/alma | ParentToChildSubFlowMapping, ChildToGrandchildSubFlowMapping | +| Shared transitions ($self) — parent | State degistirmeden data guncelleme | shared-update-data | +| **Shared transitions ($self) — child** | Child tanimindaki paylasimli gecis; **availableIn: child-subflow-state** | shared-child-update, ChildSharedUpdateMapping.csx | +| availableIn kisitlamasi | Shared transition sadece belirli state'lerde | parent: parent-subflow-state; child: child-subflow-state | +| Cancel transition — parent | Parent iptal | cancel-parent → parent-cancelled | +| **Cancel hedefleri — child / grandchild** | Alt akislarda iptal final state | cancel-child → **child-cancelled**; cancel-grandchild → **grandchild-cancelled** | +| **Cancel cascade** | Parent iptalinde ic ice sonlandirma | HTTP: cancel-parent senaryosu | +| **Effective state** | `/functions/state` ile en derin aktif alt akis durumu (or. grandchild-initial) | HTTP Test 4 | +| **UpdateData transition (SubFlow)** | Child'dan parent instance datasini guncelleme ($self) | update-parent-data, UpdateParentDataMapping.csx | +| Manuel transition (SubFlow icinde) | Grandchild'da kullanici tetikli tamamlama | complete-grandchild | + +### HTTP Test Dosyasi (`subflow-orchestration.http`) + +| Test | Kisa Aciklama | +|------|---------------| +| TEST 1 Happy path | Grandchild tamamlama, parent-completed ve data bayraklari | +| **TEST 2 Cancel cascade** | Parent cancel; alt akislarin sonlanmasi ve parent-cancelled | +| **TEST 3 Child shared transition** | Parent instance URL uzerinden **shared-child-update**; `childSharedUpdateExecuted` | +| **TEST 4 Effective state** | nested calisma sirasinda effectiveState / metadata | +| **TEST 5 UpdateData SubFlow** | Child updateData tetikleme; parent data'da `childUpdatedParent` kontrolu | + +### Kullanilan Bilesenler + +| Tip | Anahtar | Dosya | +|-----|---------|-------| +| Task | `subflow-script-task` | Tasks/subflow-orchestration/subflow-script-task.json | +| CSX | ParentStartMapping | Workflows/subflow-orchestration/src/ParentStartMapping.csx | +| CSX | ParentToChildSubFlowMapping | Workflows/subflow-orchestration/src/ParentToChildSubFlowMapping.csx | +| CSX | ParentSharedUpdateMapping | Workflows/subflow-orchestration/src/ParentSharedUpdateMapping.csx | +| CSX | ChildStartMapping | Workflows/subflow-orchestration/src/ChildStartMapping.csx | +| CSX | ChildToGrandchildSubFlowMapping | Workflows/subflow-orchestration/src/ChildToGrandchildSubFlowMapping.csx | +| CSX | **ChildSharedUpdateMapping** | Workflows/subflow-orchestration/src/ChildSharedUpdateMapping.csx | +| CSX | **UpdateParentDataMapping** | Workflows/subflow-orchestration/src/UpdateParentDataMapping.csx | +| CSX | GrandchildStartMapping | Workflows/subflow-orchestration/src/GrandchildStartMapping.csx | +| CSX | GrandchildCompleteMapping | Workflows/subflow-orchestration/src/GrandchildCompleteMapping.csx | +| CSX | AlwaysTrueRule | Workflows/subflow-orchestration/src/AlwaysTrueRule.csx | + +--- + +## Grup 3: Task Execution & Scripting + +**Workflow'lar:** +- `task-execution-test-workflow` (type: F) - Ana test workflow'u +- `task-target-workflow` (type: F) - Cross-workflow test icin hedef + +**Amac:** Farkli task tiplerini (HTTP, Script, StartFlow, GetInstanceData) ve task siralama mekanizmasini test eder. + +### Agac Yapisi + +``` +task-execution-test-workflow (F) +│ +├── [startTransition] start-task-execution +│ └── onExecutionTasks: +│ └── task-exec-script-task + InitTaskTestMapping.csx +│ +├── http-task-state (Initial, stateType:1) +│ ├── onEntries: +│ │ └── http-process-task (type:6) + HttpProcessMapping.csx +│ └── Transitions: +│ └── auto-to-script-processing (Auto) → script-processing-state +│ +├── script-processing-state (Intermediate, stateType:2) +│ ├── onEntries: +│ │ └── task-exec-script-task (type:7) + ScriptProcessMapping.csx +│ └── Transitions: +│ └── auto-to-cross-workflow (Auto) → cross-workflow-state +│ +├── cross-workflow-state (Intermediate, stateType:2) +│ ├── onEntries: +│ │ └── task-exec-script-task (type:7) + CrossWorkflowMapping.csx +│ └── Transitions: +│ └── auto-to-start-flow (Auto) → start-flow-state +│ +├── start-flow-state (Intermediate, stateType:2) +│ ├── onEntries: +│ │ └── start-flow-task (type:11) + StartFlowMapping.csx +│ └── Transitions: +│ └── auto-to-get-instance-data (Auto) → get-instance-data-state +│ +├── get-instance-data-state (Intermediate, stateType:2) +│ ├── onEntries: +│ │ └── get-instance-data-task (type:13) + GetInstanceDataMapping.csx +│ └── Transitions: +│ └── auto-to-completed (Auto) → completed-state +│ +└── completed-state (Final/Success, stateType:3, subType:1) + +task-target-workflow (F) +│ +├── [startTransition] start-target → target-initial +│ +├── target-initial (Initial, stateType:1) +│ └── Transitions: +│ └── auto-complete-target (Auto) → target-completed +│ └── rule: AlwaysTrueRule.csx +│ +└── target-completed (Final/Success, stateType:3, subType:1) +``` + +### Test Edilen Ozellikler + +| Ozellik | Nasil Test Edilir | Ilgili Eleman | +|---------|-------------------|---------------| +| HTTP Task (type:6) | Mockoon'a HTTP istegi gonderme | http-process-task + HttpProcessMapping | +| Script Task (type:7) | C# script ile data donusumu | task-exec-script-task + ScriptProcessMapping | +| StartFlow Task (type:11) | Baska bir workflow baslatma | start-flow-task + StartFlowMapping | +| GetInstanceData Task (type:13) | Baska workflow'un datasini okuma | get-instance-data-task + GetInstanceDataMapping | +| HttpTask cast + SetBody | HTTP task'a body set etme | HttpProcessMapping.csx InputHandler | +| StartTask cast + SetBody | Start task'a body set etme | StartFlowMapping.csx InputHandler | +| GetInstanceDataTask cast + SetInstance | Hedef instance belirleme | GetInstanceDataMapping.csx InputHandler | +| context.Body.data | HTTP/Task response okuma | OutputHandler'larda context.Body.data | +| GetConfigValue | Vault'tan config degeri okuma | HttpProcessMapping (MocklabBaseUrl) | +| Task siralama (onEntries order) | Her state'te order:1 task | Tum onEntries | +| Cross-workflow iletisim | Bir workflow baska bir workflow baslatir ve datasini okur | start-flow → get-instance-data zinciri | + +### Kullanilan Bilesenler + +| Tip | Anahtar | Tip Kodu | Dosya | +|-----|---------|----------|-------| +| Task | `http-process-task` | type:6 (HTTP) | Tasks/task-execution/http-process-task.json | +| Task | `task-exec-script-task` | type:7 (Script) | Tasks/task-execution/task-exec-script-task.json | +| Task | `start-flow-task` | type:11 (StartFlow) | Tasks/task-execution/start-flow-task.json | +| Task | `get-instance-data-task` | type:13 (GetInstanceData) | Tasks/task-execution/get-instance-data-task.json | +| CSX | InitTaskTestMapping | | Workflows/task-execution/src/InitTaskTestMapping.csx | +| CSX | HttpProcessMapping | | Workflows/task-execution/src/HttpProcessMapping.csx | +| CSX | ScriptProcessMapping | | Workflows/task-execution/src/ScriptProcessMapping.csx | +| CSX | CrossWorkflowMapping | | Workflows/task-execution/src/CrossWorkflowMapping.csx | +| CSX | StartFlowMapping | | Workflows/task-execution/src/StartFlowMapping.csx | +| CSX | GetInstanceDataMapping | | Workflows/task-execution/src/GetInstanceDataMapping.csx | +| CSX | AlwaysTrueRule | | Workflows/task-execution/src/AlwaysTrueRule.csx | + +--- + +## Grup 4: Error Boundary + +**Workflow:** `error-boundary-test-workflow` (type: F) + +**Amac:** Hata yonetimi mekanizmasini (error boundary) task, state ve workflow seviyelerinde test eder; **Rollback (action:2)**, **Log (action:5)** ve **Notify (action:4)** aksiyonlari ile zincirlenmis senaryoyu kapsar. Ayrica **timeoutPolicy** (onTimeout) ve **gelismis errorHandlerRule** (errorTypes/errorCodes filtreleme) ozelliklerini icerir. + +### Agac Yapisi + +``` +error-boundary-test-workflow (F) +│ +├── [startTransition] start-error-boundary-test +│ └── onExecutionTasks: +│ └── error-script-task + InitErrorTestMapping.csx +│ +├── [workflow-level errorBoundary] +│ ├── onError: action:0 (Abort), priority:100 +│ └── onTimeout: action:3 (Ignore) +│ +├── retry-test-state (Initial, stateType:1) +│ ├── onEntries: +│ │ └── error-http-task (type:6) + ErrorHttpMapping.csx +│ │ └── [task-level errorBoundary] +│ │ └── onError: action:1 (Retry), priority:10 +│ │ └── retryPolicy: maxRetries:2, initialDelay:PT2S, backoffType:0 +│ └── Transitions: +│ └── auto-to-ignore-test (Auto) → ignore-test-state +│ └── rule: AlwaysTrueRule.csx +│ +├── ignore-test-state (Intermediate, stateType:2) +│ ├── [state-level errorBoundary] +│ │ └── onError: action:3 (Ignore), priority:10, errorTypes:["System.InvalidOperationException"], errorCodes:["*"] +│ ├── onEntries: +│ │ ├── order:1 error-script-task + ThrowErrorMapping.csx (kasitli hata firlatir) +│ │ └── order:2 error-script-task + IgnoreErrorMapping.csx (hata yoksayildiktan sonra calisir) +│ └── Transitions: +│ └── auto-to-rollback-from-ignore (Auto) → rollback-test-state +│ └── rule: AlwaysTrueRule.csx +│ +├── rollback-test-state (Intermediate, stateType:2) +│ ├── [state-level errorBoundary] +│ │ └── onError: action:2 (Rollback), priority:10 +│ ├── onEntries: +│ │ ├── order:1 error-script-task + ThrowErrorMapping.csx +│ │ └── order:2 error-script-task + RollbackMapping.csx (IMapping) +│ └── Transitions: +│ └── auto-to-log-from-rollback (Auto) → log-test-state +│ └── rule: AlwaysTrueRule.csx +│ +├── log-test-state (Intermediate, stateType:2) +│ ├── [state-level errorBoundary] +│ │ └── onError: action:5 (Log), priority:10 +│ ├── onEntries: +│ │ ├── order:1 error-script-task + ThrowErrorMapping.csx +│ │ └── order:2 error-script-task + LogOnlyMapping.csx +│ └── Transitions: +│ └── auto-to-completed-from-log (Auto) → notify-test-state +│ └── rule: AlwaysTrueRule.csx +│ +├── notify-test-state (Intermediate, stateType:2) +│ ├── [state-level errorBoundary] +│ │ └── onError: action:4 (Notify), priority:10, transition:"auto-to-completed-from-notify" +│ ├── onEntries: +│ │ ├── order:1 error-script-task + ThrowErrorMapping.csx +│ │ └── order:2 error-script-task + NotifyMapping.csx (IMapping) +│ └── Transitions: +│ └── auto-to-completed-from-notify (Auto) → completed-state +│ └── rule: AlwaysTrueRule.csx +│ +├── completed-state (Final/Success, stateType:3, subType:1) +└── error-final (Final/Error, stateType:3, subType:2) +``` + +### Test Edilen Ozellikler + +| Ozellik | Nasil Test Edilir | Ilgili Eleman | +|---------|-------------------|---------------| +| Task-level error boundary | Task onEntries'de errorBoundary | retry-test-state onEntries | +| State-level error boundary | State uzerinde errorBoundary | ignore-test-state, rollback-test-state, log-test-state | +| Workflow-level error boundary | Workflow attributes'da errorBoundary | attributes.errorBoundary | +| Retry action (action:1) | HTTP task hata alinca yeniden dene | retry-test-state task errorBoundary | +| Retry policy | maxRetries, initialDelay, backoffType | retryPolicy yapisi | +| Ignore action (action:3) | Script hata firlatinca yoksay | ignore-test-state errorBoundary | +| **Rollback action (action:2)** | State errorBoundary rollback | rollback-test-state | +| **Log action (action:5)** | Hata loglama; siradaki task ile devam | log-test-state | +| **Notify action (action:4)** | Hata bildirim ve transition tetikleme | notify-test-state errorBoundary | +| Abort action (action:0) | En son calisacak global yakalama | workflow errorBoundary | +| **timeoutPolicy (onTimeout)** | Timeout durumunda action:3 (Ignore) | workflow errorBoundary.onTimeout | +| **errorHandlerRule (errorTypes)** | Hata tipine gore filtreleme | ignore-test-state: System.InvalidOperationException | +| **errorHandlerRule (errorCodes)** | Hata koduna gore filtreleme | ignore-test-state: errorCodes:["*"] | +| Priority siralama | Dusuk priority once calisir | task:10, state:10, workflow:100 | +| Hata sonrasi devam | Ignore sonrasi siradaki task calisir | IgnoreErrorMapping (order:2) | +| Rollback sonrasi zincir | rollback-test-state tamamlaninca log-test-state | auto-to-log-from-rollback | +| Log sonrasi basari finali | log-test-state tamamlaninca completed-state | auto-to-completed-from-log | + +### Kullanilan Bilesenler + +| Tip | Anahtar | Dosya | +|-----|---------|-------| +| Task | `error-http-task` (type:6) | Tasks/error-boundary/error-http-task.json | +| Task | `error-script-task` (type:7) | Tasks/error-boundary/error-script-task.json | +| CSX | InitErrorTestMapping | Workflows/error-boundary/src/InitErrorTestMapping.csx | +| CSX | ErrorHttpMapping | Workflows/error-boundary/src/ErrorHttpMapping.csx | +| CSX | ThrowErrorMapping | Workflows/error-boundary/src/ThrowErrorMapping.csx | +| CSX | IgnoreErrorMapping | Workflows/error-boundary/src/IgnoreErrorMapping.csx | +| CSX | **RollbackMapping** | Workflows/error-boundary/src/RollbackMapping.csx | +| CSX | LogOnlyMapping | Workflows/error-boundary/src/LogOnlyMapping.csx | +| CSX | **NotifyMapping** | Workflows/error-boundary/src/NotifyMapping.csx | +| CSX | AlwaysTrueRule | Workflows/error-boundary/src/AlwaysTrueRule.csx | + +**Workflow tag'leri (ozet):** `rollback`, `log-action`, `notify`, `notify-action`, `timeout-policy`, `error-types`, `error-codes` dahil; tam liste `error-boundary-test-workflow.json` icindedir. + +--- + +## Grup 5: View, Function & Extension + +**Workflow:** `view-function-extension-test-workflow` (type: F) + +**Amac:** View tipleri, display modlari, function cagrilari, extension mekanizmasi, wizard state'i ve **features** referansini test eder. + +### Agac Yapisi + +``` +view-function-extension-test-workflow (F) +│ +├── [startTransition] start-view-function-extension-test +│ └── onExecutionTasks: +│ └── vfe-script-task + InitVfeMapping.csx +│ +├── [functions] +│ ├── single-task-function (scope: Instance) +│ │ └── task: vfe-script-task + FunctionSingleTaskMapping.csx +│ └── multi-task-function (scope: Instance) +│ ├── onExecutionTasks: +│ │ ├── order:1 vfe-script-task + FunctionMultiTask1Mapping.csx +│ │ └── order:2 vfe-http-task + FunctionMultiTask2Mapping.csx +│ └── output: FunctionOutputMapping.csx (IOutputHandler) +│ +├── [features] +│ └── global-extension (sys-extensions referansi — features array'inde) +│ +├── [extensions] +│ ├── global-extension (type:1 Global, scope:3 Everywhere) +│ │ └── task: vfe-script-task + GlobalExtensionMapping.csx +│ └── requested-extension (type:4 DefinedFlowAndRequested, scope:1 GetInstance) +│ └── task: vfe-script-task + RequestedExtensionMapping.csx +│ +├── view-test-state (Initial, stateType:1) +│ ├── view: json-view (type:1 JSON, display: full-page) +│ └── Transitions: +│ ├── auto-to-multi-view (Auto, triggerType:1) → multi-view-state +│ │ └── rule: WebPlatformRule.csx (IConditionMapping, platform kontrolu) +│ └── default-auto-fallback (Auto, triggerType:1, triggerKind:10) → completed-state +│ └── rule: AlwaysTrueRule.csx (fallback) +│ +├── multi-view-state (Intermediate, stateType:2) +│ ├── view: html-view (type:2 HTML, display: popup) +│ └── Transitions: +│ └── manual-to-wizard (Manual) → wizard-state +│ +├── wizard-state (Wizard, stateType:5) +│ └── Transitions: +│ └── complete-with-markdown-view (Manual) → completed-state +│ └── view: markdown-view (type:3 Markdown, display: bottom-sheet) +│ +└── completed-state (Final/Success, stateType:3, subType:1) +``` + +### Test Edilen Ozellikler + +| Ozellik | Nasil Test Edilir | Ilgili Eleman | +|---------|-------------------|---------------| +| JSON View (type:1) | State'e JSON view baglama | json-view → view-test-state | +| HTML View (type:2) | State'e HTML view baglama | html-view → multi-view-state | +| Markdown View (type:3) | Transition'a view baglama | markdown-view → complete-with-markdown-view | +| Display modlari | full-page, popup, bottom-sheet | 3 farkli view | +| Wizard State (stateType:5) | En fazla 1 transition kisitlamasi | wizard-state | +| Transition view | Transition uzerinde view gosterimi | complete-with-markdown-view | +| IConditionMapping (transition rule) | Auto transition'da rule kullanimi | WebPlatformRule.csx | +| triggerKind:10 (varsayilan fallback) | Complementary auto transitions | default-auto-fallback | +| Single-task function | Tek task'li function tanimlama | single-task-function | +| Multi-task function | Birden fazla task'li function | multi-task-function | +| IOutputHandler | Function ciktisini birlestirme | FunctionOutputMapping.csx | +| Global extension (type:1) | Tum isteklerde calisan extension | global-extension | +| Requested extension (type:4) | Talep edildiginde calisan extension | requested-extension | +| Extension scope | Everywhere vs GetInstance | scope:3 vs scope:1 | +| **Features referansi** | features array'inde extension referansi | features: global-extension | + +### Kullanilan Bilesenler + +| Tip | Anahtar | Dosya | +|-----|---------|-------| +| Task | `vfe-script-task` (type:7) | Tasks/view-function-extension/vfe-script-task.json | +| Task | `vfe-http-task` (type:6) | Tasks/view-function-extension/vfe-http-task.json | +| View | `json-view` | Views/view-function-extension/json-view.json | +| View | `html-view` | Views/view-function-extension/html-view.json | +| View | `markdown-view` | Views/view-function-extension/markdown-view.json | +| Function | `single-task-function` | Functions/view-function-extension/single-task-function.json | +| Function | `multi-task-function` | Functions/view-function-extension/multi-task-function.json | +| Extension | `global-extension` | Extensions/view-function-extension/global-extension.json | +| Extension | `requested-extension` | Extensions/view-function-extension/requested-extension.json | +| CSX | InitVfeMapping | Workflows/view-function-extension/src/InitVfeMapping.csx | +| CSX | WebPlatformRule | Workflows/view-function-extension/src/WebPlatformRule.csx | +| CSX | AlwaysTrueRule | Workflows/view-function-extension/src/AlwaysTrueRule.csx | +| CSX | FunctionSingleTaskMapping | Functions/view-function-extension/src/FunctionSingleTaskMapping.csx | +| CSX | FunctionMultiTask1Mapping | Functions/view-function-extension/src/FunctionMultiTask1Mapping.csx | +| CSX | FunctionMultiTask2Mapping | Functions/view-function-extension/src/FunctionMultiTask2Mapping.csx | +| CSX | FunctionOutputMapping | Functions/view-function-extension/src/FunctionOutputMapping.csx | +| CSX | GlobalExtensionMapping | Extensions/view-function-extension/src/GlobalExtensionMapping.csx | +| CSX | RequestedExtensionMapping | Extensions/view-function-extension/src/RequestedExtensionMapping.csx | + +--- + +## Grup 6: Schema & Data Management + +**Workflow:** `schema-data-test-workflow` (type: F) + +**Amac:** Master schema, transition schema validasyonu, updateData ($self) mekanizmasi ve field roles ozelliklerini test eder. + +### Agac Yapisi + +``` +schema-data-test-workflow (F) +│ +├── [startTransition] start-schema-test +│ └── onExecutionTasks: +│ └── schema-data-script-task + SchemaInitMapping.csx +│ +├── [workflow-level schema] +│ └── schema-data-master (master schema) +│ ├── required: orderId, customerName, amount, currency +│ ├── enum: currency (TRY, USD, EUR) +│ └── roles: internalNote (admin:allow, customer:deny), auditLog (auditor:allow) +│ +├── [updateData] +│ └── update-instance-data (Manual, target: $self) +│ +├── data-initialized (Initial, stateType:1) +│ └── Transitions: +│ ├── confirm-with-schema (Manual) → schema-validated-state +│ │ ├── schema: schema-data-confirm-transition +│ │ │ └── required: confirmed (boolean), confirmedBy (string) +│ │ └── onExecutionTasks: +│ │ └── schema-data-script-task + ConfirmMapping.csx +│ └── skip-to-no-schema (Manual) → no-schema-state +│ +├── schema-validated-state (Intermediate, stateType:2) +│ └── Transitions: +│ └── to-no-schema (Manual) → no-schema-state +│ +├── no-schema-state (Intermediate, stateType:2) +│ └── Transitions: +│ └── complete-schema-test (Manual) → completed-state +│ +└── completed-state (Final/Success, stateType:3, subType:1) +``` + +### Test Edilen Ozellikler + +| Ozellik | Nasil Test Edilir | Ilgili Eleman | +|---------|-------------------|---------------| +| Master schema (workflow-level) | Workflow attributes.schema ile tanimlama | schema-data-master | +| Transition schema | Transition'a schema baglama | schema-data-confirm-transition | +| Schema validasyonu | Gecerli data ile transition | confirm-with-schema | +| Schema sessiz reddi | Gecersiz data gonderildiginde state degismez | HTTP test: eksik required alan gonderme | +| updateData ($self) | State degistirmeden data guncelleme | update-instance-data | +| Field roles | Alan bazli erisim kontrolu | internalNote (admin/customer), auditLog (auditor) | +| JSON Schema Draft 2020-12 | Schema standardi uyumu | Her iki schema dosyasi | +| Required alan kontrolu | Zorunlu alanlarin validasyonu | orderId, customerName, amount, currency | +| Enum validasyonu | Gecerli deger kümesi kontrolu | currency: TRY, USD, EUR | +| ETag | Instance data versiyonlama (HTTP test) | HTTP test dosyasinda | + +### Kullanilan Bilesenler + +| Tip | Anahtar | Dosya | +|-----|---------|-------| +| Task | `schema-data-script-task` (type:7) | Tasks/schema-data/schema-data-script-task.json | +| Schema | `schema-data-master` | Schemas/schema-data/schema-data-master.json | +| Schema | `schema-data-confirm-transition` | Schemas/schema-data/schema-data-confirm-transition.json | +| CSX | SchemaInitMapping | Workflows/schema-data/src/SchemaInitMapping.csx | +| CSX | ConfirmMapping | Workflows/schema-data/src/ConfirmMapping.csx | + +--- + +## Grup 7: Instance Management + +**Workflow:** `instance-management-test-workflow` (type: F) + +**Amac:** Instance filtreleme, sayfalama, siralama, workflow timeout, idempotent start mekanizmalarini ve **state subType 4 (Temporarily suspended), 5 (Busy), 6 (Human)** ozelliklerini test eder. + +### Agac Yapisi + +``` +instance-management-test-workflow (F) +│ +├── [startTransition] start-instance-management-test +│ └── onExecutionTasks: +│ └── instance-mgmt-script-task + InitInstanceMgmtMapping.csx +│ +├── [timeout] +│ └── workflow-timeout → timeout-state +│ └── timer: duration PT120S (2 dakika), reset: false +│ +├── active-state (Initial, stateType:1) +│ └── Transitions: +│ ├── process (Manual) → processing-state +│ └── fast-complete (Manual) → completed-state +│ +├── processing-state (Intermediate, stateType:2) +│ └── Transitions: +│ ├── finish (Manual) → completed-state +│ ├── reject (Manual) → rejected-state +│ ├── suspend (Manual) → suspended-state +│ ├── set-busy (Manual) → busy-state +│ └── assign-human (Manual) → human-state +│ +├── completed-state (Final/Success, stateType:3, subType:1) +├── rejected-state (Final/Error, stateType:3, subType:2) +├── timeout-state (Final/Terminated, stateType:3, subType:3) +├── suspended-state (Final/Suspended, stateType:3, subType:4) +├── busy-state (Final/Busy, stateType:3, subType:5) +└── human-state (Final/Human, stateType:3, subType:6) +``` + +### Test Edilen Ozellikler + +| Ozellik | Nasil Test Edilir | Ilgili Eleman | +|---------|-------------------|---------------| +| Workflow timeout | PT120S sonunda otomatik timeout-state | attributes.timeout | +| Timeout timer | Suresiz timeout ve reset:false | timer yapisi | +| Idempotent start | Ayni key ile tekrar baslatma | HTTP test: ayni key ile 2 kez POST | +| Instance filtreleme | API uzerinden filtre sorgusu | HTTP test: filter=attributes.category eq 'finance' | +| Instance sayfalama | page ve pageSize parametreleri | HTTP test: page=1&pageSize=2 | +| Instance siralama | sort parametresi | HTTP test: sort=-createdAt | +| Effective state | State bazli filtreleme | HTTP test: filter=state eq 'active-state' | +| Status filtreleme | Instance durumuna gore filtreleme | HTTP test: filter=status eq 'A' | +| Coklu instance senaryosu | Farkli category/priority ile birden fazla instance | HTTP test: 3 farkli instance | +| **subType 4 (Temporarily suspended)** | Final state ile suspended alt tipi | suspended-state | +| **subType 5 (Busy)** | Final state ile busy alt tipi | busy-state | +| **subType 6 (Human)** | Final state ile human alt tipi | human-state | +| Manuel transition cesitleri | Ayni state'ten farkli hedeflere gecis | process, fast-complete, finish, reject, suspend, set-busy, assign-human | + +### Kullanilan Bilesenler + +| Tip | Anahtar | Dosya | +|-----|---------|-------| +| Task | `instance-mgmt-script-task` (type:7) | Tasks/instance-management/instance-mgmt-script-task.json | +| CSX | InitInstanceMgmtMapping | Workflows/instance-management/src/InitInstanceMgmtMapping.csx | + +--- + +## Grup 8: Extended Tasks (Dapr ve Genisletilmis Gorev Tipleri) + +**Workflow:** `extended-tasks-test-workflow` (type: F) + +**Dosya:** `Workflows/extended-tasks/extended-tasks-test-workflow.json` + +**Amac:** Dapr tabanli gorev tipleri (HTTP, Service, Binding, PubSub), bildirim, baska instance uzerinde gecis tetikleme, alt surec baslatma, instance listesi sorgulama ve insan gorevi (manuel onay) akislarini tek workflow zincirinde dogrular. Baslangic state'inde **lifecycle-transitions** modulundeki **`script-task`** tanimi yeniden kullanilir; mapping bu workflow'a ozel **`InitExtendedTaskMapping.csx`** dosyasidir. + +### Gorev Tipleri (`Tasks/extended-tasks/`) + +| Anahtar | type (kod) | Aciklama | +|---------|------------|----------| +| `dapr-http-task` | 1 | Dapr HTTP invoke | +| `dapr-binding-task` | 2 | Dapr output binding | +| `dapr-service-task` | 3 | Dapr service invocation | +| `dapr-pubsub-task` | 4 | Dapr pub/sub publish | +| `human-task` | 5 | Insan onayi / manuel gorev | +| `notification-task` | 10 | Dis bildirim (HTTP vb.) | +| `trigger-transition-task` | 12 | Hedef instance'da transition tetikleme | +| `subprocess-task` | 14 | Alt surec / bagli flow calistirma | +| `get-instances-task` | 15 | Instance listesi filtreleme | + +### Agac Yapisi + +``` +extended-tasks-test-workflow (F) +│ +├── [startTransition] start-extended-tasks → init-state +│ └── onExecutionTasks: (bos) +│ +├── init-state (Initial, stateType:1) +│ ├── onEntries: +│ │ └── script-task (lifecycle-transitions tanimi) + InitExtendedTaskMapping.csx +│ └── Transitions: +│ └── auto-to-dapr-http (Auto) → dapr-http-state +│ └── rule: AlwaysTrueRule.csx +│ +├── dapr-http-state (Intermediate, stateType:2) +│ ├── onEntries: dapr-http-task (type:1) + DaprHttpMapping.csx +│ └── Transitions: auto-to-dapr-service → dapr-service-state (AlwaysTrueRule) +│ +├── dapr-service-state (Intermediate, stateType:2) +│ ├── onEntries: dapr-service-task (type:3) + DaprServiceMapping.csx +│ └── Transitions: auto-to-dapr-binding → dapr-binding-state +│ +├── dapr-binding-state (Intermediate, stateType:2) +│ ├── onEntries: dapr-binding-task (type:2) + DaprBindingMapping.csx +│ └── Transitions: auto-to-dapr-pubsub → dapr-pubsub-state +│ +├── dapr-pubsub-state (Intermediate, stateType:2) +│ ├── onEntries: dapr-pubsub-task (type:4) + DaprPubSubMapping.csx +│ └── Transitions: auto-to-notification → notification-state +│ +├── notification-state (Intermediate, stateType:2) +│ ├── onEntries: notification-task (type:10) + NotificationMapping.csx +│ └── Transitions: auto-to-trigger-transition → trigger-transition-state +│ +├── trigger-transition-state (Intermediate, stateType:2) +│ ├── onEntries: trigger-transition-task (type:12) + TriggerTransitionMapping.csx +│ └── Transitions: auto-to-subprocess → subprocess-state +│ +├── subprocess-state (Intermediate, stateType:2) +│ ├── onEntries: subprocess-task (type:14) + SubProcessMapping.csx +│ └── Transitions: auto-to-get-instances → get-instances-state +│ +├── get-instances-state (Intermediate, stateType:2) +│ ├── onEntries: get-instances-task (type:15) + GetInstancesMapping.csx +│ └── Transitions: auto-to-human-task → human-task-state +│ +├── human-task-state (Intermediate, stateType:2) +│ ├── onEntries: human-task (type:5) + HumanTaskMapping.csx +│ └── Transitions: +│ └── approve-human-task (Manual) → completed-state +│ +└── completed-state (Final/Success, stateType:3, subType:1) +``` + +### CSX Dosyalari (`Workflows/extended-tasks/src/`) + +| Dosya | Rol | +|-------|-----| +| InitExtendedTaskMapping.csx | IMapping — init-state onEntries | +| DaprHttpMapping.csx | IMapping | +| DaprServiceMapping.csx | IMapping | +| DaprBindingMapping.csx | IMapping | +| DaprPubSubMapping.csx | IMapping | +| NotificationMapping.csx | IMapping | +| TriggerTransitionMapping.csx | IMapping | +| SubProcessMapping.csx | IMapping | +| GetInstancesMapping.csx | IMapping | +| HumanTaskMapping.csx | IMapping | +| AlwaysTrueRule.csx | IConditionMapping — otomatik gecis kurallari | + +### Test Edilen Ozellikler (ozet) + +| Ozellik | Nasil Test Edilir | Ilgili Eleman | +|---------|-------------------|---------------| +| Dapr HTTP task | Sidecar uzerinden uzaktan HTTP cagri | dapr-http-task, DaprHttpMapping | +| Dapr Service task | App-id ile service invocation | dapr-service-task | +| Dapr Binding task | Tanimli output binding | dapr-binding-task, test-binding.yaml | +| Dapr PubSub task | Pub/sub mesaj yayini | dapr-pubsub-task, test-pubsub.yaml | +| Notification task | Mock HTTP bildirim ucu | notification-task | +| Trigger transition task | Baska instance transition | trigger-transition-task | +| Subprocess task | Bagli workflow calistirma | subprocess-task | +| Get instances task | Filtreli instance listesi | get-instances-task | +| Human task | Manuel onay ile tamamlama | human-task, approve-human-task | +| Script task paylasimi | Ayni script-task JSON, farkli mapping | script-task + InitExtendedTaskMapping | + +### HTTP Test + +`Workflows/extended-tasks/extended-tasks-test-workflow.http` dosyasi ile uçtan uca senaryo ve ara kontroller calistirilabilir. + +### Kullanilan Bilesenler (task JSON yollari) + +| Tip | Anahtar | Dosya | +|-----|---------|-------| +| Task | `dapr-http-task` | Tasks/extended-tasks/dapr-http-task.json | +| Task | `dapr-binding-task` | Tasks/extended-tasks/dapr-binding-task.json | +| Task | `dapr-service-task` | Tasks/extended-tasks/dapr-service-task.json | +| Task | `dapr-pubsub-task` | Tasks/extended-tasks/dapr-pubsub-task.json | +| Task | `human-task` | Tasks/extended-tasks/human-task.json | +| Task | `notification-task` | Tasks/extended-tasks/notification-task.json | +| Task | `trigger-transition-task` | Tasks/extended-tasks/trigger-transition-task.json | +| Task | `subprocess-task` | Tasks/extended-tasks/subprocess-task.json | +| Task | `get-instances-task` | Tasks/extended-tasks/get-instances-task.json | +| Task | `script-task` (paylasimli) | Tasks/lifecycle-transitions/script-task.json | + +--- + +## Grup 9: Flow Types (Core ve SubProcess) + +**Workflow'lar:** +- `core-flow-test` (type: C) - Core flow tipi +- `subprocess-flow-test` (type: P) - SubProcess flow tipi + +**Amac:** vNext'in destekledigi 4 farkli workflow tipinden (C, F, S, P) test edilmeyen **Core (C)** ve **SubProcess (P)** tiplerinin runtime tarafindan kabul edilip calistirilabildigini dogrular. + +### Agac Yapisi + +``` +core-flow-test (C) +│ +├── [startTransition] start-core-flow → core-init-state +│ └── onExecutionTasks: +│ └── flow-types-script-task + CoreInitMapping.csx +│ +├── core-init-state (Initial, stateType:1) +│ ├── onEntries: +│ │ └── flow-types-script-task + CoreInitMapping.csx +│ └── Transitions: +│ └── auto-to-core-completed (Auto) → core-completed +│ └── rule: AlwaysTrueRule.csx +│ +└── core-completed (Final/Success, stateType:3, subType:1) + +subprocess-flow-test (P) +│ +├── [startTransition] start-subprocess-flow → subprocess-init-state +│ └── onExecutionTasks: +│ └── flow-types-script-task + SubProcessInitMapping.csx +│ +├── subprocess-init-state (Initial, stateType:1) +│ ├── onEntries: +│ │ └── flow-types-script-task + SubProcessInitMapping.csx +│ └── Transitions: +│ └── auto-to-subprocess-completed (Auto) → subprocess-completed +│ └── rule: AlwaysTrueRule.csx +│ +└── subprocess-completed (Final/Success, stateType:3, subType:1) +``` + +### Test Edilen Ozellikler + +| Ozellik | Nasil Test Edilir | Ilgili Eleman | +|---------|-------------------|---------------| +| Core flow tipi (type: C) | Minimal workflow publish ve calistirma | core-flow-test | +| SubProcess flow tipi (type: P) | Minimal workflow publish ve calistirma | subprocess-flow-test | +| Farkli flow tiplerinin runtime uyumlulugu | Tum 4 tip: C (G9), F (G1-G8), S (G2), P (G9) | Tum gruplarda | + +### Kullanilan Bilesenler + +| Tip | Anahtar | Dosya | +|-----|---------|-------| +| Task | `flow-types-script-task` (type:7) | Tasks/flow-types/flow-types-script-task.json | +| CSX | CoreInitMapping | Workflows/flow-types/src/CoreInitMapping.csx | +| CSX | SubProcessInitMapping | Workflows/flow-types/src/SubProcessInitMapping.csx | +| CSX | AlwaysTrueRule | Workflows/flow-types/src/AlwaysTrueRule.csx | + +### HTTP Test Dosyasi (`flow-types-test.http`) + +| Test | Kisa Aciklama | +|------|---------------| +| Core flow | Core (C) tipi workflow baslatma ve state kontrolu | +| SubProcess flow | SubProcess (P) tipi workflow baslatma ve state kontrolu | + +--- + +## Grup 10: Version Consistency (Versiyon Tutarliligi) + +**Workflow:** `version-consistency-test-workflow` (type: F) — ayni key, iki farkli versiyon (v1.0.0 ve v2.0.0) + +**Amac:** Workflow versiyonu degistiginde mevcut instance'larin kendi baslangic versiyonlarinin akisindan devam ettigini dogrular. v2.0.0 publish edildikten sonra bile v1.0.0 uzerinde baslatilmis instance'in v1 yolunu takip etmesini test eder. + +**NOT:** Bu test publish surecine bagimli oldugu icin tamamen otomatik calistirilamaz. HTTP test dosyasi kullanicinin sirasiyla v1 ve v2'yi publish etmesini gerektiren adim adim bir rehber niteligindedir. + +### Agac Yapisi + +``` +version-consistency-test-workflow (F, v1.0.0) — 3 state +│ +├── [startTransition] start-version-test → init-state +│ └── onExecutionTasks: +│ └── version-consistency-script-task + InitVersionMapping.csx +│ +├── init-state (Initial, stateType:1) +│ └── Transitions: +│ └── auto-to-processing (Auto) → processing-state +│ └── rule: AlwaysTrueRule.csx +│ +├── processing-state (Intermediate, stateType:2) +│ └── Transitions: +│ └── complete-processing (Manual) → completed-state ← v1: dogrudan completed +│ +└── completed-state (Final/Success, stateType:3, subType:1) + └── onEntries: + └── version-consistency-script-task + V1CompletedMapping.csx (v1Completed=true) + + +version-consistency-test-workflow (F, v2.0.0) — 4 state (ekstra review-state) +│ +├── [startTransition] start-version-test → init-state +│ └── onExecutionTasks: +│ └── version-consistency-script-task + InitVersionMapping.csx +│ +├── init-state (Initial, stateType:1) +│ └── Transitions: +│ └── auto-to-processing (Auto) → processing-state +│ └── rule: AlwaysTrueRule.csx +│ +├── processing-state (Intermediate, stateType:2) +│ └── Transitions: +│ └── complete-processing (Manual) → review-state ← v2: review'a gider +│ +├── review-state (Intermediate, stateType:2) ← SADECE v2'de VAR +│ ├── onEntries: +│ │ └── version-consistency-script-task + ReviewMapping.csx (reviewExecuted=true) +│ └── Transitions: +│ └── approve-review (Manual) → completed-state +│ +└── completed-state (Final/Success, stateType:3, subType:1) + └── onEntries: + └── version-consistency-script-task + V2CompletedMapping.csx (v2Completed=true) +``` + +### Test Senaryosu + +| Adim | Islem | Beklenen Sonuc | +|------|-------|----------------| +| 1 | v1.0.0 publish et | Runtime v1 tanimini kaydeder | +| 2 | Instance A baslat (v1 uzerinde) | A: processing-state'te bekler | +| 3 | v2.0.0 publish et (ayni key) | Runtime v2 tanimini kaydeder, A etkilenmez | +| 4 | Instance B baslat (v2 uzerinde) | B: processing-state'te bekler | +| 5 | Instance A: complete-processing | A → completed-state (v1 yolu, review YOK) | +| 6 | Instance B: complete-processing | B → review-state (v2 yolu) | +| 7 | Instance B: approve-review | B → completed-state | + +### Dogrulama Kriterleri + +| Instance | Son State | Data Bayraklari | +|----------|-----------|-----------------| +| A (v1.0.0) | completed-state | `v1Completed=true`, `completedByVersion="1.0.0"`, `reviewExecuted` **YOK** | +| B (v2.0.0) | completed-state | `reviewExecuted=true`, `v2Completed=true`, `completedByVersion="2.0.0"`, `v1Completed` **YOK** | + +### Test Edilen Ozellikler + +| Ozellik | Nasil Test Edilir | Ilgili Eleman | +|---------|-------------------|---------------| +| Version isolation | v2 publish sonrasi v1 instance v1 akisinda kalir | Instance A vs Instance B | +| Ayni key farkli versiyon | Ayni workflow key ile 2 farkli versiyon publish | v1.0.0 + v2.0.0 JSON dosyalari | +| Yeni instance en son versiyonu kullanir | v2 sonrasi baslatilan instance v2 akisinda gider | Instance B → review-state | +| Eski instance eski versiyonda kalir | v1 instance v2 state'lerine ugramaz | Instance A → completed (review YOK) | +| Versiyon bazli data kaniti | Her versiyonun mapping'leri farkli bayraklar set eder | v1Completed vs v2Completed, reviewExecuted | + +### Kullanilan Bilesenler + +| Tip | Anahtar | Dosya | +|-----|---------|-------| +| Task | `version-consistency-script-task` (type:7) | Tasks/version-consistency/version-consistency-script-task.json | +| Workflow | `version-consistency-test-workflow` (v1.0.0) | Workflows/version-consistency/version-consistency-test-workflow.json | +| Workflow | `version-consistency-test-workflow` (v2.0.0) | Workflows/version-consistency/version-consistency-test-workflow-v2.json | +| CSX | InitVersionMapping | Workflows/version-consistency/src/InitVersionMapping.csx | +| CSX | AlwaysTrueRule | Workflows/version-consistency/src/AlwaysTrueRule.csx | +| CSX | V1CompletedMapping | Workflows/version-consistency/src/V1CompletedMapping.csx | +| CSX | ReviewMapping | Workflows/version-consistency/src/ReviewMapping.csx | +| CSX | V2CompletedMapping | Workflows/version-consistency/src/V2CompletedMapping.csx | + +### HTTP Test Dosyasi (`version-consistency-test.http`) + +| Adim | Kisa Aciklama | +|------|---------------| +| ADIM 1 | v1.0.0 publish (manuel) | +| ADIM 2-3 | Instance A baslat, state kontrol (processing) | +| ADIM 4 | v2.0.0 publish (manuel) | +| ADIM 5-6 | Instance B baslat, state kontrol (processing) | +| ADIM 7 | Instance A complete → completed (v1 yolu) | +| ADIM 8 | Instance B complete → review (v2 yolu) | +| ADIM 9 | Instance B approve → completed | +| ADIM 10 | Data dogrulama | + +--- + +## Altyapi Bilesenleri + +### Docker Compose + +`docker-compose.yml` dosyasi asagidaki servisleri tanimlar: + +| Servis | Amac | Port / Not | +|--------|------|--------------| +| `core-mocklab` | Mock API sunucusu (HTTP task testleri icin) | 3002:5000 | +| `core-mocklab-dapr` | Mocklab Dapr sidecar | `daprd` komutunda **`--resources-path /etc/dapr/components`** ile bilesen YAML'lari yuklenir; volume: `./etc/dapr:/etc/dapr` | + +**Dapr bilesen dosyalari:** + +| Dosya | Amac | +|-------|------| +| `etc/dapr/components/test-binding.yaml` | Dapr output binding testleri (Grup 8) | +| `etc/dapr/components/test-pubsub.yaml` | Dapr pub/sub testleri (Grup 8) | +| `etc/dapr/config.yaml` | Dapr genel konfigurasyon | + +### Mockoon Mock Endpoint'leri + +`etc/docker/config/seed/integration-test-collection.json` dosyasinda tanimlanan endpoint'ler: + +| Method | Endpoint | Durum | Amac | +|--------|----------|-------|------| +| POST | `/api/test/process` | 200 | HTTP task testi (Grup 3) | +| POST | `/api/test/validate` | 200/400 | Kural bazli validasyon testi | +| GET | `/api/test/user-info` | 200 | Function/extension HTTP task testi (Grup 5) | +| POST | `/api/test/error-endpoint` | 500 | Error boundary testi (Grup 4) | +| POST | `/api/test/slow-endpoint` | 200 (5s delay) | Timeout testi | +| POST | `/api/test/notification` | 200 | Bildirim testi | + +--- + +## CSX Interface Rehberi + +Integration testlerde kullanilan C# script interface'leri: + +| Interface | Kullanim Alani | Metodlar | +|-----------|---------------|----------| +| `ScriptBase, IMapping` | Task mapping (onEntries, onExits, onExecutionTasks), **exit** `onExecutionTasks`, shared transition gorevleri | `InputHandler(WorkflowTask, ScriptContext)`, `OutputHandler(ScriptContext)` | +| `ScriptBase, IConditionMapping` | Auto transition rule, view selection rule | `Handler(ScriptContext)` → `Task` | +| `ScriptBase, ITimerMapping` | Scheduled transition zamanlama | `Handler(ScriptContext)` → zamanlama bilgisi | +| `ScriptBase, ISubFlowMapping` | SubFlow data aktarimi | `InputHandler(ScriptContext)`, `OutputHandler(ScriptContext)` | +| `ScriptBase, IOutputHandler` | Function cikti birlestirme | `OutputHandler(ScriptContext)` | + +### Ortak ScriptBase Yardimci Metodlari + +| Metod | Aciklama | +|-------|----------| +| `HasProperty(obj, "propName")` | Dynamic nesnede property var mi kontrol eder | +| `LogInformation($"mesaj")` | Loglama yapar | +| `GetConfigValue("Key")` | Vault'tan konfigürasyon degeri okur | + +--- + +## Ozellik Kapsam Matrisi + +Her grubun hangi vNext ozelliklerini test ettigini gosteren matris: + +| Ozellik | G1 | G2 | G3 | G4 | G5 | G6 | G7 | G8 | G9 | G10 | +|---------|----|----|----|----|----|----|----|-----|-----|------| +| State tipleri (1/2/3) | X | X | X | X | X | X | X | X | X | X | +| State alt tipleri (1/2/3) | X | X | | X | | | X | X | | | +| **State alt tipleri (4/5/6)** | | | | | | | X | | | | +| SubFlow state (4) | | X | | | | | | | | | +| Wizard state (5) | | | | | X | | | | | | +| Manuel transition (0) | X | X | | | X | X | X | X | | X | +| Otomatik transition (1) | X | X | X | X | X | | | X | X | X | +| Zamanlanmis transition (2) | X | | | | | | | | | | +| triggerKind:10 (default) | X | | | | X | | | | | | +| onEntries | X | X | X | X | | | | X | X | X | +| onExits | X | | | | | | | | | | +| startTransition tasks | X | X | X | X | X | X | X | | X | X | +| IMapping | X | X | X | X | X | X | X | X | X | X | +| IConditionMapping | X | X | X | X | X | | | X | X | X | +| ITimerMapping | X | | | | | | | | | | +| ITransitionMapping | X | | | | | | | | | | +| ISubFlowMapping | | X | | | | | | | | | +| IOutputHandler | | | | | X | | | | | | +| HTTP Task (type:6) | | | X | X | | | | | | | +| Script Task (type:7) | X | X | X | X | X | X | X | X | X | X | +| StartFlow Task (11) | | | X | | | | | | | | +| GetInstanceData Task (13) | | | X | | | | | | | | +| **Dapr HTTP Task (1)** | | | | | | | | X | | | +| **Dapr Binding Task (2)** | | | | | | | | X | | | +| **Dapr Service Task (3)** | | | | | | | | X | | | +| **Dapr PubSub Task (4)** | | | | | | | | X | | | +| **Human Task (5)** | | | | | | | | X | | | +| **Notification Task (10)** | | | | | | | | X | | | +| **Trigger Transition Task (12)** | | | | | | | | X | | | +| **SubProcess Task (14)** | | | | | | | | X | | | +| **Get Instances Task (15)** | | | | | | | | X | | | +| Cancel transition | X | X | | | | | | | | | +| **Exit transition (`attributes.exit`)** | X | | | | | | | | | | +| **Schedule cancel (manuel)** | X | | | | | | | | | | +| **Timer reschedule ($self)** | X | | | | | | | | | | +| Shared transitions ($self) | | X | | | | | | | | | +| **Child-level shared transition** | | X | | | | | | | | | +| **SubFlow cancel final states (child/grandchild)** | | X | | | | | | | | | +| **Effective state (/functions/state, nested)** | | X | | | | | | | | | +| updateData ($self) | | X | | | | X | | | | | +| **UpdateData (SubFlow context)** | | X | | | | | | | | | +| Master schema | | | | | | X | | | | | +| Transition schema | | | | | | X | | | | | +| Field roles | | | | | | X | | | | | +| **queryRoles (workflow/state)** | X | | | | | | | | | | +| **Transition roles** | X | | | | | | | | | | +| Error boundary (task) | | | | X | | | | | | | +| Error boundary (state) | | | | X | | | | | | | +| Error boundary (workflow) | | | | X | | | | | | | +| Retry policy | | | | X | | | | | | | +| **Rollback (action:2)** | | | | X | | | | | | | +| **Log action (action:5, state)** | | | | X | | | | | | | +| **Notify action (action:4)** | | | | X | | | | | | | +| **timeoutPolicy (onTimeout)** | | | | X | | | | | | | +| **errorHandlerRule (errorTypes/errorCodes)** | | | | X | | | | | | | +| View (JSON/HTML/MD) | | | | | X | | | | | | +| Display modlari | | | | | X | | | | | | +| Function (single/multi) | | | | | X | | | | | | +| Extension (global/req) | | | | | X | | | | | | +| **Features referansi** | | | | | X | | | | | | +| Workflow timeout | | | | | | | X | | | | +| Idempotent start | X | | | | | | X | | | | +| Instance filtreleme | | | | | | | X | X | | | +| Sayfalama/Siralama | | | | | | | X | X | | | +| Cross-workflow task | | | X | | | | | | | | +| Complementary rules | X | | | | X | | | | | | +| **Dapr sidecar + bilesen YAML** | | | | | | | | X | | | +| **Flow tipi: Core (C)** | | | | | | | | | X | | +| **Flow tipi: SubProcess (P)** | | | | | | | | | X | | +| Flow tipi: Flow (F) | X | | X | X | X | X | X | X | | X | +| Flow tipi: SubFlow (S) | | X | | | | | | | | | +| **Version isolation (ayni key, farkli versiyon)** | | | | | | | | | | X | +| **Eski instance eski versiyonda kalir** | | | | | | | | | | X | + +--- + +## NOT: Schema Kisitlamalari + +1. **Rule-based view selection**: Mevcut `vnext-schema` versiyonu (0.0.23) state uzerinde sadece tekil `view` (viewDefinition) desteklemektedir. Runtime dokumantasyonunda anlatilan coklu `views` array'i (rule-based view selection) bu schema versiyonunda desteklenmemektedir. Bu nedenle `WebPlatformRule.csx` rule-based view selection yerine transition rule olarak kullanilmistir. Schema guncellendikten sonra bu test, `views` array'i ile yeniden yapilandirilabilir. + +2. **platformOverrides**: `view-definition.schema.json` icinde `platformOverrides` alani tanimli degildir. Bu nedenle platform bazli view override testleri mevcut schema ile yapilamaz. + +3. **Event transition (triggerType:3)**: Runtime dokumantasyonunda tanimlanan event-driven transition'lar icin test eklenmemistir. Bu, ileri asamada ayri bir senaryoda test edilebilir. diff --git a/docker-compose.yml b/docker-compose.yml index bd263a3..d5fb02a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,6 +30,8 @@ services: - "50001" - --config - /etc/dapr/config.yaml + - --resources-path + - /etc/dapr/components - --log-level - info volumes: diff --git a/etc/dapr/components/test-binding.yaml b/etc/dapr/components/test-binding.yaml new file mode 100644 index 0000000..8c75ab4 --- /dev/null +++ b/etc/dapr/components/test-binding.yaml @@ -0,0 +1,12 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: test-binding +spec: + type: bindings.http + version: v1 + metadata: + - name: url + value: "http://localhost:5000/api/test/process" + - name: direction + value: "output" diff --git a/etc/dapr/components/test-pubsub.yaml b/etc/dapr/components/test-pubsub.yaml new file mode 100644 index 0000000..9f028a5 --- /dev/null +++ b/etc/dapr/components/test-pubsub.yaml @@ -0,0 +1,8 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: test-pubsub +spec: + type: pubsub.in-memory + version: v1 + metadata: [] diff --git a/etc/docker/config/seed/integration-test-collection.json b/etc/docker/config/seed/integration-test-collection.json new file mode 100644 index 0000000..6c37587 --- /dev/null +++ b/etc/docker/config/seed/integration-test-collection.json @@ -0,0 +1,117 @@ +{ + "collection": { + "name": "integration-tests", + "description": "Mock API endpoints for vNext integration tests", + "color": "#10b981" + }, + "folders": [], + "mocks": [ + { + "httpMethod": "POST", + "route": "api/test/process", + "queryString": null, + "requestBody": "", + "statusCode": 200, + "responseBody": "{\n \"processId\": \"{{helpers.guid()}}\",\n \"status\": \"completed\",\n \"result\": {\n \"success\": true,\n \"message\": \"Process completed successfully\",\n \"processedAt\": \"{{helpers.now()}}\"\n }\n}", + "contentType": "application/json", + "description": "Generic process endpoint for HTTP task testing", + "delayMs": null, + "isActive": true, + "isSequential": false, + "folderIndex": null, + "rules": [], + "sequenceItems": [] + }, + { + "httpMethod": "POST", + "route": "api/test/validate", + "queryString": null, + "requestBody": "", + "statusCode": 200, + "responseBody": "{\n \"validationId\": \"{{helpers.guid()}}\",\n \"isValid\": true,\n \"validatedAt\": \"{{helpers.now()}}\",\n \"checks\": {\n \"formatCheck\": true,\n \"businessRuleCheck\": true,\n \"complianceCheck\": true\n }\n}", + "contentType": "application/json", + "description": "Validation endpoint for testing HTTP task with rules", + "delayMs": null, + "isActive": true, + "isSequential": false, + "folderIndex": null, + "rules": [ + { + "conditionField": "body.shouldFail", + "conditionOperator": "equals", + "conditionValue": "true", + "statusCode": 400, + "responseBody": "{\n \"validationId\": \"{{helpers.guid()}}\",\n \"isValid\": false,\n \"error\": {\n \"code\": \"VALIDATION_FAILED\",\n \"message\": \"Validation failed intentionally for testing\"\n }\n}", + "contentType": "application/json", + "priority": 0, + "responseHeaders": [] + } + ], + "sequenceItems": [] + }, + { + "httpMethod": "GET", + "route": "api/test/user-info", + "queryString": null, + "requestBody": "", + "statusCode": 200, + "responseBody": "{\n \"userId\": \"{{helpers.guid()}}\",\n \"name\": \"Test User\",\n \"email\": \"test@example.com\",\n \"role\": \"admin\",\n \"isActive\": true\n}", + "contentType": "application/json", + "description": "User info endpoint for function and extension testing", + "delayMs": null, + "isActive": true, + "isSequential": false, + "folderIndex": null, + "rules": [], + "sequenceItems": [] + }, + { + "httpMethod": "POST", + "route": "api/test/error-endpoint", + "queryString": null, + "requestBody": "", + "statusCode": 500, + "responseBody": "{\n \"error\": {\n \"code\": \"INTERNAL_ERROR\",\n \"message\": \"Intentional server error for error boundary testing\"\n }\n}", + "contentType": "application/json", + "description": "Always-failing endpoint for error boundary testing", + "delayMs": null, + "isActive": true, + "isSequential": false, + "folderIndex": null, + "rules": [], + "sequenceItems": [] + }, + { + "httpMethod": "POST", + "route": "api/test/slow-endpoint", + "queryString": null, + "requestBody": "", + "statusCode": 200, + "responseBody": "{\n \"result\": \"completed after delay\"\n}", + "contentType": "application/json", + "description": "Slow endpoint for timeout testing", + "delayMs": 5000, + "isActive": true, + "isSequential": false, + "folderIndex": null, + "rules": [], + "sequenceItems": [] + }, + { + "httpMethod": "POST", + "route": "api/test/notification", + "queryString": null, + "requestBody": "", + "statusCode": 200, + "responseBody": "{\n \"notificationId\": \"{{helpers.guid()}}\",\n \"sent\": true\n}", + "contentType": "application/json", + "description": "Notification endpoint for notification task testing", + "delayMs": null, + "isActive": true, + "isSequential": false, + "folderIndex": null, + "rules": [], + "sequenceItems": [] + } + ] +} diff --git a/package-lock.json b/package-lock.json index af36ced..54174b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,14 +10,14 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@burgan-tech/vnext-schema": "^0.0.38" + "@burgan-tech/vnext-schema": "^0.0.41" }, "bin": { "vnext-setup": "setup.js", "vnext-template": "init.js" }, "devDependencies": { - "@burgan-tech/vnext-schema": "^0.0.38", + "@burgan-tech/vnext-schema": "^0.0.41", "ajv": "^8.12.0", "ajv-formats": "^2.1.1" }, @@ -26,9 +26,9 @@ } }, "node_modules/@burgan-tech/vnext-schema": { - "version": "0.0.38", - "resolved": "https://registry.npmjs.org/@burgan-tech/vnext-schema/-/vnext-schema-0.0.38.tgz", - "integrity": "sha512-Lqrl5IjLVbJTirBSEK5w806PXjEJm6f/fR9rmvOMFkmvIII5vgFwKsL1cvfi28TIKp7UKwx/7vDZy71PQakyfA==", + "version": "0.0.41", + "resolved": "https://registry.npmjs.org/@burgan-tech/vnext-schema/-/vnext-schema-0.0.41.tgz", + "integrity": "sha512-F8fFZ5hYe75TSe8eRs/V7z7wtfGai1fXAZ+QltKPH/5WewJGB+xGPPYyWgmhj6jutGbIvT49w7Oe9CwNyMu9sg==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 46841b6..d2ac747 100644 --- a/package.json +++ b/package.json @@ -55,11 +55,11 @@ "node": ">=16.0.0" }, "devDependencies": { - "@burgan-tech/vnext-schema": "^0.0.38", + "@burgan-tech/vnext-schema": "^0.0.41", "ajv": "^8.12.0", "ajv-formats": "^2.1.1" }, "dependencies": { - "@burgan-tech/vnext-schema": "^0.0.38" + "@burgan-tech/vnext-schema": "^0.0.41" } } diff --git a/tests/Core/.gitignore b/tests/Core/.gitignore new file mode 100644 index 0000000..5c152d9 --- /dev/null +++ b/tests/Core/.gitignore @@ -0,0 +1,4 @@ +TestResults/ +*.runsettings.local +bin/ +obj/ diff --git a/tests/Core/.vscode/settings.json b/tests/Core/.vscode/settings.json new file mode 100644 index 0000000..60ab17a --- /dev/null +++ b/tests/Core/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + // Points the VS Code .NET Test Explorer to the local override runsettings. + // test.runsettings.local is git-ignored — edit it freely for personal settings. + // If the file is absent, the extension falls back to the default test.runsettings. + "dotnet.unitTests.runSettingsPath": "./test.runsettings.local" +} diff --git a/tests/Core/Config/appsettings.db-migrator.json b/tests/Core/Config/appsettings.db-migrator.json new file mode 100644 index 0000000..d1a3d3f --- /dev/null +++ b/tests/Core/Config/appsettings.db-migrator.json @@ -0,0 +1,42 @@ +{ + "ApplicationName": "vnext-db-migrator", + "ConnectionStrings": { + "Default": "Host=POSTGRES_HOST;Port=5432;Database=POSTGRES_DB;Username=postgres;Password=postgres;" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.EntityFrameworkCore.Database.Command": "Warning" + } + }, + "Runtime": { + "EnableSchemaMigration": true + }, + "Vault": { + "Enabled": false + }, + "Redis": { + "Mode": "Standalone", + "InstanceName": "workflow-api", + "ConnectionTimeout": 5000, + "DefaultDatabase": 0, + "Password": "", + "Ssl": false, + "Standalone": { + "EndPoints": ["REDIS_HOST:6379"] + }, + "RetryPolicy": { + "MaxRetries": 3, + "RetryTimeout": 1000 + } + }, + "Telemetry": { + "ServiceName": "vnext-db-migrator", + "ServiceNamespace": "BBT.Workflow.DbMigrator", + "ServiceVersion": "1.0.0", + "TracingEnabled": false, + "MetricsEnabled": false, + "LoggingEnabled": false + } +} diff --git a/tests/Core/Config/appsettings.execution.json b/tests/Core/Config/appsettings.execution.json new file mode 100644 index 0000000..18a8006 --- /dev/null +++ b/tests/Core/Config/appsettings.execution.json @@ -0,0 +1,57 @@ +{ + "ApplicationName": "vnext-execution-core-test", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "OrchestrationApi": { + "AppId": "vnext-app-core" + }, + "TriggerRetry": { + "MaxRetryAttempts": 3, + "RetryDelayMilliseconds": 2000, + "RetryOnStatusCodes": [409], + "UseJitter": true + }, + "ResponseCompression": { + "Enable": false + }, + "Redis": { + "Mode": "Standalone", + "InstanceName": "workflow-api-core-test", + "ConnectionTimeout": 5000, + "DefaultDatabase": 0, + "Password": "", + "Ssl": false, + "Standalone": { + "EndPoints": [ + "REDIS_HOST:6379" + ] + }, + "RetryPolicy": { + "MaxRetries": 3, + "RetryTimeout": 1000 + } + }, + "Telemetry": { + "ServiceName": "vnext-execution-app-core-test", + "ServiceNamespace": "BBT.Workflow.Execution", + "ServiceVersion": "1.0.0", + "TracingEnabled": false, + "MetricsEnabled": false, + "LoggingEnabled": false + }, + "AllowedHosts": "*", + "Vault": { + "Enabled": false + }, + "Dapr": { + "Notification": { + "ComponentName": "vnext-notification-binding", + "DefaultOperation": "create", + "TimeoutSeconds": 30 + } + } +} diff --git a/tests/Core/Config/appsettings.orchestration.json b/tests/Core/Config/appsettings.orchestration.json new file mode 100644 index 0000000..fbb7037 --- /dev/null +++ b/tests/Core/Config/appsettings.orchestration.json @@ -0,0 +1,98 @@ +{ + "ApplicationName": "vnext-core-test", + "ConnectionStrings": { + "Default": "Host=POSTGRES_HOST;Port=5432;Database=vNext_Core_Test;Username=postgres;Password=postgres;" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Microsoft.EntityFrameworkCore.Database.Command": "Warning" + } + }, + "vNextApi": { + "BaseUrl": "http://localhost:5000", + "ApiVersion": "1", + "TimeoutSeconds": 60, + "MaxRetryAttempts": 3, + "RetryDelayMilliseconds": 1000, + "CircuitBreakerFailureThreshold": 20, + "CircuitBreakerTimeoutSeconds": 60, + "EnableCircuitBreakerBypass": true, + "InternalOperationHeader": "X-Internal-Operation" + }, + "ResponseCompression": { + "Enable": false + }, + "Redis": { + "Mode": "Standalone", + "InstanceName": "workflow-api-core-test", + "ConnectionTimeout": 5000, + "DefaultDatabase": 0, + "Password": "", + "Ssl": false, + "Standalone": { + "EndPoints": [ + "REDIS_HOST:6379" + ] + }, + "RetryPolicy": { + "MaxRetries": 3, + "RetryTimeout": 1000 + } + }, + "Telemetry": { + "ServiceName": "vnext-app-core-test", + "ServiceNamespace": "BBT.Workflow.Orchestration", + "ServiceVersion": "1.0.0", + "TracingEnabled": false, + "MetricsEnabled": false, + "LoggingEnabled": false + }, + "AllowedHosts": "*", + "TaskFactory": { + "UseObjectPooling": false, + "MaxPoolSize": 50, + "InitialPoolSize": 5, + "EnableMetrics": false, + "PooledTaskTypes": [ + "ConditionTask", + "DaprBindingTask", + "DaprHttpEndpointTask", + "DaprPubSubTask", + "DaprServiceTask", + "DirectTriggerTask", + "GetInstanceDataTask", + "HttpTask", + "HumanTask", + "NotificationTask", + "ScriptTask", + "StartTask", + "SubProcessTask", + "TimerTask" + ] + }, + "ExecutionApi": { + "AppId": "vnext-execution-app-core" + }, + "Vault": { + "Enabled": false + }, + "ClickHouse": { + "Enabled": false + }, + "ResultRetry": { + "MaxRetryAttempts": 3, + "RetryDelayMilliseconds": 50, + "UseJitter": true, + "BackoffType": "Constant", + "RetryOnErrorCodes": [ + "TransitionLocked", + "Locked" + ] + }, + "ServiceDiscovery": { + "Enabled": false + }, + "MocklabBaseUrl": "http://localhost:3001" +} diff --git a/tests/Core/Core.IntegrationTests.csproj b/tests/Core/Core.IntegrationTests.csproj new file mode 100644 index 0000000..7555694 --- /dev/null +++ b/tests/Core/Core.IntegrationTests.csproj @@ -0,0 +1,43 @@ + + + + net10.0 + enable + enable + false + Core.IntegrationTests + + $(MSBuildProjectDirectory)\test.runsettings.local + $(MSBuildProjectDirectory)\test.runsettings + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/tests/Core/Helpers/TestDataBuilder.cs b/tests/Core/Helpers/TestDataBuilder.cs new file mode 100644 index 0000000..4ea9e37 --- /dev/null +++ b/tests/Core/Helpers/TestDataBuilder.cs @@ -0,0 +1,45 @@ +using VNext.Testing.Sdk.Builders; + +namespace Core.IntegrationTests.Helpers; + +/// +/// Core-specific factory methods for building vNext workflow instance payloads. +/// Add static methods here for each workflow your domain tests. +/// +/// Inherited helpers from : +/// - BuildInstancePayload(key, tags, attributes) +/// - BuildTransitionBody(attributes) +/// - UniqueKey(prefix) +/// - DeterministicKey(prefix, parts) +/// - BuildCustomWorkingHours(schedule) +/// - DefaultWeekdaySchedule(...) +/// +public class TestDataBuilder : TestDataBuilderBase +{ + // ------------------------------------------------------------------------- + // Example: replace with your domain's workflow payloads + // ------------------------------------------------------------------------- + + /// + /// Example: start a "my-workflow" instance. + /// Replace with your domain's actual workflow names and attributes. + /// + public static object MyWorkflow(string userId, string startDateTime, string endDateTime) + { + return BuildInstancePayload( + key: DeterministicKey("my-wf", userId, startDateTime), + tags: ["my-workflow"], + attributes: new + { + userId, + startDateTime, + endDateTime + }); + } + + /// + /// Example: build an update/cancel transition body. + /// + public static object UpdateAttributes(object attributes) => + BuildTransitionBody(attributes); +} diff --git a/tests/Core/Infrastructure/DaprComponents/db-migrator/config.yaml b/tests/Core/Infrastructure/DaprComponents/db-migrator/config.yaml new file mode 100644 index 0000000..8ff5076 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/db-migrator/config.yaml @@ -0,0 +1,11 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-config +spec: + type: configuration.redis + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" diff --git a/tests/Core/Infrastructure/DaprComponents/db-migrator/lock.yaml b/tests/Core/Infrastructure/DaprComponents/db-migrator/lock.yaml new file mode 100644 index 0000000..f718528 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/db-migrator/lock.yaml @@ -0,0 +1,14 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-lock +spec: + type: lock.redis + version: v1 + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" + - name: keyPrefix + value: "vnext" diff --git a/tests/Core/Infrastructure/DaprComponents/db-migrator/secretstore.yaml b/tests/Core/Infrastructure/DaprComponents/db-migrator/secretstore.yaml new file mode 100644 index 0000000..d340ae8 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/db-migrator/secretstore.yaml @@ -0,0 +1,22 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-secret +spec: + type: secretstores.hashicorp.vault + version: v1 + metadata: + - name: vaultAddr + value: http://VAULT_HOST:8200 + - name: vaultToken + value: "admin" + - name: skipVerify + value: true + - name: vaultKVUsePrefix + value: false + - name: vaultKVPrefix + value: workflow-secret + - name: enginePath + value: "secret" + - name: vaultValueType + value: "map" diff --git a/tests/Core/Infrastructure/DaprComponents/execution/config.yaml b/tests/Core/Infrastructure/DaprComponents/execution/config.yaml new file mode 100644 index 0000000..8ff5076 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/execution/config.yaml @@ -0,0 +1,11 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-config +spec: + type: configuration.redis + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" diff --git a/tests/Core/Infrastructure/DaprComponents/execution/lock.yaml b/tests/Core/Infrastructure/DaprComponents/execution/lock.yaml new file mode 100644 index 0000000..f718528 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/execution/lock.yaml @@ -0,0 +1,14 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-lock +spec: + type: lock.redis + version: v1 + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" + - name: keyPrefix + value: "vnext" diff --git a/tests/Core/Infrastructure/DaprComponents/execution/notification-binding.yaml b/tests/Core/Infrastructure/DaprComponents/execution/notification-binding.yaml new file mode 100644 index 0000000..2889069 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/execution/notification-binding.yaml @@ -0,0 +1,10 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-notification-binding +spec: + type: bindings.http + version: v1 + metadata: + - name: url + value: http://MOCKOON_HOST:3001/api/notification/send diff --git a/tests/Core/Infrastructure/DaprComponents/execution/pubsub-broadcast.yaml b/tests/Core/Infrastructure/DaprComponents/execution/pubsub-broadcast.yaml new file mode 100644 index 0000000..cc86671 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/execution/pubsub-broadcast.yaml @@ -0,0 +1,11 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-pubsub-broadcast +spec: + type: pubsub.redis + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" diff --git a/tests/Core/Infrastructure/DaprComponents/execution/pubsub.yaml b/tests/Core/Infrastructure/DaprComponents/execution/pubsub.yaml new file mode 100644 index 0000000..d0f804f --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/execution/pubsub.yaml @@ -0,0 +1,11 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-pubsub +spec: + type: pubsub.redis + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" diff --git a/tests/Core/Infrastructure/DaprComponents/execution/secretstore.yaml b/tests/Core/Infrastructure/DaprComponents/execution/secretstore.yaml new file mode 100644 index 0000000..d340ae8 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/execution/secretstore.yaml @@ -0,0 +1,22 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-secret +spec: + type: secretstores.hashicorp.vault + version: v1 + metadata: + - name: vaultAddr + value: http://VAULT_HOST:8200 + - name: vaultToken + value: "admin" + - name: skipVerify + value: true + - name: vaultKVUsePrefix + value: false + - name: vaultKVPrefix + value: workflow-secret + - name: enginePath + value: "secret" + - name: vaultValueType + value: "map" diff --git a/tests/Core/Infrastructure/DaprComponents/execution/state.yaml b/tests/Core/Infrastructure/DaprComponents/execution/state.yaml new file mode 100644 index 0000000..cc20d5e --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/execution/state.yaml @@ -0,0 +1,16 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-state +spec: + type: state.redis + version: v1 + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" + - name: actorStateStore + value: "false" + - name: keyPrefix + value: "vnext" diff --git a/tests/Core/Infrastructure/DaprComponents/orchestration/config.yaml b/tests/Core/Infrastructure/DaprComponents/orchestration/config.yaml new file mode 100644 index 0000000..8ff5076 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/orchestration/config.yaml @@ -0,0 +1,11 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-config +spec: + type: configuration.redis + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" diff --git a/tests/Core/Infrastructure/DaprComponents/orchestration/definition-component-published-subscription.yaml b/tests/Core/Infrastructure/DaprComponents/orchestration/definition-component-published-subscription.yaml new file mode 100644 index 0000000..1753fd8 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/orchestration/definition-component-published-subscription.yaml @@ -0,0 +1,8 @@ +apiVersion: dapr.io/v1alpha1 +kind: Subscription +metadata: + name: vnext-definition-component-published-subscription +spec: + topic: definition.component.published + route: /api/v1/utilities/cache/component-published + pubsubname: vnext-pubsub-broadcast diff --git a/tests/Core/Infrastructure/DaprComponents/orchestration/invalidate-cache-subscription.yaml b/tests/Core/Infrastructure/DaprComponents/orchestration/invalidate-cache-subscription.yaml new file mode 100644 index 0000000..acc6157 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/orchestration/invalidate-cache-subscription.yaml @@ -0,0 +1,8 @@ +apiVersion: dapr.io/v1alpha1 +kind: Subscription +metadata: + name: vnext-definition-cache-invalidation-subscription +spec: + topic: definition.cache.invalidate + route: /api/v1/utilities/cache/invalidate + pubsubname: vnext-pubsub-broadcast diff --git a/tests/Core/Infrastructure/DaprComponents/orchestration/lock.yaml b/tests/Core/Infrastructure/DaprComponents/orchestration/lock.yaml new file mode 100644 index 0000000..f718528 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/orchestration/lock.yaml @@ -0,0 +1,14 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-lock +spec: + type: lock.redis + version: v1 + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" + - name: keyPrefix + value: "vnext" diff --git a/tests/Core/Infrastructure/DaprComponents/orchestration/pubsub-broadcast.yaml b/tests/Core/Infrastructure/DaprComponents/orchestration/pubsub-broadcast.yaml new file mode 100644 index 0000000..cc86671 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/orchestration/pubsub-broadcast.yaml @@ -0,0 +1,11 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-pubsub-broadcast +spec: + type: pubsub.redis + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" diff --git a/tests/Core/Infrastructure/DaprComponents/orchestration/pubsub.yaml b/tests/Core/Infrastructure/DaprComponents/orchestration/pubsub.yaml new file mode 100644 index 0000000..d0f804f --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/orchestration/pubsub.yaml @@ -0,0 +1,11 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-pubsub +spec: + type: pubsub.redis + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" diff --git a/tests/Core/Infrastructure/DaprComponents/orchestration/secretstore.yaml b/tests/Core/Infrastructure/DaprComponents/orchestration/secretstore.yaml new file mode 100644 index 0000000..d340ae8 --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/orchestration/secretstore.yaml @@ -0,0 +1,22 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-secret +spec: + type: secretstores.hashicorp.vault + version: v1 + metadata: + - name: vaultAddr + value: http://VAULT_HOST:8200 + - name: vaultToken + value: "admin" + - name: skipVerify + value: true + - name: vaultKVUsePrefix + value: false + - name: vaultKVPrefix + value: workflow-secret + - name: enginePath + value: "secret" + - name: vaultValueType + value: "map" diff --git a/tests/Core/Infrastructure/DaprComponents/orchestration/state.yaml b/tests/Core/Infrastructure/DaprComponents/orchestration/state.yaml new file mode 100644 index 0000000..cc20d5e --- /dev/null +++ b/tests/Core/Infrastructure/DaprComponents/orchestration/state.yaml @@ -0,0 +1,16 @@ +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: vnext-state +spec: + type: state.redis + version: v1 + metadata: + - name: redisHost + value: REDIS_HOST:6379 + - name: redisPassword + value: "" + - name: actorStateStore + value: "false" + - name: keyPrefix + value: "vnext" diff --git a/tests/Core/Infrastructure/IntegrationTestBase.cs b/tests/Core/Infrastructure/IntegrationTestBase.cs new file mode 100644 index 0000000..c5db569 --- /dev/null +++ b/tests/Core/Infrastructure/IntegrationTestBase.cs @@ -0,0 +1,35 @@ +using VNext.Testing.Sdk.Client; + +namespace Core.IntegrationTests.Infrastructure; + +/// +/// Base class for all Core integration tests. +/// Inherits shared fixtures from . +/// +[Collection("VNextIntegration")] +public abstract class IntegrationTestBase + : VNext.Testing.Sdk.Infrastructure.IntegrationTestBase +{ + protected IntegrationTestBase(VNextTestEnvironment environment) : base(environment) { } + + /// + /// Creates a client pre-configured for the "core" domain. + /// Override to add auth headers or custom behaviour. + /// + protected override VNextApiClient CreateApiClient(string baseUrl) => + new(new VNextApiClientOptions + { + BaseUrl = baseUrl, + Domain = "core", + ApiVersion = "1" + }); +} + +/// +/// xUnit collection definition — shares one across all +/// test classes in this project. +/// +[CollectionDefinition("VNextIntegration")] +public class VNextIntegrationCollection : ICollectionFixture +{ +} diff --git a/tests/Core/Infrastructure/MocklabSeed/.gitkeep b/tests/Core/Infrastructure/MocklabSeed/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/Core/Infrastructure/VNextTestEnvironment.cs b/tests/Core/Infrastructure/VNextTestEnvironment.cs new file mode 100644 index 0000000..39bee1a --- /dev/null +++ b/tests/Core/Infrastructure/VNextTestEnvironment.cs @@ -0,0 +1,94 @@ +using VNext.Testing.Sdk.Infrastructure; + +namespace Core.IntegrationTests.Infrastructure; + +/// +/// Domain-specific test environment for Core. +/// Override any virtual property or method from +/// to customise the Docker stack for this domain. +/// +public class VNextTestEnvironment : VNext.Testing.Sdk.Infrastructure.VNextTestEnvironment +{ + // ------------------------------------------------------------------------- + // Required — set these to match your domain + // ------------------------------------------------------------------------- + + /// APP_DOMAIN value passed to vNext containers. + protected override string Domain => "core"; + + /// PostgreSQL database name created during test setup. + protected override string DatabaseName => "vNext_Core_Test"; + + /// + /// Base image for vNext orchestrator/execution (without the role suffix). + /// Override if your team publishes to a different registry. + /// + protected override string VNextImage => "ghcr.io/burgan-tech/vnext"; + + /// + /// Image tag for vNext containers. Defaults to "latest". + /// Override to pin a specific release, e.g. "1.4.2" or "sha-abc1234". + /// + // protected override string VNextImageVersion => "latest"; + + /// + /// Full image for the db-migrator worker. Defaults to {VNextImage}/db-migrator:{VNextImageVersion}. + /// Override if your migrator image lives at a different path or tag. + /// + // protected override string DbMigratorImage => $"{VNextImage}/db-migrator:{VNextImageVersion}"; + + /// + /// Mocklab container image. Defaults to "ghcr.io/burgan-tech/mocklab:latest". + /// Override to pin a specific version. + /// + // protected override string MocklabImage => "ghcr.io/burgan-tech/mocklab:latest"; + + /// + /// Host-side directory bind-mounted to /app/seed in the Mocklab container. + /// Defaults to Infrastructure/MocklabSeed/ relative to the test output directory. + /// Override to point to a different seed data location. + /// + // protected override string MocklabSeedDirectory => + // Path.Combine(Directory.GetCurrentDirectory(), "Infrastructure", "MocklabSeed"); + + // ------------------------------------------------------------------------- + // Optional — uncomment and override as needed + // ------------------------------------------------------------------------- + + // /// Disable Mocklab if your domain doesn't need mock HTTP services. + // protected override bool EnableMocklab => false; + + // /// Disable domain publish if definitions are managed externally. + // protected override bool EnableDomainPublish => false; + + // /// + // /// Called after the full stack is ready. Start additional services here + // /// (e.g. a custom microservice, a second mock server, a message broker). + // /// Containers started here must be disposed in a DisposeAsync override. + // /// + // protected override async Task OnAfterEnvironmentReadyAsync() + // { + // // _myService = new ContainerBuilder() + // // .WithImage("my-registry/my-service:latest") + // // .WithNetwork(_network) + // // .WithNetworkAliases("test-my-service") + // // .Build(); + // // await _myService.StartAsync(); + // } + + // /// Adds domain-specific Vault secrets on top of the SDK defaults. + // protected override Dictionary> GetVaultSecrets() + // { + // var secrets = base.GetVaultSecrets(); + // secrets["core-secret"] = new() { ["ApiKey"] = "my-test-api-key" }; + // return secrets; + // } + + // /// Extends the orchestrator environment variables. + // protected override Dictionary GetOrchestratorEnvironment() + // { + // var env = base.GetOrchestratorEnvironment(); + // env["MY_CUSTOM_VAR"] = "value"; + // return env; + // } +} diff --git a/tests/Core/Tests/SmokeTests.cs b/tests/Core/Tests/SmokeTests.cs new file mode 100644 index 0000000..79314b6 --- /dev/null +++ b/tests/Core/Tests/SmokeTests.cs @@ -0,0 +1,28 @@ +using Core.IntegrationTests.Infrastructure; + +namespace Core.IntegrationTests.Tests; + +/// +/// Smoke tests — verify the environment is up and the API is reachable. +/// These run first and catch infrastructure issues before domain tests execute. +/// +public class SmokeTests : IntegrationTestBase +{ + public SmokeTests(VNextTestEnvironment environment) : base(environment) { } + + [Fact] + public async Task HealthEndpoint_Returns200() + { + var response = await Api.GetRawAsync("/health"); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task ListInstances_ReturnsValidResponse() + { + // Replace "my-workflow" with a workflow name that exists in your domain. + var response = await Api.ListInstancesAsync("my-workflow"); + Assert.True(response.Body.ValueKind != System.Text.Json.JsonValueKind.Null, + "Expected a non-null response from ListInstances"); + } +} diff --git a/tests/Core/test.runsettings b/tests/Core/test.runsettings new file mode 100644 index 0000000..405c925 --- /dev/null +++ b/tests/Core/test.runsettings @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/vnext-example.sln b/vnext-example.sln new file mode 100644 index 0000000..77cac5e --- /dev/null +++ b/vnext-example.sln @@ -0,0 +1,32 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{5C35D9BE-388A-8745-CD5F-BB8E361A8720}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.IntegrationTests", "tests\Core\Core.IntegrationTests.csproj", "{E4963139-E4EB-2D4C-E609-219AB4596A8A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4963139-E4EB-2D4C-E609-219AB4596A8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4963139-E4EB-2D4C-E609-219AB4596A8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4963139-E4EB-2D4C-E609-219AB4596A8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4963139-E4EB-2D4C-E609-219AB4596A8A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {5C35D9BE-388A-8745-CD5F-BB8E361A8720} = {0AB3BF05-4346-4AA6-1389-037BE0695223} + {E4963139-E4EB-2D4C-E609-219AB4596A8A} = {5C35D9BE-388A-8745-CD5F-BB8E361A8720} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {59B7D2E4-3C16-49D7-A46B-6E222F7AF9E3} + EndGlobalSection +EndGlobal diff --git a/vnext.config.json b/vnext.config.json index 913b5ce..60a37d4 100644 --- a/vnext.config.json +++ b/vnext.config.json @@ -3,7 +3,7 @@ "description": "core Domain Definition Configuration", "domain": "core", "runtimeVersion": "0.0.32", - "schemaVersion": "0.0.38", + "schemaVersion": "0.0.41", "paths": { "componentsRoot": "core", "tasks": "Tasks",