diff --git a/packagerepo/backend/workflows/auth_login.backup.json b/packagerepo/backend/workflows/auth_login.backup.json new file mode 100644 index 000000000..c8522e111 --- /dev/null +++ b/packagerepo/backend/workflows/auth_login.backup.json @@ -0,0 +1,82 @@ +{ + "name": "Authenticate User", + "description": "Login and generate JWT token", + "version": "1.0.0", + "nodes": [ + { + "id": "parse_body", + "type": "packagerepo.parse_json", + "parameters": { + "input": "$request.body", + "out": "credentials" + } + }, + { + "id": "validate_fields", + "type": "logic.if", + "parameters": { + "condition": "$credentials.username == null || $credentials.password == null", + "then": "error_invalid_request", + "else": "verify_password" + } + }, + { + "id": "verify_password", + "type": "packagerepo.auth_verify_password", + "parameters": { + "username": "$credentials.username", + "password": "$credentials.password", + "out": "user" + } + }, + { + "id": "check_verified", + "type": "logic.if", + "parameters": { + "condition": "$user == null", + "then": "error_unauthorized", + "else": "generate_token" + } + }, + { + "id": "generate_token", + "type": "packagerepo.auth_generate_jwt", + "parameters": { + "subject": "$user.username", + "scopes": "$user.scopes", + "expires_in": 86400, + "out": "token" + } + }, + { + "id": "respond_success", + "type": "packagerepo.respond_json", + "parameters": { + "body": { + "ok": true, + "token": "$token", + "username": "$user.username", + "scopes": "$user.scopes", + "expires_in": 86400 + }, + "status": 200 + } + }, + { + "id": "error_invalid_request", + "type": "packagerepo.respond_error", + "parameters": { + "message": "Missing username or password", + "status": 400 + } + }, + { + "id": "error_unauthorized", + "type": "packagerepo.respond_error", + "parameters": { + "message": "Invalid username or password", + "status": 401 + } + } + ] +} diff --git a/packagerepo/backend/workflows/auth_login.json b/packagerepo/backend/workflows/auth_login.json index c8522e111..d2fdfe8fc 100644 --- a/packagerepo/backend/workflows/auth_login.json +++ b/packagerepo/backend/workflows/auth_login.json @@ -1,82 +1,157 @@ { "name": "Authenticate User", - "description": "Login and generate JWT token", - "version": "1.0.0", + "active": false, "nodes": [ { "id": "parse_body", + "name": "Parse Body", "type": "packagerepo.parse_json", + "typeVersion": 1, + "position": [ + 100, + 100 + ], "parameters": { - "input": "$request.body", - "out": "credentials" + "parameters": { + "input": "$request.body", + "out": "credentials" + } } }, { "id": "validate_fields", + "name": "Validate Fields", "type": "logic.if", + "typeVersion": 1, + "position": [ + 400, + 100 + ], "parameters": { - "condition": "$credentials.username == null || $credentials.password == null", - "then": "error_invalid_request", - "else": "verify_password" + "parameters": { + "condition": "$credentials.username == null || $credentials.password == null", + "then": "error_invalid_request", + "else": "verify_password" + } } }, { "id": "verify_password", + "name": "Verify Password", "type": "packagerepo.auth_verify_password", + "typeVersion": 1, + "position": [ + 700, + 100 + ], "parameters": { - "username": "$credentials.username", - "password": "$credentials.password", - "out": "user" + "parameters": { + "username": "$credentials.username", + "password": "$credentials.password", + "out": "user" + } } }, { "id": "check_verified", + "name": "Check Verified", "type": "logic.if", + "typeVersion": 1, + "position": [ + 100, + 300 + ], "parameters": { - "condition": "$user == null", - "then": "error_unauthorized", - "else": "generate_token" + "parameters": { + "condition": "$user == null", + "then": "error_unauthorized", + "else": "generate_token" + } } }, { "id": "generate_token", + "name": "Generate Token", "type": "packagerepo.auth_generate_jwt", + "typeVersion": 1, + "position": [ + 400, + 300 + ], "parameters": { - "subject": "$user.username", - "scopes": "$user.scopes", - "expires_in": 86400, - "out": "token" + "parameters": { + "subject": "$user.username", + "scopes": "$user.scopes", + "expires_in": 86400, + "out": "token" + } } }, { "id": "respond_success", + "name": "Respond Success", "type": "packagerepo.respond_json", + "typeVersion": 1, + "position": [ + 700, + 300 + ], "parameters": { - "body": { - "ok": true, - "token": "$token", - "username": "$user.username", - "scopes": "$user.scopes", - "expires_in": 86400 - }, - "status": 200 + "parameters": { + "body": { + "ok": true, + "token": "$token", + "username": "$user.username", + "scopes": "$user.scopes", + "expires_in": 86400 + }, + "status": 200 + } } }, { "id": "error_invalid_request", + "name": "Error Invalid Request", "type": "packagerepo.respond_error", + "typeVersion": 1, + "position": [ + 100, + 500 + ], "parameters": { - "message": "Missing username or password", - "status": 400 + "parameters": { + "message": "Missing username or password", + "status": 400 + } } }, { "id": "error_unauthorized", + "name": "Error Unauthorized", "type": "packagerepo.respond_error", + "typeVersion": 1, + "position": [ + 400, + 500 + ], "parameters": { - "message": "Invalid username or password", - "status": 401 + "parameters": { + "message": "Invalid username or password", + "status": 401 + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Login and generate JWT token" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packagerepo/backend/workflows/download_artifact.backup.json b/packagerepo/backend/workflows/download_artifact.backup.json new file mode 100644 index 000000000..329258779 --- /dev/null +++ b/packagerepo/backend/workflows/download_artifact.backup.json @@ -0,0 +1,87 @@ +{ + "name": "Download Artifact", + "description": "Download a package artifact blob", + "version": "1.0.0", + "nodes": [ + { + "id": "parse_path", + "type": "packagerepo.parse_path", + "parameters": { + "path": "$request.path", + "pattern": "/v1/:namespace/:name/:version/:variant/blob", + "out": "entity" + } + }, + { + "id": "normalize", + "type": "packagerepo.normalize_entity", + "parameters": { + "entity": "$entity", + "out": "normalized" + } + }, + { + "id": "get_meta", + "type": "packagerepo.kv_get", + "parameters": { + "key": "artifact/$entity.namespace/$entity.name/$entity.version/$entity.variant", + "out": "metadata" + } + }, + { + "id": "check_exists", + "type": "logic.if", + "parameters": { + "condition": "$metadata == null", + "then": "error_not_found", + "else": "read_blob" + } + }, + { + "id": "read_blob", + "type": "packagerepo.blob_get", + "parameters": { + "digest": "$metadata.digest", + "out": "blob_data" + } + }, + { + "id": "check_blob_exists", + "type": "logic.if", + "parameters": { + "condition": "$blob_data == null", + "then": "error_blob_missing", + "else": "respond_blob" + } + }, + { + "id": "respond_blob", + "type": "packagerepo.respond_blob", + "parameters": { + "data": "$blob_data", + "headers": { + "Content-Type": "application/octet-stream", + "Content-Digest": "sha-256=$metadata.digest", + "Content-Length": "$metadata.size" + }, + "status": 200 + } + }, + { + "id": "error_not_found", + "type": "packagerepo.respond_error", + "parameters": { + "message": "Artifact not found", + "status": 404 + } + }, + { + "id": "error_blob_missing", + "type": "packagerepo.respond_error", + "parameters": { + "message": "Artifact blob data missing", + "status": 500 + } + } + ] +} diff --git a/packagerepo/backend/workflows/download_artifact.json b/packagerepo/backend/workflows/download_artifact.json index 329258779..a8d691462 100644 --- a/packagerepo/backend/workflows/download_artifact.json +++ b/packagerepo/backend/workflows/download_artifact.json @@ -1,87 +1,170 @@ { "name": "Download Artifact", - "description": "Download a package artifact blob", - "version": "1.0.0", + "active": false, "nodes": [ { "id": "parse_path", + "name": "Parse Path", "type": "packagerepo.parse_path", + "typeVersion": 1, + "position": [ + 100, + 100 + ], "parameters": { - "path": "$request.path", - "pattern": "/v1/:namespace/:name/:version/:variant/blob", - "out": "entity" + "parameters": { + "path": "$request.path", + "pattern": "/v1/:namespace/:name/:version/:variant/blob", + "out": "entity" + } } }, { "id": "normalize", + "name": "Normalize", "type": "packagerepo.normalize_entity", + "typeVersion": 1, + "position": [ + 400, + 100 + ], "parameters": { - "entity": "$entity", - "out": "normalized" + "parameters": { + "entity": "$entity", + "out": "normalized" + } } }, { "id": "get_meta", + "name": "Get Meta", "type": "packagerepo.kv_get", + "typeVersion": 1, + "position": [ + 700, + 100 + ], "parameters": { - "key": "artifact/$entity.namespace/$entity.name/$entity.version/$entity.variant", - "out": "metadata" + "parameters": { + "key": "artifact/$entity.namespace/$entity.name/$entity.version/$entity.variant", + "out": "metadata" + } } }, { "id": "check_exists", + "name": "Check Exists", "type": "logic.if", + "typeVersion": 1, + "position": [ + 100, + 300 + ], "parameters": { - "condition": "$metadata == null", - "then": "error_not_found", - "else": "read_blob" + "parameters": { + "condition": "$metadata == null", + "then": "error_not_found", + "else": "read_blob" + } } }, { "id": "read_blob", + "name": "Read Blob", "type": "packagerepo.blob_get", + "typeVersion": 1, + "position": [ + 400, + 300 + ], "parameters": { - "digest": "$metadata.digest", - "out": "blob_data" + "parameters": { + "digest": "$metadata.digest", + "out": "blob_data" + } } }, { "id": "check_blob_exists", + "name": "Check Blob Exists", "type": "logic.if", + "typeVersion": 1, + "position": [ + 700, + 300 + ], "parameters": { - "condition": "$blob_data == null", - "then": "error_blob_missing", - "else": "respond_blob" + "parameters": { + "condition": "$blob_data == null", + "then": "error_blob_missing", + "else": "respond_blob" + } } }, { "id": "respond_blob", + "name": "Respond Blob", "type": "packagerepo.respond_blob", + "typeVersion": 1, + "position": [ + 100, + 500 + ], "parameters": { - "data": "$blob_data", - "headers": { - "Content-Type": "application/octet-stream", - "Content-Digest": "sha-256=$metadata.digest", - "Content-Length": "$metadata.size" - }, - "status": 200 + "parameters": { + "data": "$blob_data", + "headers": { + "Content-Type": "application/octet-stream", + "Content-Digest": "sha-256=$metadata.digest", + "Content-Length": "$metadata.size" + }, + "status": 200 + } } }, { "id": "error_not_found", + "name": "Error Not Found", "type": "packagerepo.respond_error", + "typeVersion": 1, + "position": [ + 400, + 500 + ], "parameters": { - "message": "Artifact not found", - "status": 404 + "parameters": { + "message": "Artifact not found", + "status": 404 + } } }, { "id": "error_blob_missing", + "name": "Error Blob Missing", "type": "packagerepo.respond_error", + "typeVersion": 1, + "position": [ + 700, + 500 + ], "parameters": { - "message": "Artifact blob data missing", - "status": 500 + "parameters": { + "message": "Artifact blob data missing", + "status": 500 + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Download a package artifact blob" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packagerepo/backend/workflows/list_versions.backup.json b/packagerepo/backend/workflows/list_versions.backup.json new file mode 100644 index 000000000..18f0fc751 --- /dev/null +++ b/packagerepo/backend/workflows/list_versions.backup.json @@ -0,0 +1,71 @@ +{ + "name": "List Package Versions", + "description": "List all versions of a package", + "version": "1.0.0", + "nodes": [ + { + "id": "parse_path", + "type": "packagerepo.parse_path", + "parameters": { + "path": "$request.path", + "pattern": "/v1/:namespace/:name/versions", + "out": "entity" + } + }, + { + "id": "normalize", + "type": "packagerepo.normalize_entity", + "parameters": { + "entity": "$entity", + "out": "normalized" + } + }, + { + "id": "query_index", + "type": "packagerepo.index_query", + "parameters": { + "key": "$entity.namespace/$entity.name", + "out": "versions" + } + }, + { + "id": "check_exists", + "type": "logic.if", + "parameters": { + "condition": "$versions == null", + "then": "error_not_found", + "else": "enrich_versions" + } + }, + { + "id": "enrich_versions", + "type": "packagerepo.enrich_version_list", + "parameters": { + "namespace": "$entity.namespace", + "name": "$entity.name", + "versions": "$versions", + "out": "enriched" + } + }, + { + "id": "respond_json", + "type": "packagerepo.respond_json", + "parameters": { + "body": { + "namespace": "$entity.namespace", + "name": "$entity.name", + "versions": "$enriched" + }, + "status": 200 + } + }, + { + "id": "error_not_found", + "type": "packagerepo.respond_error", + "parameters": { + "message": "Package not found", + "status": 404 + } + } + ] +} diff --git a/packagerepo/backend/workflows/list_versions.json b/packagerepo/backend/workflows/list_versions.json index 18f0fc751..20c7340a2 100644 --- a/packagerepo/backend/workflows/list_versions.json +++ b/packagerepo/backend/workflows/list_versions.json @@ -1,71 +1,138 @@ { "name": "List Package Versions", - "description": "List all versions of a package", - "version": "1.0.0", + "active": false, "nodes": [ { "id": "parse_path", + "name": "Parse Path", "type": "packagerepo.parse_path", + "typeVersion": 1, + "position": [ + 100, + 100 + ], "parameters": { - "path": "$request.path", - "pattern": "/v1/:namespace/:name/versions", - "out": "entity" + "parameters": { + "path": "$request.path", + "pattern": "/v1/:namespace/:name/versions", + "out": "entity" + } } }, { "id": "normalize", + "name": "Normalize", "type": "packagerepo.normalize_entity", + "typeVersion": 1, + "position": [ + 400, + 100 + ], "parameters": { - "entity": "$entity", - "out": "normalized" + "parameters": { + "entity": "$entity", + "out": "normalized" + } } }, { "id": "query_index", + "name": "Query Index", "type": "packagerepo.index_query", + "typeVersion": 1, + "position": [ + 700, + 100 + ], "parameters": { - "key": "$entity.namespace/$entity.name", - "out": "versions" + "parameters": { + "key": "$entity.namespace/$entity.name", + "out": "versions" + } } }, { "id": "check_exists", + "name": "Check Exists", "type": "logic.if", + "typeVersion": 1, + "position": [ + 100, + 300 + ], "parameters": { - "condition": "$versions == null", - "then": "error_not_found", - "else": "enrich_versions" + "parameters": { + "condition": "$versions == null", + "then": "error_not_found", + "else": "enrich_versions" + } } }, { "id": "enrich_versions", + "name": "Enrich Versions", "type": "packagerepo.enrich_version_list", + "typeVersion": 1, + "position": [ + 400, + 300 + ], "parameters": { - "namespace": "$entity.namespace", - "name": "$entity.name", - "versions": "$versions", - "out": "enriched" + "parameters": { + "namespace": "$entity.namespace", + "name": "$entity.name", + "versions": "$versions", + "out": "enriched" + } } }, { "id": "respond_json", + "name": "Respond Json", "type": "packagerepo.respond_json", + "typeVersion": 1, + "position": [ + 700, + 300 + ], "parameters": { - "body": { - "namespace": "$entity.namespace", - "name": "$entity.name", - "versions": "$enriched" - }, - "status": 200 + "parameters": { + "body": { + "namespace": "$entity.namespace", + "name": "$entity.name", + "versions": "$enriched" + }, + "status": 200 + } } }, { "id": "error_not_found", + "name": "Error Not Found", "type": "packagerepo.respond_error", + "typeVersion": 1, + "position": [ + 100, + 500 + ], "parameters": { - "message": "Package not found", - "status": 404 + "parameters": { + "message": "Package not found", + "status": 404 + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "List all versions of a package" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packagerepo/backend/workflows/publish_artifact.backup.json b/packagerepo/backend/workflows/publish_artifact.backup.json new file mode 100644 index 000000000..1b16ecbab --- /dev/null +++ b/packagerepo/backend/workflows/publish_artifact.backup.json @@ -0,0 +1,124 @@ +{ + "name": "Publish Artifact", + "description": "Upload and store a package artifact", + "version": "1.0.0", + "nodes": [ + { + "id": "verify_auth", + "type": "packagerepo.auth_verify_jwt", + "parameters": { + "token": "$request.headers.Authorization", + "out": "principal" + } + }, + { + "id": "check_write_scope", + "type": "packagerepo.auth_check_scopes", + "parameters": { + "principal": "$principal", + "required_scopes": ["write"] + } + }, + { + "id": "parse_path", + "type": "packagerepo.parse_path", + "parameters": { + "path": "$request.path", + "pattern": "/v1/:namespace/:name/:version/:variant/blob", + "out": "entity" + } + }, + { + "id": "normalize", + "type": "packagerepo.normalize_entity", + "parameters": { + "entity": "$entity", + "out": "normalized" + } + }, + { + "id": "validate", + "type": "packagerepo.validate_entity", + "parameters": { + "entity": "$normalized" + } + }, + { + "id": "compute_digest", + "type": "string.sha256", + "parameters": { + "input": "$request.body", + "out": "digest" + } + }, + { + "id": "check_exists", + "type": "packagerepo.kv_get", + "parameters": { + "key": "artifact/$entity.namespace/$entity.name/$entity.version/$entity.variant", + "out": "existing" + } + }, + { + "id": "if_exists", + "type": "logic.if", + "parameters": { + "condition": "$existing != null", + "then": "error_exists", + "else": "write_blob" + } + }, + { + "id": "write_blob", + "type": "packagerepo.blob_put", + "parameters": { + "digest": "$digest", + "data": "$request.body" + } + }, + { + "id": "write_meta", + "type": "packagerepo.kv_put", + "parameters": { + "key": "artifact/$entity.namespace/$entity.name/$entity.version/$entity.variant", + "value": { + "digest": "$digest", + "size": "$request.content_length", + "uploaded_at": "$timestamp", + "uploaded_by": "$principal.sub" + } + } + }, + { + "id": "update_index", + "type": "packagerepo.index_upsert", + "parameters": { + "key": "$entity.namespace/$entity.name", + "entry": { + "version": "$entity.version", + "variant": "$entity.variant", + "digest": "$digest" + } + } + }, + { + "id": "success", + "type": "packagerepo.respond_json", + "parameters": { + "body": { + "ok": true, + "digest": "$digest" + }, + "status": 201 + } + }, + { + "id": "error_exists", + "type": "packagerepo.respond_error", + "parameters": { + "message": "Artifact already exists", + "status": 409 + } + } + ] +} diff --git a/packagerepo/backend/workflows/publish_artifact.json b/packagerepo/backend/workflows/publish_artifact.json index 1b16ecbab..87f8928bf 100644 --- a/packagerepo/backend/workflows/publish_artifact.json +++ b/packagerepo/backend/workflows/publish_artifact.json @@ -1,124 +1,241 @@ { "name": "Publish Artifact", - "description": "Upload and store a package artifact", - "version": "1.0.0", + "active": false, "nodes": [ { "id": "verify_auth", + "name": "Verify Auth", "type": "packagerepo.auth_verify_jwt", + "typeVersion": 1, + "position": [ + 100, + 100 + ], "parameters": { - "token": "$request.headers.Authorization", - "out": "principal" + "parameters": { + "token": "$request.headers.Authorization", + "out": "principal" + } } }, { "id": "check_write_scope", + "name": "Check Write Scope", "type": "packagerepo.auth_check_scopes", + "typeVersion": 1, + "position": [ + 400, + 100 + ], "parameters": { - "principal": "$principal", - "required_scopes": ["write"] + "parameters": { + "principal": "$principal", + "required_scopes": [ + "write" + ] + } } }, { "id": "parse_path", + "name": "Parse Path", "type": "packagerepo.parse_path", + "typeVersion": 1, + "position": [ + 700, + 100 + ], "parameters": { - "path": "$request.path", - "pattern": "/v1/:namespace/:name/:version/:variant/blob", - "out": "entity" + "parameters": { + "path": "$request.path", + "pattern": "/v1/:namespace/:name/:version/:variant/blob", + "out": "entity" + } } }, { "id": "normalize", + "name": "Normalize", "type": "packagerepo.normalize_entity", + "typeVersion": 1, + "position": [ + 100, + 300 + ], "parameters": { - "entity": "$entity", - "out": "normalized" + "parameters": { + "entity": "$entity", + "out": "normalized" + } } }, { "id": "validate", + "name": "Validate", "type": "packagerepo.validate_entity", + "typeVersion": 1, + "position": [ + 400, + 300 + ], "parameters": { - "entity": "$normalized" + "parameters": { + "entity": "$normalized" + } } }, { "id": "compute_digest", + "name": "Compute Digest", "type": "string.sha256", + "typeVersion": 1, + "position": [ + 700, + 300 + ], "parameters": { - "input": "$request.body", - "out": "digest" + "parameters": { + "input": "$request.body", + "out": "digest" + } } }, { "id": "check_exists", + "name": "Check Exists", "type": "packagerepo.kv_get", + "typeVersion": 1, + "position": [ + 100, + 500 + ], "parameters": { - "key": "artifact/$entity.namespace/$entity.name/$entity.version/$entity.variant", - "out": "existing" + "parameters": { + "key": "artifact/$entity.namespace/$entity.name/$entity.version/$entity.variant", + "out": "existing" + } } }, { "id": "if_exists", + "name": "If Exists", "type": "logic.if", + "typeVersion": 1, + "position": [ + 400, + 500 + ], "parameters": { - "condition": "$existing != null", - "then": "error_exists", - "else": "write_blob" + "parameters": { + "condition": "$existing != null", + "then": "error_exists", + "else": "write_blob" + } } }, { "id": "write_blob", + "name": "Write Blob", "type": "packagerepo.blob_put", + "typeVersion": 1, + "position": [ + 700, + 500 + ], "parameters": { - "digest": "$digest", - "data": "$request.body" + "parameters": { + "digest": "$digest", + "data": "$request.body" + } } }, { "id": "write_meta", + "name": "Write Meta", "type": "packagerepo.kv_put", + "typeVersion": 1, + "position": [ + 100, + 700 + ], "parameters": { - "key": "artifact/$entity.namespace/$entity.name/$entity.version/$entity.variant", - "value": { - "digest": "$digest", - "size": "$request.content_length", - "uploaded_at": "$timestamp", - "uploaded_by": "$principal.sub" + "parameters": { + "key": "artifact/$entity.namespace/$entity.name/$entity.version/$entity.variant", + "value": { + "digest": "$digest", + "size": "$request.content_length", + "uploaded_at": "$timestamp", + "uploaded_by": "$principal.sub" + } } } }, { "id": "update_index", + "name": "Update Index", "type": "packagerepo.index_upsert", + "typeVersion": 1, + "position": [ + 400, + 700 + ], "parameters": { - "key": "$entity.namespace/$entity.name", - "entry": { - "version": "$entity.version", - "variant": "$entity.variant", - "digest": "$digest" + "parameters": { + "key": "$entity.namespace/$entity.name", + "entry": { + "version": "$entity.version", + "variant": "$entity.variant", + "digest": "$digest" + } } } }, { "id": "success", + "name": "Success", "type": "packagerepo.respond_json", + "typeVersion": 1, + "position": [ + 700, + 700 + ], "parameters": { - "body": { - "ok": true, - "digest": "$digest" - }, - "status": 201 + "parameters": { + "body": { + "ok": true, + "digest": "$digest" + }, + "status": 201 + } } }, { "id": "error_exists", + "name": "Error Exists", "type": "packagerepo.respond_error", + "typeVersion": 1, + "position": [ + 100, + 900 + ], "parameters": { - "message": "Artifact already exists", - "status": 409 + "parameters": { + "message": "Artifact already exists", + "status": 409 + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Upload and store a package artifact" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packagerepo/backend/workflows/resolve_latest.backup.json b/packagerepo/backend/workflows/resolve_latest.backup.json new file mode 100644 index 000000000..8448f6c0d --- /dev/null +++ b/packagerepo/backend/workflows/resolve_latest.backup.json @@ -0,0 +1,81 @@ +{ + "name": "Resolve Latest Version", + "description": "Get the latest version of a package", + "version": "1.0.0", + "nodes": [ + { + "id": "parse_path", + "type": "packagerepo.parse_path", + "parameters": { + "path": "$request.path", + "pattern": "/v1/:namespace/:name/latest", + "out": "entity" + } + }, + { + "id": "normalize", + "type": "packagerepo.normalize_entity", + "parameters": { + "entity": "$entity", + "out": "normalized" + } + }, + { + "id": "query_index", + "type": "packagerepo.index_query", + "parameters": { + "key": "$entity.namespace/$entity.name", + "out": "versions" + } + }, + { + "id": "check_exists", + "type": "logic.if", + "parameters": { + "condition": "$versions == null || $versions.length == 0", + "then": "error_not_found", + "else": "find_latest" + } + }, + { + "id": "find_latest", + "type": "packagerepo.resolve_latest_version", + "parameters": { + "versions": "$versions", + "out": "latest" + } + }, + { + "id": "get_meta", + "type": "packagerepo.kv_get", + "parameters": { + "key": "artifact/$entity.namespace/$entity.name/$latest.version/$latest.variant", + "out": "metadata" + } + }, + { + "id": "respond_json", + "type": "packagerepo.respond_json", + "parameters": { + "body": { + "namespace": "$entity.namespace", + "name": "$entity.name", + "version": "$latest.version", + "variant": "$latest.variant", + "digest": "$latest.digest", + "size": "$metadata.size", + "uploaded_at": "$metadata.uploaded_at" + }, + "status": 200 + } + }, + { + "id": "error_not_found", + "type": "packagerepo.respond_error", + "parameters": { + "message": "Package not found", + "status": 404 + } + } + ] +} diff --git a/packagerepo/backend/workflows/resolve_latest.json b/packagerepo/backend/workflows/resolve_latest.json index 8448f6c0d..af03f9f5a 100644 --- a/packagerepo/backend/workflows/resolve_latest.json +++ b/packagerepo/backend/workflows/resolve_latest.json @@ -1,81 +1,156 @@ { "name": "Resolve Latest Version", - "description": "Get the latest version of a package", - "version": "1.0.0", + "active": false, "nodes": [ { "id": "parse_path", + "name": "Parse Path", "type": "packagerepo.parse_path", + "typeVersion": 1, + "position": [ + 100, + 100 + ], "parameters": { - "path": "$request.path", - "pattern": "/v1/:namespace/:name/latest", - "out": "entity" + "parameters": { + "path": "$request.path", + "pattern": "/v1/:namespace/:name/latest", + "out": "entity" + } } }, { "id": "normalize", + "name": "Normalize", "type": "packagerepo.normalize_entity", + "typeVersion": 1, + "position": [ + 400, + 100 + ], "parameters": { - "entity": "$entity", - "out": "normalized" + "parameters": { + "entity": "$entity", + "out": "normalized" + } } }, { "id": "query_index", + "name": "Query Index", "type": "packagerepo.index_query", + "typeVersion": 1, + "position": [ + 700, + 100 + ], "parameters": { - "key": "$entity.namespace/$entity.name", - "out": "versions" + "parameters": { + "key": "$entity.namespace/$entity.name", + "out": "versions" + } } }, { "id": "check_exists", + "name": "Check Exists", "type": "logic.if", + "typeVersion": 1, + "position": [ + 100, + 300 + ], "parameters": { - "condition": "$versions == null || $versions.length == 0", - "then": "error_not_found", - "else": "find_latest" + "parameters": { + "condition": "$versions == null || $versions.length == 0", + "then": "error_not_found", + "else": "find_latest" + } } }, { "id": "find_latest", + "name": "Find Latest", "type": "packagerepo.resolve_latest_version", + "typeVersion": 1, + "position": [ + 400, + 300 + ], "parameters": { - "versions": "$versions", - "out": "latest" + "parameters": { + "versions": "$versions", + "out": "latest" + } } }, { "id": "get_meta", + "name": "Get Meta", "type": "packagerepo.kv_get", + "typeVersion": 1, + "position": [ + 700, + 300 + ], "parameters": { - "key": "artifact/$entity.namespace/$entity.name/$latest.version/$latest.variant", - "out": "metadata" + "parameters": { + "key": "artifact/$entity.namespace/$entity.name/$latest.version/$latest.variant", + "out": "metadata" + } } }, { "id": "respond_json", + "name": "Respond Json", "type": "packagerepo.respond_json", + "typeVersion": 1, + "position": [ + 100, + 500 + ], "parameters": { - "body": { - "namespace": "$entity.namespace", - "name": "$entity.name", - "version": "$latest.version", - "variant": "$latest.variant", - "digest": "$latest.digest", - "size": "$metadata.size", - "uploaded_at": "$metadata.uploaded_at" - }, - "status": 200 + "parameters": { + "body": { + "namespace": "$entity.namespace", + "name": "$entity.name", + "version": "$latest.version", + "variant": "$latest.variant", + "digest": "$latest.digest", + "size": "$metadata.size", + "uploaded_at": "$metadata.uploaded_at" + }, + "status": 200 + } } }, { "id": "error_not_found", + "name": "Error Not Found", "type": "packagerepo.respond_error", + "typeVersion": 1, + "position": [ + 400, + 500 + ], "parameters": { - "message": "Package not found", - "status": 404 + "parameters": { + "message": "Package not found", + "status": 404 + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Get the latest version of a package" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packagerepo/backend/workflows/server.backup.json b/packagerepo/backend/workflows/server.backup.json new file mode 100644 index 000000000..cc0bff199 --- /dev/null +++ b/packagerepo/backend/workflows/server.backup.json @@ -0,0 +1,84 @@ +{ + "name": "Package Repository Server", + "description": "Complete Flask server defined as a workflow", + "version": "1.0.0", + "nodes": [ + { + "id": "create_app", + "type": "web.create_flask_app", + "parameters": { + "name": "packagerepo", + "config": { + "MAX_CONTENT_LENGTH": 2147483648 + } + } + }, + { + "id": "register_publish", + "type": "web.register_route", + "parameters": { + "path": "/v1/////blob", + "methods": ["PUT"], + "workflow": "publish_artifact", + "endpoint": "publish_artifact" + } + }, + { + "id": "register_download", + "type": "web.register_route", + "parameters": { + "path": "/v1/////blob", + "methods": ["GET"], + "workflow": "download_artifact", + "endpoint": "download_artifact" + } + }, + { + "id": "register_latest", + "type": "web.register_route", + "parameters": { + "path": "/v1///latest", + "methods": ["GET"], + "workflow": "resolve_latest", + "endpoint": "resolve_latest" + } + }, + { + "id": "register_versions", + "type": "web.register_route", + "parameters": { + "path": "/v1///versions", + "methods": ["GET"], + "workflow": "list_versions", + "endpoint": "list_versions" + } + }, + { + "id": "register_login", + "type": "web.register_route", + "parameters": { + "path": "/auth/login", + "methods": ["POST"], + "workflow": "auth_login", + "endpoint": "auth_login" + } + }, + { + "id": "start_server", + "type": "web.start_server", + "parameters": { + "host": "0.0.0.0", + "port": 8080, + "debug": false + } + } + ], + "connections": { + "create_app": ["register_publish"], + "register_publish": ["register_download"], + "register_download": ["register_latest"], + "register_latest": ["register_versions"], + "register_versions": ["register_login"], + "register_login": ["start_server"] + } +} diff --git a/packagerepo/backend/workflows/server.json b/packagerepo/backend/workflows/server.json index cc0bff199..2349490ee 100644 --- a/packagerepo/backend/workflows/server.json +++ b/packagerepo/backend/workflows/server.json @@ -1,84 +1,220 @@ { "name": "Package Repository Server", - "description": "Complete Flask server defined as a workflow", - "version": "1.0.0", + "active": false, "nodes": [ { "id": "create_app", + "name": "Create App", "type": "web.create_flask_app", + "typeVersion": 1, + "position": [ + 100, + 100 + ], "parameters": { - "name": "packagerepo", - "config": { - "MAX_CONTENT_LENGTH": 2147483648 + "parameters": { + "name": "packagerepo", + "config": { + "MAX_CONTENT_LENGTH": 2147483648 + } } } }, { "id": "register_publish", + "name": "Register Publish", "type": "web.register_route", + "typeVersion": 1, + "position": [ + 400, + 100 + ], "parameters": { - "path": "/v1/////blob", - "methods": ["PUT"], - "workflow": "publish_artifact", - "endpoint": "publish_artifact" + "parameters": { + "path": "/v1/////blob", + "methods": [ + "PUT" + ], + "workflow": "publish_artifact", + "endpoint": "publish_artifact" + } } }, { "id": "register_download", + "name": "Register Download", "type": "web.register_route", + "typeVersion": 1, + "position": [ + 700, + 100 + ], "parameters": { - "path": "/v1/////blob", - "methods": ["GET"], - "workflow": "download_artifact", - "endpoint": "download_artifact" + "parameters": { + "path": "/v1/////blob", + "methods": [ + "GET" + ], + "workflow": "download_artifact", + "endpoint": "download_artifact" + } } }, { "id": "register_latest", + "name": "Register Latest", "type": "web.register_route", + "typeVersion": 1, + "position": [ + 100, + 300 + ], "parameters": { - "path": "/v1///latest", - "methods": ["GET"], - "workflow": "resolve_latest", - "endpoint": "resolve_latest" + "parameters": { + "path": "/v1///latest", + "methods": [ + "GET" + ], + "workflow": "resolve_latest", + "endpoint": "resolve_latest" + } } }, { "id": "register_versions", + "name": "Register Versions", "type": "web.register_route", + "typeVersion": 1, + "position": [ + 400, + 300 + ], "parameters": { - "path": "/v1///versions", - "methods": ["GET"], - "workflow": "list_versions", - "endpoint": "list_versions" + "parameters": { + "path": "/v1///versions", + "methods": [ + "GET" + ], + "workflow": "list_versions", + "endpoint": "list_versions" + } } }, { "id": "register_login", + "name": "Register Login", "type": "web.register_route", + "typeVersion": 1, + "position": [ + 700, + 300 + ], "parameters": { - "path": "/auth/login", - "methods": ["POST"], - "workflow": "auth_login", - "endpoint": "auth_login" + "parameters": { + "path": "/auth/login", + "methods": [ + "POST" + ], + "workflow": "auth_login", + "endpoint": "auth_login" + } } }, { "id": "start_server", + "name": "Start Server", "type": "web.start_server", + "typeVersion": 1, + "position": [ + 100, + 500 + ], "parameters": { - "host": "0.0.0.0", - "port": 8080, - "debug": false + "parameters": { + "host": "0.0.0.0", + "port": 8080, + "debug": false + } } } ], "connections": { - "create_app": ["register_publish"], - "register_publish": ["register_download"], - "register_download": ["register_latest"], - "register_latest": ["register_versions"], - "register_versions": ["register_login"], - "register_login": ["start_server"] + "Create App": { + "main": { + "0": [ + { + "node": "Register Publish", + "type": "main", + "index": 0 + } + ] + } + }, + "Register Publish": { + "main": { + "0": [ + { + "node": "Register Download", + "type": "main", + "index": 0 + } + ] + } + }, + "Register Download": { + "main": { + "0": [ + { + "node": "Register Latest", + "type": "main", + "index": 0 + } + ] + } + }, + "Register Latest": { + "main": { + "0": [ + { + "node": "Register Versions", + "type": "main", + "index": 0 + } + ] + } + }, + "Register Versions": { + "main": { + "0": [ + { + "node": "Register Login", + "type": "main", + "index": 0 + } + ] + } + }, + "Register Login": { + "main": { + "0": [ + { + "node": "Start Server", + "type": "main", + "index": 0 + } + ] + } + } + }, + "staticData": {}, + "meta": { + "description": "Complete Flask server defined as a workflow" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" } } diff --git a/packages/audit_log/workflow/filters.backup.jsonscript b/packages/audit_log/workflow/filters.backup.jsonscript new file mode 100644 index 000000000..ccc439ec4 --- /dev/null +++ b/packages/audit_log/workflow/filters.backup.jsonscript @@ -0,0 +1,66 @@ +{ + "version": "2.2.0", + "name": "Filter Audit Logs", + "description": "Advanced filtering of audit logs by action, entity, user, and date range", + "trigger": { + "type": "http", + "method": "POST", + "path": "/audit-logs/filter" + }, + "nodes": [ + { + "id": "validate_tenant", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required", + "errorMessage": "tenantId is required" + }, + { + "id": "build_filter", + "type": "operation", + "op": "transform_data", + "input": "{{ $json }}", + "output": { + "tenantId": "{{ $context.tenantId }}", + "action": "{{ $json.action }}", + "entity": "{{ $json.entity }}", + "userId": "{{ $json.userId }}", + "timestamp": { + "$gte": "{{ $json.startDate || new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString() }}", + "$lte": "{{ $json.endDate || new Date().toISOString() }}" + } + } + }, + { + "id": "clean_filter", + "type": "operation", + "op": "transform_data", + "input": "{{ $steps.build_filter.output }}", + "output": "{{ Object.entries($steps.build_filter.output).reduce((acc, [key, value]) => { if (value !== undefined && value !== null && (typeof value !== 'string' || value.length > 0)) acc[key] = value; return acc; }, {}) }}" + }, + { + "id": "fetch_filtered", + "type": "operation", + "op": "database_read", + "entity": "AuditLog", + "params": { + "filter": "{{ $steps.clean_filter.output }}", + "sort": {"timestamp": -1}, + "limit": "{{ Math.min($json.limit || 100, 500) }}" + }, + "output": "results" + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": { + "filters": "{{ $json }}", + "count": "{{ $steps.fetch_filtered.output.length }}", + "results": "{{ $steps.fetch_filtered.output }}" + } + } + ] +} diff --git a/packages/audit_log/workflow/filters.jsonscript b/packages/audit_log/workflow/filters.jsonscript index ccc439ec4..bcbfe516f 100644 --- a/packages/audit_log/workflow/filters.jsonscript +++ b/packages/audit_log/workflow/filters.jsonscript @@ -1,66 +1,112 @@ { - "version": "2.2.0", "name": "Filter Audit Logs", - "description": "Advanced filtering of audit logs by action, entity, user, and date range", - "trigger": { - "type": "http", - "method": "POST", - "path": "/audit-logs/filter" - }, + "active": false, "nodes": [ { "id": "validate_tenant", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required", - "errorMessage": "tenantId is required" + "name": "Validate Tenant", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required", + "errorMessage": "tenantId is required" + } }, { "id": "build_filter", - "type": "operation", - "op": "transform_data", - "input": "{{ $json }}", - "output": { - "tenantId": "{{ $context.tenantId }}", - "action": "{{ $json.action }}", - "entity": "{{ $json.entity }}", - "userId": "{{ $json.userId }}", - "timestamp": { - "$gte": "{{ $json.startDate || new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString() }}", - "$lte": "{{ $json.endDate || new Date().toISOString() }}" - } + "name": "Build Filter", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "output": { + "tenantId": "{{ $context.tenantId }}", + "action": "{{ $json.action }}", + "entity": "{{ $json.entity }}", + "userId": "{{ $json.userId }}", + "timestamp": { + "$gte": "{{ $json.startDate || new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString() }}", + "$lte": "{{ $json.endDate || new Date().toISOString() }}" + } + }, + "operation": "transform_data" } }, { "id": "clean_filter", - "type": "operation", - "op": "transform_data", - "input": "{{ $steps.build_filter.output }}", - "output": "{{ Object.entries($steps.build_filter.output).reduce((acc, [key, value]) => { if (value !== undefined && value !== null && (typeof value !== 'string' || value.length > 0)) acc[key] = value; return acc; }, {}) }}" + "name": "Clean Filter", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "input": "{{ $steps.build_filter.output }}", + "output": "{{ Object.entries($steps.build_filter.output).reduce((acc, [key, value]) => { if (value !== undefined && value !== null && (typeof value !== 'string' || value.length > 0)) acc[key] = value; return acc; }, {}) }}", + "operation": "transform_data" + } }, { "id": "fetch_filtered", - "type": "operation", - "op": "database_read", - "entity": "AuditLog", - "params": { + "name": "Fetch Filtered", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { "filter": "{{ $steps.clean_filter.output }}", - "sort": {"timestamp": -1}, - "limit": "{{ Math.min($json.limit || 100, 500) }}" - }, - "output": "results" + "sort": { + "timestamp": -1 + }, + "limit": "{{ Math.min($json.limit || 100, 500) }}", + "output": "results", + "operation": "database_read", + "entity": "AuditLog" + } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": { - "filters": "{{ $json }}", - "count": "{{ $steps.fetch_filtered.output.length }}", - "results": "{{ $steps.fetch_filtered.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": { + "filters": "{{ $json }}", + "count": "{{ $steps.fetch_filtered.output.length }}", + "results": "{{ $steps.fetch_filtered.output }}" + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Advanced filtering of audit logs by action, entity, user, and date range" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/audit_log/workflow/formatting.backup.jsonscript b/packages/audit_log/workflow/formatting.backup.jsonscript new file mode 100644 index 000000000..598a401e0 --- /dev/null +++ b/packages/audit_log/workflow/formatting.backup.jsonscript @@ -0,0 +1,69 @@ +{ + "version": "2.2.0", + "name": "Format Audit Log Entry", + "description": "Format audit log entries with user and entity details for display", + "trigger": { + "type": "operation", + "op": "transform" + }, + "nodes": [ + { + "id": "extract_log_id", + "type": "operation", + "op": "transform_data", + "input": "{{ $json }}", + "output": "{{ $json.id }}" + }, + { + "id": "fetch_user_details", + "type": "operation", + "op": "database_read", + "entity": "User", + "params": { + "filter": { + "id": "{{ $json.userId }}", + "tenantId": "{{ $context.tenantId }}" + } + }, + "output": "user" + }, + { + "id": "format_timestamp", + "type": "operation", + "op": "transform_data", + "input": "{{ $json.timestamp }}", + "output": { + "iso": "{{ new Date($json.timestamp).toISOString() }}", + "formatted": "{{ new Date($json.timestamp).toLocaleString('en-US') }}", + "relative": "{{ Math.floor((Date.now() - new Date($json.timestamp).getTime()) / 1000) }} seconds ago" + } + }, + { + "id": "format_entry", + "type": "operation", + "op": "transform_data", + "output": { + "id": "{{ $json.id }}", + "user": { + "id": "{{ $steps.fetch_user_details.output.id }}", + "email": "{{ $steps.fetch_user_details.output.email }}", + "displayName": "{{ $steps.fetch_user_details.output.displayName }}" + }, + "action": "{{ $json.action }}", + "entity": "{{ $json.entity }}", + "entityId": "{{ $json.entityId }}", + "changes": "{{ $json.changes }}", + "timestamp": "{{ $steps.format_timestamp.output }}", + "ipAddress": "{{ $json.ipAddress }}", + "userAgent": "{{ $json.userAgent }}" + } + }, + { + "id": "return_formatted", + "type": "action", + "action": "emit_event", + "event": "audit_formatted", + "data": "{{ $steps.format_entry.output }}" + } + ] +} diff --git a/packages/audit_log/workflow/formatting.jsonscript b/packages/audit_log/workflow/formatting.jsonscript index 598a401e0..55253750a 100644 --- a/packages/audit_log/workflow/formatting.jsonscript +++ b/packages/audit_log/workflow/formatting.jsonscript @@ -1,69 +1,114 @@ { - "version": "2.2.0", "name": "Format Audit Log Entry", - "description": "Format audit log entries with user and entity details for display", - "trigger": { - "type": "operation", - "op": "transform" - }, + "active": false, "nodes": [ { "id": "extract_log_id", - "type": "operation", - "op": "transform_data", - "input": "{{ $json }}", - "output": "{{ $json.id }}" + "name": "Extract Log Id", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "output": "{{ $json.id }}", + "operation": "transform_data" + } }, { "id": "fetch_user_details", - "type": "operation", - "op": "database_read", - "entity": "User", - "params": { + "name": "Fetch User Details", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { "filter": { "id": "{{ $json.userId }}", "tenantId": "{{ $context.tenantId }}" - } - }, - "output": "user" + }, + "output": "user", + "operation": "database_read", + "entity": "User" + } }, { "id": "format_timestamp", - "type": "operation", - "op": "transform_data", - "input": "{{ $json.timestamp }}", - "output": { - "iso": "{{ new Date($json.timestamp).toISOString() }}", - "formatted": "{{ new Date($json.timestamp).toLocaleString('en-US') }}", - "relative": "{{ Math.floor((Date.now() - new Date($json.timestamp).getTime()) / 1000) }} seconds ago" + "name": "Format Timestamp", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "input": "{{ $json.timestamp }}", + "output": { + "iso": "{{ new Date($json.timestamp).toISOString() }}", + "formatted": "{{ new Date($json.timestamp).toLocaleString('en-US') }}", + "relative": "{{ Math.floor((Date.now() - new Date($json.timestamp).getTime()) / 1000) }} seconds ago" + }, + "operation": "transform_data" } }, { "id": "format_entry", - "type": "operation", - "op": "transform_data", - "output": { - "id": "{{ $json.id }}", - "user": { - "id": "{{ $steps.fetch_user_details.output.id }}", - "email": "{{ $steps.fetch_user_details.output.email }}", - "displayName": "{{ $steps.fetch_user_details.output.displayName }}" + "name": "Format Entry", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "output": { + "id": "{{ $json.id }}", + "user": { + "id": "{{ $steps.fetch_user_details.output.id }}", + "email": "{{ $steps.fetch_user_details.output.email }}", + "displayName": "{{ $steps.fetch_user_details.output.displayName }}" + }, + "action": "{{ $json.action }}", + "entity": "{{ $json.entity }}", + "entityId": "{{ $json.entityId }}", + "changes": "{{ $json.changes }}", + "timestamp": "{{ $steps.format_timestamp.output }}", + "ipAddress": "{{ $json.ipAddress }}", + "userAgent": "{{ $json.userAgent }}" }, - "action": "{{ $json.action }}", - "entity": "{{ $json.entity }}", - "entityId": "{{ $json.entityId }}", - "changes": "{{ $json.changes }}", - "timestamp": "{{ $steps.format_timestamp.output }}", - "ipAddress": "{{ $json.ipAddress }}", - "userAgent": "{{ $json.userAgent }}" + "operation": "transform_data" } }, { "id": "return_formatted", - "type": "action", - "action": "emit_event", - "event": "audit_formatted", - "data": "{{ $steps.format_entry.output }}" + "name": "Return Formatted", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "data": "{{ $steps.format_entry.output }}", + "action": "emit_event", + "event": "audit_formatted" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Format audit log entries with user and entity details for display" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/audit_log/workflow/init.backup.jsonscript b/packages/audit_log/workflow/init.backup.jsonscript new file mode 100644 index 000000000..7141e5424 --- /dev/null +++ b/packages/audit_log/workflow/init.backup.jsonscript @@ -0,0 +1,88 @@ +{ + "version": "2.2.0", + "name": "Load Audit Logs", + "description": "Load and paginate audit logs with tenant filtering", + "trigger": { + "type": "http", + "method": "GET", + "path": "/audit-logs" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required", + "errorMessage": "tenantId is required for multi-tenant safety" + }, + { + "id": "extract_pagination", + "type": "operation", + "op": "transform_data", + "input": "{{ $json }}", + "output": { + "limit": "{{ Math.min($json.limit || 100, 500) }}", + "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 100) }}" + } + }, + { + "id": "fetch_logs", + "type": "operation", + "op": "database_read", + "entity": "AuditLog", + "params": { + "filter": { + "tenantId": "{{ $context.tenantId }}" + }, + "sort": {"timestamp": -1}, + "limit": "{{ $steps.extract_pagination.output.limit }}", + "offset": "{{ $steps.extract_pagination.output.offset }}" + }, + "output": "logs" + }, + { + "id": "fetch_count", + "type": "operation", + "op": "database_count", + "entity": "AuditLog", + "params": { + "filter": { + "tenantId": "{{ $context.tenantId }}" + } + }, + "output": "totalCount" + }, + { + "id": "format_response", + "type": "operation", + "op": "transform_data", + "input": "{{ $steps.fetch_logs.output }}", + "output": { + "logs": "{{ $steps.fetch_logs.output }}", + "pagination": { + "total": "{{ $steps.fetch_count.output }}", + "limit": "{{ $steps.extract_pagination.output.limit }}", + "offset": "{{ $steps.extract_pagination.output.offset }}", + "hasMore": "{{ $steps.fetch_count.output > ($steps.extract_pagination.output.offset + $steps.extract_pagination.output.limit) }}" + } + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } + ], + "errorHandler": { + "type": "action", + "action": "http_response", + "status": 500, + "body": { + "error": "Failed to load audit logs", + "message": "{{ $error.message }}" + } + } +} diff --git a/packages/audit_log/workflow/init.jsonscript b/packages/audit_log/workflow/init.jsonscript index 7141e5424..2bf43c06c 100644 --- a/packages/audit_log/workflow/init.jsonscript +++ b/packages/audit_log/workflow/init.jsonscript @@ -1,88 +1,131 @@ { - "version": "2.2.0", "name": "Load Audit Logs", - "description": "Load and paginate audit logs with tenant filtering", - "trigger": { - "type": "http", - "method": "GET", - "path": "/audit-logs" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required", - "errorMessage": "tenantId is required for multi-tenant safety" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required", + "errorMessage": "tenantId is required for multi-tenant safety" + } }, { "id": "extract_pagination", - "type": "operation", - "op": "transform_data", - "input": "{{ $json }}", - "output": { - "limit": "{{ Math.min($json.limit || 100, 500) }}", - "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 100) }}" + "name": "Extract Pagination", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "output": { + "limit": "{{ Math.min($json.limit || 100, 500) }}", + "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 100) }}" + }, + "operation": "transform_data" } }, { "id": "fetch_logs", - "type": "operation", - "op": "database_read", - "entity": "AuditLog", - "params": { + "name": "Fetch Logs", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { "filter": { "tenantId": "{{ $context.tenantId }}" }, - "sort": {"timestamp": -1}, + "sort": { + "timestamp": -1 + }, "limit": "{{ $steps.extract_pagination.output.limit }}", - "offset": "{{ $steps.extract_pagination.output.offset }}" - }, - "output": "logs" + "offset": "{{ $steps.extract_pagination.output.offset }}", + "output": "logs", + "operation": "database_read", + "entity": "AuditLog" + } }, { "id": "fetch_count", - "type": "operation", - "op": "database_count", - "entity": "AuditLog", - "params": { + "name": "Fetch Count", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { "filter": { "tenantId": "{{ $context.tenantId }}" - } - }, - "output": "totalCount" + }, + "output": "totalCount", + "operation": "database_count", + "entity": "AuditLog" + } }, { "id": "format_response", - "type": "operation", - "op": "transform_data", - "input": "{{ $steps.fetch_logs.output }}", - "output": { - "logs": "{{ $steps.fetch_logs.output }}", - "pagination": { - "total": "{{ $steps.fetch_count.output }}", - "limit": "{{ $steps.extract_pagination.output.limit }}", - "offset": "{{ $steps.extract_pagination.output.offset }}", - "hasMore": "{{ $steps.fetch_count.output > ($steps.extract_pagination.output.offset + $steps.extract_pagination.output.limit) }}" - } + "name": "Format Response", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "input": "{{ $steps.fetch_logs.output }}", + "output": { + "logs": "{{ $steps.fetch_logs.output }}", + "pagination": { + "total": "{{ $steps.fetch_count.output }}", + "limit": "{{ $steps.extract_pagination.output.limit }}", + "offset": "{{ $steps.extract_pagination.output.offset }}", + "hasMore": "{{ $steps.fetch_count.output > ($steps.extract_pagination.output.offset + $steps.extract_pagination.output.limit) }}" + } + }, + "operation": "transform_data" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.format_response.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } } ], - "errorHandler": { - "type": "action", - "action": "http_response", - "status": 500, - "body": { - "error": "Failed to load audit logs", - "message": "{{ $error.message }}" - } + "connections": {}, + "staticData": {}, + "meta": { + "description": "Load and paginate audit logs with tenant filtering" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" } } diff --git a/packages/audit_log/workflow/stats.backup.jsonscript b/packages/audit_log/workflow/stats.backup.jsonscript new file mode 100644 index 000000000..569e5b184 --- /dev/null +++ b/packages/audit_log/workflow/stats.backup.jsonscript @@ -0,0 +1,87 @@ +{ + "version": "2.2.0", + "name": "Calculate Audit Statistics", + "description": "Calculate audit log statistics (action counts, user activity)", + "trigger": { + "type": "http", + "method": "GET", + "path": "/audit-logs/stats" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required", + "errorMessage": "tenantId is required" + }, + { + "id": "get_date_range", + "type": "operation", + "op": "transform_data", + "output": { + "startDate": "{{ new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString() }}", + "endDate": "{{ new Date().toISOString() }}" + } + }, + { + "id": "count_by_action", + "type": "operation", + "op": "database_aggregate", + "entity": "AuditLog", + "params": { + "filter": { + "tenantId": "{{ $context.tenantId }}", + "timestamp": { + "$gte": "{{ $steps.get_date_range.output.startDate }}", + "$lte": "{{ $steps.get_date_range.output.endDate }}" + } + }, + "groupBy": "action", + "aggregations": { + "count": "count" + } + }, + "output": "actionStats" + }, + { + "id": "count_by_entity", + "type": "operation", + "op": "database_aggregate", + "entity": "AuditLog", + "params": { + "filter": { + "tenantId": "{{ $context.tenantId }}", + "timestamp": { + "$gte": "{{ $steps.get_date_range.output.startDate }}", + "$lte": "{{ $steps.get_date_range.output.endDate }}" + } + }, + "groupBy": "entity", + "aggregations": { + "count": "count" + } + }, + "output": "entityStats" + }, + { + "id": "format_response", + "type": "operation", + "op": "transform_data", + "output": { + "dateRange": "{{ $steps.get_date_range.output }}", + "actionStatistics": "{{ $steps.count_by_action.output }}", + "entityStatistics": "{{ $steps.count_by_entity.output }}", + "totalEntries": "{{ $steps.count_by_action.output.reduce((sum, item) => sum + item.count, 0) }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } + ] +} diff --git a/packages/audit_log/workflow/stats.jsonscript b/packages/audit_log/workflow/stats.jsonscript index 569e5b184..3883fd24a 100644 --- a/packages/audit_log/workflow/stats.jsonscript +++ b/packages/audit_log/workflow/stats.jsonscript @@ -1,36 +1,50 @@ { - "version": "2.2.0", "name": "Calculate Audit Statistics", - "description": "Calculate audit log statistics (action counts, user activity)", - "trigger": { - "type": "http", - "method": "GET", - "path": "/audit-logs/stats" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required", - "errorMessage": "tenantId is required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required", + "errorMessage": "tenantId is required" + } }, { "id": "get_date_range", - "type": "operation", - "op": "transform_data", - "output": { - "startDate": "{{ new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString() }}", - "endDate": "{{ new Date().toISOString() }}" + "name": "Get Date Range", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "output": { + "startDate": "{{ new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString() }}", + "endDate": "{{ new Date().toISOString() }}" + }, + "operation": "transform_data" } }, { "id": "count_by_action", - "type": "operation", - "op": "database_aggregate", - "entity": "AuditLog", - "params": { + "name": "Count By Action", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { "filter": { "tenantId": "{{ $context.tenantId }}", "timestamp": { @@ -41,16 +55,22 @@ "groupBy": "action", "aggregations": { "count": "count" - } - }, - "output": "actionStats" + }, + "output": "actionStats", + "operation": "database_aggregate", + "entity": "AuditLog" + } }, { "id": "count_by_entity", - "type": "operation", - "op": "database_aggregate", - "entity": "AuditLog", - "params": { + "name": "Count By Entity", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { "filter": { "tenantId": "{{ $context.tenantId }}", "timestamp": { @@ -61,27 +81,57 @@ "groupBy": "entity", "aggregations": { "count": "count" - } - }, - "output": "entityStats" + }, + "output": "entityStats", + "operation": "database_aggregate", + "entity": "AuditLog" + } }, { "id": "format_response", - "type": "operation", - "op": "transform_data", - "output": { - "dateRange": "{{ $steps.get_date_range.output }}", - "actionStatistics": "{{ $steps.count_by_action.output }}", - "entityStatistics": "{{ $steps.count_by_entity.output }}", - "totalEntries": "{{ $steps.count_by_action.output.reduce((sum, item) => sum + item.count, 0) }}" + "name": "Format Response", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "output": { + "dateRange": "{{ $steps.get_date_range.output }}", + "actionStatistics": "{{ $steps.count_by_action.output }}", + "entityStatistics": "{{ $steps.count_by_entity.output }}", + "totalEntries": "{{ $steps.count_by_action.output.reduce((sum, item) => sum + item.count, 0) }}" + }, + "operation": "transform_data" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.format_response.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Calculate audit log statistics (action counts, user activity)" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/dashboard/workflow/fetch-dashboard-data.backup.jsonscript b/packages/dashboard/workflow/fetch-dashboard-data.backup.jsonscript new file mode 100644 index 000000000..a37e04bb9 --- /dev/null +++ b/packages/dashboard/workflow/fetch-dashboard-data.backup.jsonscript @@ -0,0 +1,131 @@ +{ + "version": "2.2.0", + "name": "Fetch Dashboard Data", + "description": "Fetch all dashboard data in parallel (profile, stats, recent activity, notifications)", + "trigger": { + "type": "http", + "method": "GET", + "path": "/dashboard" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.user.id }}", + "validator": "required" + }, + { + "id": "fetch_user_profile_parallel", + "type": "operation", + "op": "parallel", + "tasks": [ + { + "id": "fetch_user", + "op": "database_read", + "entity": "User", + "params": { + "filter": { + "id": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "fetch_unread_notifications", + "op": "database_count", + "entity": "Notification", + "params": { + "filter": { + "userId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}", + "isRead": false + } + } + }, + { + "id": "fetch_recent_activity", + "op": "database_read", + "entity": "ForumPost", + "params": { + "filter": { + "authorId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + }, + "sort": {"createdAt": -1}, + "limit": 5 + } + } + ] + }, + { + "id": "fetch_statistics", + "type": "operation", + "op": "parallel", + "tasks": [ + { + "id": "count_posts", + "op": "database_count", + "entity": "ForumPost", + "params": { + "filter": { + "authorId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "count_threads", + "op": "database_count", + "entity": "ForumThread", + "params": { + "filter": { + "authorId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "count_media", + "op": "database_count", + "entity": "MediaAsset", + "params": { + "filter": { + "uploadedBy": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + } + ] + }, + { + "id": "format_response", + "type": "operation", + "op": "transform_data", + "output": { + "profile": { + "id": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.id }}", + "email": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.email }}", + "displayName": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.displayName }}", + "avatar": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.avatar }}" + }, + "notifications": { + "unread": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_unread_notifications.output }}" + }, + "statistics": { + "posts": "{{ $steps.fetch_statistics.tasks.count_posts.output }}", + "threads": "{{ $steps.fetch_statistics.tasks.count_threads.output }}", + "mediaUploads": "{{ $steps.fetch_statistics.tasks.count_media.output }}" + }, + "recentActivity": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_recent_activity.output }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } + ] +} diff --git a/packages/dashboard/workflow/fetch-dashboard-data.jsonscript b/packages/dashboard/workflow/fetch-dashboard-data.jsonscript index a37e04bb9..10404aa00 100644 --- a/packages/dashboard/workflow/fetch-dashboard-data.jsonscript +++ b/packages/dashboard/workflow/fetch-dashboard-data.jsonscript @@ -1,131 +1,179 @@ { - "version": "2.2.0", "name": "Fetch Dashboard Data", - "description": "Fetch all dashboard data in parallel (profile, stats, recent activity, notifications)", - "trigger": { - "type": "http", - "method": "GET", - "path": "/dashboard" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.user.id }}", - "validator": "required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } }, { "id": "fetch_user_profile_parallel", - "type": "operation", - "op": "parallel", - "tasks": [ - { - "id": "fetch_user", - "op": "database_read", - "entity": "User", - "params": { - "filter": { - "id": "{{ $context.user.id }}", - "tenantId": "{{ $context.tenantId }}" + "name": "Fetch User Profile Parallel", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "operation": "parallel", + "tasks": [ + { + "id": "fetch_user", + "op": "database_read", + "entity": "User", + "params": { + "filter": { + "id": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "fetch_unread_notifications", + "op": "database_count", + "entity": "Notification", + "params": { + "filter": { + "userId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}", + "isRead": false + } + } + }, + { + "id": "fetch_recent_activity", + "op": "database_read", + "entity": "ForumPost", + "params": { + "filter": { + "authorId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + }, + "sort": { + "createdAt": -1 + }, + "limit": 5 } } - }, - { - "id": "fetch_unread_notifications", - "op": "database_count", - "entity": "Notification", - "params": { - "filter": { - "userId": "{{ $context.user.id }}", - "tenantId": "{{ $context.tenantId }}", - "isRead": false - } - } - }, - { - "id": "fetch_recent_activity", - "op": "database_read", - "entity": "ForumPost", - "params": { - "filter": { - "authorId": "{{ $context.user.id }}", - "tenantId": "{{ $context.tenantId }}" - }, - "sort": {"createdAt": -1}, - "limit": 5 - } - } - ] + ] + } }, { "id": "fetch_statistics", - "type": "operation", - "op": "parallel", - "tasks": [ - { - "id": "count_posts", - "op": "database_count", - "entity": "ForumPost", - "params": { - "filter": { - "authorId": "{{ $context.user.id }}", - "tenantId": "{{ $context.tenantId }}" + "name": "Fetch Statistics", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "operation": "parallel", + "tasks": [ + { + "id": "count_posts", + "op": "database_count", + "entity": "ForumPost", + "params": { + "filter": { + "authorId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "count_threads", + "op": "database_count", + "entity": "ForumThread", + "params": { + "filter": { + "authorId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "count_media", + "op": "database_count", + "entity": "MediaAsset", + "params": { + "filter": { + "uploadedBy": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } } } - }, - { - "id": "count_threads", - "op": "database_count", - "entity": "ForumThread", - "params": { - "filter": { - "authorId": "{{ $context.user.id }}", - "tenantId": "{{ $context.tenantId }}" - } - } - }, - { - "id": "count_media", - "op": "database_count", - "entity": "MediaAsset", - "params": { - "filter": { - "uploadedBy": "{{ $context.user.id }}", - "tenantId": "{{ $context.tenantId }}" - } - } - } - ] + ] + } }, { "id": "format_response", - "type": "operation", - "op": "transform_data", - "output": { - "profile": { - "id": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.id }}", - "email": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.email }}", - "displayName": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.displayName }}", - "avatar": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.avatar }}" + "name": "Format Response", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "output": { + "profile": { + "id": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.id }}", + "email": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.email }}", + "displayName": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.displayName }}", + "avatar": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_user.output.avatar }}" + }, + "notifications": { + "unread": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_unread_notifications.output }}" + }, + "statistics": { + "posts": "{{ $steps.fetch_statistics.tasks.count_posts.output }}", + "threads": "{{ $steps.fetch_statistics.tasks.count_threads.output }}", + "mediaUploads": "{{ $steps.fetch_statistics.tasks.count_media.output }}" + }, + "recentActivity": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_recent_activity.output }}" }, - "notifications": { - "unread": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_unread_notifications.output }}" - }, - "statistics": { - "posts": "{{ $steps.fetch_statistics.tasks.count_posts.output }}", - "threads": "{{ $steps.fetch_statistics.tasks.count_threads.output }}", - "mediaUploads": "{{ $steps.fetch_statistics.tasks.count_media.output }}" - }, - "recentActivity": "{{ $steps.fetch_user_profile_parallel.tasks.fetch_recent_activity.output }}" + "operation": "transform_data" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.format_response.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Fetch all dashboard data in parallel (profile, stats, recent activity, notifications)" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/dashboard/workflow/fetch-user-comments.backup.jsonscript b/packages/dashboard/workflow/fetch-user-comments.backup.jsonscript new file mode 100644 index 000000000..218a1bbd8 --- /dev/null +++ b/packages/dashboard/workflow/fetch-user-comments.backup.jsonscript @@ -0,0 +1,85 @@ +{ + "version": "2.2.0", + "name": "Fetch User Comments", + "description": "Fetch recent comments/posts from current user with pagination", + "trigger": { + "type": "http", + "method": "GET", + "path": "/activity" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.user.id }}", + "validator": "required" + }, + { + "id": "extract_pagination", + "type": "operation", + "op": "transform_data", + "output": { + "limit": "{{ Math.min($json.limit || 20, 100) }}", + "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 20) }}" + } + }, + { + "id": "fetch_comments", + "type": "operation", + "op": "database_read", + "entity": "ForumPost", + "params": { + "filter": { + "authorId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}", + "isDeleted": false + }, + "sort": {"createdAt": -1}, + "limit": "{{ $steps.extract_pagination.output.limit }}", + "offset": "{{ $steps.extract_pagination.output.offset }}" + } + }, + { + "id": "enrich_with_thread_info", + "type": "operation", + "op": "transform_data", + "input": "{{ $steps.fetch_comments.output }}", + "output": "{{ $steps.fetch_comments.output.map(post => ({ ...post, threadUrl: '/forum/thread/' + post.threadId })) }}" + }, + { + "id": "count_total", + "type": "operation", + "op": "database_count", + "entity": "ForumPost", + "params": { + "filter": { + "authorId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}", + "isDeleted": false + } + } + }, + { + "id": "format_response", + "type": "operation", + "op": "transform_data", + "output": { + "comments": "{{ $steps.enrich_with_thread_info.output }}", + "pagination": { + "total": "{{ $steps.count_total.output }}", + "page": "{{ $json.page || 1 }}", + "limit": "{{ $steps.extract_pagination.output.limit }}", + "hasMore": "{{ $steps.count_total.output > ($steps.extract_pagination.output.offset + $steps.extract_pagination.output.limit) }}" + } + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } + ] +} diff --git a/packages/dashboard/workflow/fetch-user-comments.jsonscript b/packages/dashboard/workflow/fetch-user-comments.jsonscript index 218a1bbd8..00a97687c 100644 --- a/packages/dashboard/workflow/fetch-user-comments.jsonscript +++ b/packages/dashboard/workflow/fetch-user-comments.jsonscript @@ -1,85 +1,145 @@ { - "version": "2.2.0", "name": "Fetch User Comments", - "description": "Fetch recent comments/posts from current user with pagination", - "trigger": { - "type": "http", - "method": "GET", - "path": "/activity" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.user.id }}", - "validator": "required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } }, { "id": "extract_pagination", - "type": "operation", - "op": "transform_data", - "output": { - "limit": "{{ Math.min($json.limit || 20, 100) }}", - "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 20) }}" + "name": "Extract Pagination", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "output": { + "limit": "{{ Math.min($json.limit || 20, 100) }}", + "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 20) }}" + }, + "operation": "transform_data" } }, { "id": "fetch_comments", - "type": "operation", - "op": "database_read", - "entity": "ForumPost", - "params": { + "name": "Fetch Comments", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { "filter": { "authorId": "{{ $context.user.id }}", "tenantId": "{{ $context.tenantId }}", "isDeleted": false }, - "sort": {"createdAt": -1}, + "sort": { + "createdAt": -1 + }, "limit": "{{ $steps.extract_pagination.output.limit }}", - "offset": "{{ $steps.extract_pagination.output.offset }}" + "offset": "{{ $steps.extract_pagination.output.offset }}", + "operation": "database_read", + "entity": "ForumPost" } }, { "id": "enrich_with_thread_info", - "type": "operation", - "op": "transform_data", - "input": "{{ $steps.fetch_comments.output }}", - "output": "{{ $steps.fetch_comments.output.map(post => ({ ...post, threadUrl: '/forum/thread/' + post.threadId })) }}" + "name": "Enrich With Thread Info", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "input": "{{ $steps.fetch_comments.output }}", + "output": "{{ $steps.fetch_comments.output.map(post => ({ ...post, threadUrl: '/forum/thread/' + post.threadId })) }}", + "operation": "transform_data" + } }, { "id": "count_total", - "type": "operation", - "op": "database_count", - "entity": "ForumPost", - "params": { + "name": "Count Total", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { "filter": { "authorId": "{{ $context.user.id }}", "tenantId": "{{ $context.tenantId }}", "isDeleted": false - } + }, + "operation": "database_count", + "entity": "ForumPost" } }, { "id": "format_response", - "type": "operation", - "op": "transform_data", - "output": { - "comments": "{{ $steps.enrich_with_thread_info.output }}", - "pagination": { - "total": "{{ $steps.count_total.output }}", - "page": "{{ $json.page || 1 }}", - "limit": "{{ $steps.extract_pagination.output.limit }}", - "hasMore": "{{ $steps.count_total.output > ($steps.extract_pagination.output.offset + $steps.extract_pagination.output.limit) }}" - } + "name": "Format Response", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "output": { + "comments": "{{ $steps.enrich_with_thread_info.output }}", + "pagination": { + "total": "{{ $steps.count_total.output }}", + "page": "{{ $json.page || 1 }}", + "limit": "{{ $steps.extract_pagination.output.limit }}", + "hasMore": "{{ $steps.count_total.output > ($steps.extract_pagination.output.offset + $steps.extract_pagination.output.limit) }}" + } + }, + "operation": "transform_data" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.format_response.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Fetch recent comments/posts from current user with pagination" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/dashboard/workflow/fetch-user-profile.backup.jsonscript b/packages/dashboard/workflow/fetch-user-profile.backup.jsonscript new file mode 100644 index 000000000..ae624a7fc --- /dev/null +++ b/packages/dashboard/workflow/fetch-user-profile.backup.jsonscript @@ -0,0 +1,65 @@ +{ + "version": "2.2.0", + "name": "Fetch User Profile", + "description": "Fetch current user profile information including name, email, avatar", + "trigger": { + "type": "http", + "method": "GET", + "path": "/profile" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.user.id }}", + "validator": "required" + }, + { + "id": "fetch_user", + "type": "operation", + "op": "database_read", + "entity": "User", + "params": { + "filter": { + "id": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "fetch_preferences", + "type": "operation", + "op": "database_read", + "entity": "UserPreferences", + "params": { + "filter": { + "userId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "format_response", + "type": "operation", + "op": "transform_data", + "output": { + "id": "{{ $steps.fetch_user.output.id }}", + "email": "{{ $steps.fetch_user.output.email }}", + "displayName": "{{ $steps.fetch_user.output.displayName }}", + "avatar": "{{ $steps.fetch_user.output.avatar }}", + "bio": "{{ $steps.fetch_user.output.bio }}", + "createdAt": "{{ $steps.fetch_user.output.createdAt }}", + "lastLogin": "{{ $steps.fetch_user.output.lastLogin }}", + "preferences": "{{ $steps.fetch_preferences.output }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } + ] +} diff --git a/packages/dashboard/workflow/fetch-user-profile.jsonscript b/packages/dashboard/workflow/fetch-user-profile.jsonscript index ae624a7fc..adf4da415 100644 --- a/packages/dashboard/workflow/fetch-user-profile.jsonscript +++ b/packages/dashboard/workflow/fetch-user-profile.jsonscript @@ -1,65 +1,107 @@ { - "version": "2.2.0", "name": "Fetch User Profile", - "description": "Fetch current user profile information including name, email, avatar", - "trigger": { - "type": "http", - "method": "GET", - "path": "/profile" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.user.id }}", - "validator": "required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } }, { "id": "fetch_user", - "type": "operation", - "op": "database_read", - "entity": "User", - "params": { + "name": "Fetch User", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { "filter": { "id": "{{ $context.user.id }}", "tenantId": "{{ $context.tenantId }}" - } + }, + "operation": "database_read", + "entity": "User" } }, { "id": "fetch_preferences", - "type": "operation", - "op": "database_read", - "entity": "UserPreferences", - "params": { + "name": "Fetch Preferences", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { "filter": { "userId": "{{ $context.user.id }}", "tenantId": "{{ $context.tenantId }}" - } + }, + "operation": "database_read", + "entity": "UserPreferences" } }, { "id": "format_response", - "type": "operation", - "op": "transform_data", - "output": { - "id": "{{ $steps.fetch_user.output.id }}", - "email": "{{ $steps.fetch_user.output.email }}", - "displayName": "{{ $steps.fetch_user.output.displayName }}", - "avatar": "{{ $steps.fetch_user.output.avatar }}", - "bio": "{{ $steps.fetch_user.output.bio }}", - "createdAt": "{{ $steps.fetch_user.output.createdAt }}", - "lastLogin": "{{ $steps.fetch_user.output.lastLogin }}", - "preferences": "{{ $steps.fetch_preferences.output }}" + "name": "Format Response", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "output": { + "id": "{{ $steps.fetch_user.output.id }}", + "email": "{{ $steps.fetch_user.output.email }}", + "displayName": "{{ $steps.fetch_user.output.displayName }}", + "avatar": "{{ $steps.fetch_user.output.avatar }}", + "bio": "{{ $steps.fetch_user.output.bio }}", + "createdAt": "{{ $steps.fetch_user.output.createdAt }}", + "lastLogin": "{{ $steps.fetch_user.output.lastLogin }}", + "preferences": "{{ $steps.fetch_preferences.output }}" + }, + "operation": "transform_data" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.format_response.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Fetch current user profile information including name, email, avatar" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/dashboard/workflow/fetch-user-stats.backup.jsonscript b/packages/dashboard/workflow/fetch-user-stats.backup.jsonscript new file mode 100644 index 000000000..e4144cffd --- /dev/null +++ b/packages/dashboard/workflow/fetch-user-stats.backup.jsonscript @@ -0,0 +1,94 @@ +{ + "version": "2.2.0", + "name": "Fetch User Statistics", + "description": "Calculate and fetch user statistics (posts, comments, activity, etc)", + "trigger": { + "type": "http", + "method": "GET", + "path": "/stats" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.user.id }}", + "validator": "required" + }, + { + "id": "count_forum_posts", + "type": "operation", + "op": "database_count", + "entity": "ForumPost", + "params": { + "filter": { + "authorId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}", + "isDeleted": false + } + } + }, + { + "id": "count_forum_threads", + "type": "operation", + "op": "database_count", + "entity": "ForumThread", + "params": { + "filter": { + "authorId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "count_media_uploads", + "type": "operation", + "op": "database_count", + "entity": "MediaAsset", + "params": { + "filter": { + "uploadedBy": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "calculate_engagement", + "type": "operation", + "op": "database_aggregate", + "entity": "ForumPost", + "params": { + "filter": { + "authorId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}", + "isDeleted": false + }, + "aggregations": { + "totalLikes": "sum(likes)", + "avgScore": "avg(score)" + } + } + }, + { + "id": "format_response", + "type": "operation", + "op": "transform_data", + "output": { + "forumPosts": "{{ $steps.count_forum_posts.output }}", + "forumThreads": "{{ $steps.count_forum_threads.output }}", + "mediaUploads": "{{ $steps.count_media_uploads.output }}", + "engagement": { + "totalLikes": "{{ $steps.calculate_engagement.output.totalLikes || 0 }}", + "averageScore": "{{ $steps.calculate_engagement.output.avgScore || 0 }}" + } + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } + ] +} diff --git a/packages/dashboard/workflow/fetch-user-stats.jsonscript b/packages/dashboard/workflow/fetch-user-stats.jsonscript index e4144cffd..c40022e3a 100644 --- a/packages/dashboard/workflow/fetch-user-stats.jsonscript +++ b/packages/dashboard/workflow/fetch-user-stats.jsonscript @@ -1,63 +1,87 @@ { - "version": "2.2.0", "name": "Fetch User Statistics", - "description": "Calculate and fetch user statistics (posts, comments, activity, etc)", - "trigger": { - "type": "http", - "method": "GET", - "path": "/stats" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.user.id }}", - "validator": "required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } }, { "id": "count_forum_posts", - "type": "operation", - "op": "database_count", - "entity": "ForumPost", - "params": { + "name": "Count Forum Posts", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { "filter": { "authorId": "{{ $context.user.id }}", "tenantId": "{{ $context.tenantId }}", "isDeleted": false - } + }, + "operation": "database_count", + "entity": "ForumPost" } }, { "id": "count_forum_threads", - "type": "operation", - "op": "database_count", - "entity": "ForumThread", - "params": { + "name": "Count Forum Threads", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { "filter": { "authorId": "{{ $context.user.id }}", "tenantId": "{{ $context.tenantId }}" - } + }, + "operation": "database_count", + "entity": "ForumThread" } }, { "id": "count_media_uploads", - "type": "operation", - "op": "database_count", - "entity": "MediaAsset", - "params": { + "name": "Count Media Uploads", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { "filter": { "uploadedBy": "{{ $context.user.id }}", "tenantId": "{{ $context.tenantId }}" - } + }, + "operation": "database_count", + "entity": "MediaAsset" } }, { "id": "calculate_engagement", - "type": "operation", - "op": "database_aggregate", - "entity": "ForumPost", - "params": { + "name": "Calculate Engagement", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { "filter": { "authorId": "{{ $context.user.id }}", "tenantId": "{{ $context.tenantId }}", @@ -66,29 +90,59 @@ "aggregations": { "totalLikes": "sum(likes)", "avgScore": "avg(score)" - } + }, + "operation": "database_aggregate", + "entity": "ForumPost" } }, { "id": "format_response", - "type": "operation", - "op": "transform_data", - "output": { - "forumPosts": "{{ $steps.count_forum_posts.output }}", - "forumThreads": "{{ $steps.count_forum_threads.output }}", - "mediaUploads": "{{ $steps.count_media_uploads.output }}", - "engagement": { - "totalLikes": "{{ $steps.calculate_engagement.output.totalLikes || 0 }}", - "averageScore": "{{ $steps.calculate_engagement.output.avgScore || 0 }}" - } + "name": "Format Response", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "output": { + "forumPosts": "{{ $steps.count_forum_posts.output }}", + "forumThreads": "{{ $steps.count_forum_threads.output }}", + "mediaUploads": "{{ $steps.count_media_uploads.output }}", + "engagement": { + "totalLikes": "{{ $steps.calculate_engagement.output.totalLikes || 0 }}", + "averageScore": "{{ $steps.calculate_engagement.output.avgScore || 0 }}" + } + }, + "operation": "transform_data" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.format_response.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Calculate and fetch user statistics (posts, comments, activity, etc)" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/data_table/workflow/fetch-data.backup.jsonscript b/packages/data_table/workflow/fetch-data.backup.jsonscript new file mode 100644 index 000000000..a72ff2290 --- /dev/null +++ b/packages/data_table/workflow/fetch-data.backup.jsonscript @@ -0,0 +1,143 @@ +{ + "version": "2.2.0", + "name": "Fetch Data for Table", + "description": "Fetch data with multi-tenant filtering, sorting, and pagination - CRITICAL for security", + "trigger": { + "type": "http", + "method": "POST", + "path": "/data-table/fetch" + }, + "nodes": [ + { + "id": "validate_tenant_critical", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required", + "errorMessage": "tenantId is REQUIRED for multi-tenant safety - data leak prevention" + }, + { + "id": "validate_user_critical", + "type": "operation", + "op": "validate", + "input": "{{ $context.user.id }}", + "validator": "required", + "errorMessage": "userId is REQUIRED for row-level ACL" + }, + { + "id": "validate_input", + "type": "operation", + "op": "validate", + "input": "{{ $json }}", + "rules": { + "entity": "required|string", + "sortBy": "string", + "sortOrder": "string", + "limit": "number|max:500", + "page": "number|min:1" + } + }, + { + "id": "extract_params", + "type": "operation", + "op": "transform_data", + "output": { + "entity": "{{ $json.entity }}", + "sortBy": "{{ $json.sortBy || 'createdAt' }}", + "sortOrder": "{{ $json.sortOrder === 'asc' ? 1 : -1 }}", + "limit": "{{ Math.min($json.limit || 50, 500) }}", + "page": "{{ $json.page || 1 }}" + } + }, + { + "id": "calculate_offset", + "type": "operation", + "op": "transform_data", + "output": "{{ ($steps.extract_params.output.page - 1) * $steps.extract_params.output.limit }}" + }, + { + "id": "build_filter", + "type": "operation", + "op": "transform_data", + "output": { + "tenantId": "{{ $context.tenantId }}", + "searchTerm": "{{ $json.search || null }}", + "filters": "{{ $json.filters || {} }}" + } + }, + { + "id": "apply_user_acl", + "type": "operation", + "op": "condition", + "condition": "{{ $context.user.level >= 3 || $build_filter.output.filters.userId === $context.user.id }}" + }, + { + "id": "fetch_data", + "type": "operation", + "op": "http_request", + "url": "{{ '/api/v1/' + $context.tenantId + '/' + $steps.extract_params.output.entity }}", + "method": "GET", + "queryParameters": { + "tenantId": "{{ $context.tenantId }}", + "sortBy": "{{ $steps.extract_params.output.sortBy }}", + "sortOrder": "{{ $steps.extract_params.output.sortOrder }}", + "limit": "{{ $steps.extract_params.output.limit }}", + "offset": "{{ $steps.calculate_offset.output }}", + "filters": "{{ JSON.stringify($steps.build_filter.output.filters) }}" + }, + "headers": { + "Authorization": "{{ 'Bearer ' + $context.token }}" + } + }, + { + "id": "validate_response", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.fetch_data.output.status === 200 }}" + }, + { + "id": "parse_response", + "type": "operation", + "op": "transform_data", + "input": "{{ $steps.fetch_data.output.body }}", + "output": { + "data": "{{ $steps.fetch_data.output.body.data }}", + "total": "{{ $steps.fetch_data.output.body.total }}" + } + }, + { + "id": "format_response", + "type": "operation", + "op": "transform_data", + "output": { + "data": "{{ $steps.parse_response.output.data }}", + "pagination": { + "total": "{{ $steps.parse_response.output.total }}", + "page": "{{ $steps.extract_params.output.page }}", + "limit": "{{ $steps.extract_params.output.limit }}", + "totalPages": "{{ Math.ceil($steps.parse_response.output.total / $steps.extract_params.output.limit) }}" + }, + "sorting": { + "sortBy": "{{ $steps.extract_params.output.sortBy }}", + "sortOrder": "{{ $steps.extract_params.output.sortOrder === 1 ? 'asc' : 'desc' }}" + } + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } + ], + "errorHandler": { + "type": "action", + "action": "http_response", + "status": 400, + "body": { + "error": "Failed to fetch data", + "message": "{{ $error.message }}" + } + } +} diff --git a/packages/data_table/workflow/fetch-data.jsonscript b/packages/data_table/workflow/fetch-data.jsonscript index a72ff2290..eec18f590 100644 --- a/packages/data_table/workflow/fetch-data.jsonscript +++ b/packages/data_table/workflow/fetch-data.jsonscript @@ -1,143 +1,236 @@ { - "version": "2.2.0", "name": "Fetch Data for Table", - "description": "Fetch data with multi-tenant filtering, sorting, and pagination - CRITICAL for security", - "trigger": { - "type": "http", - "method": "POST", - "path": "/data-table/fetch" - }, + "active": false, "nodes": [ { "id": "validate_tenant_critical", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required", - "errorMessage": "tenantId is REQUIRED for multi-tenant safety - data leak prevention" + "name": "Validate Tenant Critical", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required", + "errorMessage": "tenantId is REQUIRED for multi-tenant safety - data leak prevention" + } }, { "id": "validate_user_critical", - "type": "operation", - "op": "validate", - "input": "{{ $context.user.id }}", - "validator": "required", - "errorMessage": "userId is REQUIRED for row-level ACL" + "name": "Validate User Critical", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required", + "errorMessage": "userId is REQUIRED for row-level ACL" + } }, { "id": "validate_input", - "type": "operation", - "op": "validate", - "input": "{{ $json }}", - "rules": { - "entity": "required|string", - "sortBy": "string", - "sortOrder": "string", - "limit": "number|max:500", - "page": "number|min:1" - } - }, - { - "id": "extract_params", - "type": "operation", - "op": "transform_data", - "output": { - "entity": "{{ $json.entity }}", - "sortBy": "{{ $json.sortBy || 'createdAt' }}", - "sortOrder": "{{ $json.sortOrder === 'asc' ? 1 : -1 }}", - "limit": "{{ Math.min($json.limit || 50, 500) }}", - "page": "{{ $json.page || 1 }}" - } - }, - { - "id": "calculate_offset", - "type": "operation", - "op": "transform_data", - "output": "{{ ($steps.extract_params.output.page - 1) * $steps.extract_params.output.limit }}" - }, - { - "id": "build_filter", - "type": "operation", - "op": "transform_data", - "output": { - "tenantId": "{{ $context.tenantId }}", - "searchTerm": "{{ $json.search || null }}", - "filters": "{{ $json.filters || {} }}" - } - }, - { - "id": "apply_user_acl", - "type": "operation", - "op": "condition", - "condition": "{{ $context.user.level >= 3 || $build_filter.output.filters.userId === $context.user.id }}" - }, - { - "id": "fetch_data", - "type": "operation", - "op": "http_request", - "url": "{{ '/api/v1/' + $context.tenantId + '/' + $steps.extract_params.output.entity }}", - "method": "GET", - "queryParameters": { - "tenantId": "{{ $context.tenantId }}", - "sortBy": "{{ $steps.extract_params.output.sortBy }}", - "sortOrder": "{{ $steps.extract_params.output.sortOrder }}", - "limit": "{{ $steps.extract_params.output.limit }}", - "offset": "{{ $steps.calculate_offset.output }}", - "filters": "{{ JSON.stringify($steps.build_filter.output.filters) }}" - }, - "headers": { - "Authorization": "{{ 'Bearer ' + $context.token }}" - } - }, - { - "id": "validate_response", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.fetch_data.output.status === 200 }}" - }, - { - "id": "parse_response", - "type": "operation", - "op": "transform_data", - "input": "{{ $steps.fetch_data.output.body }}", - "output": { - "data": "{{ $steps.fetch_data.output.body.data }}", - "total": "{{ $steps.fetch_data.output.body.total }}" - } - }, - { - "id": "format_response", - "type": "operation", - "op": "transform_data", - "output": { - "data": "{{ $steps.parse_response.output.data }}", - "pagination": { - "total": "{{ $steps.parse_response.output.total }}", - "page": "{{ $steps.extract_params.output.page }}", - "limit": "{{ $steps.extract_params.output.limit }}", - "totalPages": "{{ Math.ceil($steps.parse_response.output.total / $steps.extract_params.output.limit) }}" - }, - "sorting": { - "sortBy": "{{ $steps.extract_params.output.sortBy }}", - "sortOrder": "{{ $steps.extract_params.output.sortOrder === 1 ? 'asc' : 'desc' }}" + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "entity": "required|string", + "sortBy": "string", + "sortOrder": "string", + "limit": "number|max:500", + "page": "number|min:1" } } }, + { + "id": "extract_params", + "name": "Extract Params", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "output": { + "entity": "{{ $json.entity }}", + "sortBy": "{{ $json.sortBy || 'createdAt' }}", + "sortOrder": "{{ $json.sortOrder === 'asc' ? 1 : -1 }}", + "limit": "{{ Math.min($json.limit || 50, 500) }}", + "page": "{{ $json.page || 1 }}" + }, + "operation": "transform_data" + } + }, + { + "id": "calculate_offset", + "name": "Calculate Offset", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "output": "{{ ($steps.extract_params.output.page - 1) * $steps.extract_params.output.limit }}", + "operation": "transform_data" + } + }, + { + "id": "build_filter", + "name": "Build Filter", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "output": { + "tenantId": "{{ $context.tenantId }}", + "searchTerm": "{{ $json.search || null }}", + "filters": "{{ $json.filters || {} }}" + }, + "operation": "transform_data" + } + }, + { + "id": "apply_user_acl", + "name": "Apply User Acl", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "condition": "{{ $context.user.level >= 3 || $build_filter.output.filters.userId === $context.user.id }}", + "operation": "condition" + } + }, + { + "id": "fetch_data", + "name": "Fetch Data", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { + "operation": "http_request", + "url": "{{ '/api/v1/' + $context.tenantId + '/' + $steps.extract_params.output.entity }}", + "method": "GET", + "queryParameters": { + "tenantId": "{{ $context.tenantId }}", + "sortBy": "{{ $steps.extract_params.output.sortBy }}", + "sortOrder": "{{ $steps.extract_params.output.sortOrder }}", + "limit": "{{ $steps.extract_params.output.limit }}", + "offset": "{{ $steps.calculate_offset.output }}", + "filters": "{{ JSON.stringify($steps.build_filter.output.filters) }}" + }, + "headers": { + "Authorization": "{{ 'Bearer ' + $context.token }}" + } + } + }, + { + "id": "validate_response", + "name": "Validate Response", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 700, + 500 + ], + "parameters": { + "condition": "{{ $steps.fetch_data.output.status === 200 }}", + "operation": "condition" + } + }, + { + "id": "parse_response", + "name": "Parse Response", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 700 + ], + "parameters": { + "input": "{{ $steps.fetch_data.output.body }}", + "output": { + "data": "{{ $steps.fetch_data.output.body.data }}", + "total": "{{ $steps.fetch_data.output.body.total }}" + }, + "operation": "transform_data" + } + }, + { + "id": "format_response", + "name": "Format Response", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 700 + ], + "parameters": { + "output": { + "data": "{{ $steps.parse_response.output.data }}", + "pagination": { + "total": "{{ $steps.parse_response.output.total }}", + "page": "{{ $steps.extract_params.output.page }}", + "limit": "{{ $steps.extract_params.output.limit }}", + "totalPages": "{{ Math.ceil($steps.parse_response.output.total / $steps.extract_params.output.limit) }}" + }, + "sorting": { + "sortBy": "{{ $steps.extract_params.output.sortBy }}", + "sortOrder": "{{ $steps.extract_params.output.sortOrder === 1 ? 'asc' : 'desc' }}" + } + }, + "operation": "transform_data" + } + }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.format_response.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 700 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } } ], - "errorHandler": { - "type": "action", - "action": "http_response", - "status": 400, - "body": { - "error": "Failed to fetch data", - "message": "{{ $error.message }}" - } + "connections": {}, + "staticData": {}, + "meta": { + "description": "Fetch data with multi-tenant filtering, sorting, and pagination - CRITICAL for security" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" } } diff --git a/packages/data_table/workflow/filtering.backup.jsonscript b/packages/data_table/workflow/filtering.backup.jsonscript new file mode 100644 index 000000000..394896dba --- /dev/null +++ b/packages/data_table/workflow/filtering.backup.jsonscript @@ -0,0 +1,65 @@ +{ + "version": "2.2.0", + "name": "Handle Data Table Filtering", + "description": "Apply filters to data while maintaining multi-tenant safety", + "trigger": { + "type": "operation", + "op": "transform" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required" + }, + { + "id": "extract_filters", + "type": "operation", + "op": "transform_data", + "input": "{{ $json }}", + "output": { + "status": "{{ $json.filters.status || null }}", + "searchTerm": "{{ $json.filters.search || '' }}", + "dateFrom": "{{ $json.filters.dateFrom || null }}", + "dateTo": "{{ $json.filters.dateTo || null }}" + } + }, + { + "id": "apply_status_filter", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.extract_filters.output.status !== null }}" + }, + { + "id": "apply_search_filter", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.extract_filters.output.searchTerm.length > 0 }}" + }, + { + "id": "apply_date_filter", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.extract_filters.output.dateFrom !== null || $steps.extract_filters.output.dateTo !== null }}" + }, + { + "id": "filter_data", + "type": "operation", + "op": "transform_data", + "input": "{{ $json.data }}", + "output": "{{ $json.data.filter(item => { let match = true; if ($steps.extract_filters.output.status && item.status !== $steps.extract_filters.output.status) match = false; if ($steps.extract_filters.output.searchTerm && !JSON.stringify(item).toLowerCase().includes($steps.extract_filters.output.searchTerm.toLowerCase())) match = false; if ($steps.extract_filters.output.dateFrom && new Date(item.createdAt) < new Date($steps.extract_filters.output.dateFrom)) match = false; if ($steps.extract_filters.output.dateTo && new Date(item.createdAt) > new Date($steps.extract_filters.output.dateTo)) match = false; return match; }) }}" + }, + { + "id": "return_filtered", + "type": "action", + "action": "emit_event", + "event": "data_filtered", + "data": { + "filters": "{{ $steps.extract_filters.output }}", + "data": "{{ $steps.filter_data.output }}" + } + } + ] +} diff --git a/packages/data_table/workflow/filtering.jsonscript b/packages/data_table/workflow/filtering.jsonscript index 394896dba..4e34ed1cf 100644 --- a/packages/data_table/workflow/filtering.jsonscript +++ b/packages/data_table/workflow/filtering.jsonscript @@ -1,65 +1,128 @@ { - "version": "2.2.0", "name": "Handle Data Table Filtering", - "description": "Apply filters to data while maintaining multi-tenant safety", - "trigger": { - "type": "operation", - "op": "transform" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" + } }, { "id": "extract_filters", - "type": "operation", - "op": "transform_data", - "input": "{{ $json }}", - "output": { - "status": "{{ $json.filters.status || null }}", - "searchTerm": "{{ $json.filters.search || '' }}", - "dateFrom": "{{ $json.filters.dateFrom || null }}", - "dateTo": "{{ $json.filters.dateTo || null }}" + "name": "Extract Filters", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "output": { + "status": "{{ $json.filters.status || null }}", + "searchTerm": "{{ $json.filters.search || '' }}", + "dateFrom": "{{ $json.filters.dateFrom || null }}", + "dateTo": "{{ $json.filters.dateTo || null }}" + }, + "operation": "transform_data" } }, { "id": "apply_status_filter", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.extract_filters.output.status !== null }}" + "name": "Apply Status Filter", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "condition": "{{ $steps.extract_filters.output.status !== null }}", + "operation": "condition" + } }, { "id": "apply_search_filter", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.extract_filters.output.searchTerm.length > 0 }}" + "name": "Apply Search Filter", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "condition": "{{ $steps.extract_filters.output.searchTerm.length > 0 }}", + "operation": "condition" + } }, { "id": "apply_date_filter", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.extract_filters.output.dateFrom !== null || $steps.extract_filters.output.dateTo !== null }}" + "name": "Apply Date Filter", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "condition": "{{ $steps.extract_filters.output.dateFrom !== null || $steps.extract_filters.output.dateTo !== null }}", + "operation": "condition" + } }, { "id": "filter_data", - "type": "operation", - "op": "transform_data", - "input": "{{ $json.data }}", - "output": "{{ $json.data.filter(item => { let match = true; if ($steps.extract_filters.output.status && item.status !== $steps.extract_filters.output.status) match = false; if ($steps.extract_filters.output.searchTerm && !JSON.stringify(item).toLowerCase().includes($steps.extract_filters.output.searchTerm.toLowerCase())) match = false; if ($steps.extract_filters.output.dateFrom && new Date(item.createdAt) < new Date($steps.extract_filters.output.dateFrom)) match = false; if ($steps.extract_filters.output.dateTo && new Date(item.createdAt) > new Date($steps.extract_filters.output.dateTo)) match = false; return match; }) }}" + "name": "Filter Data", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "input": "{{ $json.data }}", + "output": "{{ $json.data.filter(item => { let match = true; if ($steps.extract_filters.output.status && item.status !== $steps.extract_filters.output.status) match = false; if ($steps.extract_filters.output.searchTerm && !JSON.stringify(item).toLowerCase().includes($steps.extract_filters.output.searchTerm.toLowerCase())) match = false; if ($steps.extract_filters.output.dateFrom && new Date(item.createdAt) < new Date($steps.extract_filters.output.dateFrom)) match = false; if ($steps.extract_filters.output.dateTo && new Date(item.createdAt) > new Date($steps.extract_filters.output.dateTo)) match = false; return match; }) }}", + "operation": "transform_data" + } }, { "id": "return_filtered", - "type": "action", - "action": "emit_event", - "event": "data_filtered", - "data": { - "filters": "{{ $steps.extract_filters.output }}", - "data": "{{ $steps.filter_data.output }}" + "name": "Return Filtered", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "data": { + "filters": "{{ $steps.extract_filters.output }}", + "data": "{{ $steps.filter_data.output }}" + }, + "action": "emit_event", + "event": "data_filtered" } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Apply filters to data while maintaining multi-tenant safety" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/data_table/workflow/pagination.backup.jsonscript b/packages/data_table/workflow/pagination.backup.jsonscript new file mode 100644 index 000000000..ffa530655 --- /dev/null +++ b/packages/data_table/workflow/pagination.backup.jsonscript @@ -0,0 +1,56 @@ +{ + "version": "2.2.0", + "name": "Handle Data Table Pagination", + "description": "Apply pagination logic to data results", + "trigger": { + "type": "operation", + "op": "transform" + }, + "nodes": [ + { + "id": "extract_pagination_params", + "type": "operation", + "op": "transform_data", + "input": "{{ $json }}", + "output": { + "page": "{{ Math.max($json.page || 1, 1) }}", + "limit": "{{ Math.min($json.limit || 50, 500) }}" + } + }, + { + "id": "calculate_offset", + "type": "operation", + "op": "transform_data", + "output": "{{ ($steps.extract_pagination_params.output.page - 1) * $steps.extract_pagination_params.output.limit }}" + }, + { + "id": "slice_data", + "type": "operation", + "op": "transform_data", + "input": "{{ $json.data }}", + "output": "{{ $json.data.slice($steps.calculate_offset.output, $steps.calculate_offset.output + $steps.extract_pagination_params.output.limit) }}" + }, + { + "id": "calculate_total_pages", + "type": "operation", + "op": "transform_data", + "output": "{{ Math.ceil($json.data.length / $steps.extract_pagination_params.output.limit) }}" + }, + { + "id": "return_paginated", + "type": "action", + "action": "emit_event", + "event": "data_paginated", + "data": { + "data": "{{ $steps.slice_data.output }}", + "pagination": { + "page": "{{ $steps.extract_pagination_params.output.page }}", + "limit": "{{ $steps.extract_pagination_params.output.limit }}", + "total": "{{ $json.data.length }}", + "totalPages": "{{ $steps.calculate_total_pages.output }}", + "hasMore": "{{ $steps.extract_pagination_params.output.page < $steps.calculate_total_pages.output }}" + } + } + } + ] +} diff --git a/packages/data_table/workflow/pagination.jsonscript b/packages/data_table/workflow/pagination.jsonscript index ffa530655..1a9c6c543 100644 --- a/packages/data_table/workflow/pagination.jsonscript +++ b/packages/data_table/workflow/pagination.jsonscript @@ -1,56 +1,103 @@ { - "version": "2.2.0", "name": "Handle Data Table Pagination", - "description": "Apply pagination logic to data results", - "trigger": { - "type": "operation", - "op": "transform" - }, + "active": false, "nodes": [ { "id": "extract_pagination_params", - "type": "operation", - "op": "transform_data", - "input": "{{ $json }}", - "output": { - "page": "{{ Math.max($json.page || 1, 1) }}", - "limit": "{{ Math.min($json.limit || 50, 500) }}" + "name": "Extract Pagination Params", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "output": { + "page": "{{ Math.max($json.page || 1, 1) }}", + "limit": "{{ Math.min($json.limit || 50, 500) }}" + }, + "operation": "transform_data" } }, { "id": "calculate_offset", - "type": "operation", - "op": "transform_data", - "output": "{{ ($steps.extract_pagination_params.output.page - 1) * $steps.extract_pagination_params.output.limit }}" + "name": "Calculate Offset", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "output": "{{ ($steps.extract_pagination_params.output.page - 1) * $steps.extract_pagination_params.output.limit }}", + "operation": "transform_data" + } }, { "id": "slice_data", - "type": "operation", - "op": "transform_data", - "input": "{{ $json.data }}", - "output": "{{ $json.data.slice($steps.calculate_offset.output, $steps.calculate_offset.output + $steps.extract_pagination_params.output.limit) }}" + "name": "Slice Data", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "input": "{{ $json.data }}", + "output": "{{ $json.data.slice($steps.calculate_offset.output, $steps.calculate_offset.output + $steps.extract_pagination_params.output.limit) }}", + "operation": "transform_data" + } }, { "id": "calculate_total_pages", - "type": "operation", - "op": "transform_data", - "output": "{{ Math.ceil($json.data.length / $steps.extract_pagination_params.output.limit) }}" + "name": "Calculate Total Pages", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "output": "{{ Math.ceil($json.data.length / $steps.extract_pagination_params.output.limit) }}", + "operation": "transform_data" + } }, { "id": "return_paginated", - "type": "action", - "action": "emit_event", - "event": "data_paginated", - "data": { - "data": "{{ $steps.slice_data.output }}", - "pagination": { - "page": "{{ $steps.extract_pagination_params.output.page }}", - "limit": "{{ $steps.extract_pagination_params.output.limit }}", - "total": "{{ $json.data.length }}", - "totalPages": "{{ $steps.calculate_total_pages.output }}", - "hasMore": "{{ $steps.extract_pagination_params.output.page < $steps.calculate_total_pages.output }}" - } + "name": "Return Paginated", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "data": { + "data": "{{ $steps.slice_data.output }}", + "pagination": { + "page": "{{ $steps.extract_pagination_params.output.page }}", + "limit": "{{ $steps.extract_pagination_params.output.limit }}", + "total": "{{ $json.data.length }}", + "totalPages": "{{ $steps.calculate_total_pages.output }}", + "hasMore": "{{ $steps.extract_pagination_params.output.page < $steps.calculate_total_pages.output }}" + } + }, + "action": "emit_event", + "event": "data_paginated" } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Apply pagination logic to data results" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/data_table/workflow/sorting.backup.jsonscript b/packages/data_table/workflow/sorting.backup.jsonscript new file mode 100644 index 000000000..bb589e606 --- /dev/null +++ b/packages/data_table/workflow/sorting.backup.jsonscript @@ -0,0 +1,45 @@ +{ + "version": "2.2.0", + "name": "Handle Data Table Sorting", + "description": "Transform data based on sorting parameters", + "trigger": { + "type": "operation", + "op": "transform" + }, + "nodes": [ + { + "id": "extract_sort_params", + "type": "operation", + "op": "transform_data", + "input": "{{ $json }}", + "output": { + "sortBy": "{{ $json.sortBy || 'createdAt' }}", + "sortOrder": "{{ $json.sortOrder || 'desc' }}" + } + }, + { + "id": "validate_sort_fields", + "type": "operation", + "op": "condition", + "condition": "{{ ['id', 'name', 'email', 'createdAt', 'updatedAt', 'status'].includes($steps.extract_sort_params.output.sortBy) }}" + }, + { + "id": "apply_sort", + "type": "operation", + "op": "transform_data", + "input": "{{ $json.data }}", + "output": "{{ $json.data.sort((a, b) => { const aVal = a[$steps.extract_sort_params.output.sortBy]; const bVal = b[$steps.extract_sort_params.output.sortBy]; if ($steps.extract_sort_params.output.sortOrder === 'asc') return aVal > bVal ? 1 : -1; return aVal < bVal ? 1 : -1; }) }}" + }, + { + "id": "return_sorted", + "type": "action", + "action": "emit_event", + "event": "data_sorted", + "data": { + "sortBy": "{{ $steps.extract_sort_params.output.sortBy }}", + "sortOrder": "{{ $steps.extract_sort_params.output.sortOrder }}", + "data": "{{ $steps.apply_sort.output }}" + } + } + ] +} diff --git a/packages/data_table/workflow/sorting.jsonscript b/packages/data_table/workflow/sorting.jsonscript index bb589e606..3c204e828 100644 --- a/packages/data_table/workflow/sorting.jsonscript +++ b/packages/data_table/workflow/sorting.jsonscript @@ -1,45 +1,84 @@ { - "version": "2.2.0", "name": "Handle Data Table Sorting", - "description": "Transform data based on sorting parameters", - "trigger": { - "type": "operation", - "op": "transform" - }, + "active": false, "nodes": [ { "id": "extract_sort_params", - "type": "operation", - "op": "transform_data", - "input": "{{ $json }}", - "output": { - "sortBy": "{{ $json.sortBy || 'createdAt' }}", - "sortOrder": "{{ $json.sortOrder || 'desc' }}" + "name": "Extract Sort Params", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "output": { + "sortBy": "{{ $json.sortBy || 'createdAt' }}", + "sortOrder": "{{ $json.sortOrder || 'desc' }}" + }, + "operation": "transform_data" } }, { "id": "validate_sort_fields", - "type": "operation", - "op": "condition", - "condition": "{{ ['id', 'name', 'email', 'createdAt', 'updatedAt', 'status'].includes($steps.extract_sort_params.output.sortBy) }}" + "name": "Validate Sort Fields", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "condition": "{{ ['id', 'name', 'email', 'createdAt', 'updatedAt', 'status'].includes($steps.extract_sort_params.output.sortBy) }}", + "operation": "condition" + } }, { "id": "apply_sort", - "type": "operation", - "op": "transform_data", - "input": "{{ $json.data }}", - "output": "{{ $json.data.sort((a, b) => { const aVal = a[$steps.extract_sort_params.output.sortBy]; const bVal = b[$steps.extract_sort_params.output.sortBy]; if ($steps.extract_sort_params.output.sortOrder === 'asc') return aVal > bVal ? 1 : -1; return aVal < bVal ? 1 : -1; }) }}" + "name": "Apply Sort", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "input": "{{ $json.data }}", + "output": "{{ $json.data.sort((a, b) => { const aVal = a[$steps.extract_sort_params.output.sortBy]; const bVal = b[$steps.extract_sort_params.output.sortBy]; if ($steps.extract_sort_params.output.sortOrder === 'asc') return aVal > bVal ? 1 : -1; return aVal < bVal ? 1 : -1; }) }}", + "operation": "transform_data" + } }, { "id": "return_sorted", - "type": "action", - "action": "emit_event", - "event": "data_sorted", - "data": { - "sortBy": "{{ $steps.extract_sort_params.output.sortBy }}", - "sortOrder": "{{ $steps.extract_sort_params.output.sortOrder }}", - "data": "{{ $steps.apply_sort.output }}" + "name": "Return Sorted", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "data": { + "sortBy": "{{ $steps.extract_sort_params.output.sortBy }}", + "sortOrder": "{{ $steps.extract_sort_params.output.sortOrder }}", + "data": "{{ $steps.apply_sort.output }}" + }, + "action": "emit_event", + "event": "data_sorted" } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Transform data based on sorting parameters" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/forum_forge/workflow/create-post.backup.jsonscript b/packages/forum_forge/workflow/create-post.backup.jsonscript new file mode 100644 index 000000000..4872d682c --- /dev/null +++ b/packages/forum_forge/workflow/create-post.backup.jsonscript @@ -0,0 +1,95 @@ +{ + "version": "2.2.0", + "name": "Create Forum Post", + "description": "Create a new post (reply) in a forum thread", + "trigger": { + "type": "http", + "method": "POST", + "path": "/forum/threads/:threadId/posts" + }, + "nodes": [ + { + "id": "validate_tenant", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required" + }, + { + "id": "validate_input", + "type": "operation", + "op": "validate", + "input": "{{ $json }}", + "rules": { + "content": "required|string|minLength:3|maxLength:5000" + } + }, + { + "id": "check_thread_exists", + "type": "operation", + "op": "database_read", + "entity": "ForumThread", + "params": { + "filter": { + "id": "{{ $json.threadId }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "check_thread_locked", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.check_thread_exists.output.isLocked !== true }}" + }, + { + "id": "create_post", + "type": "operation", + "op": "database_create", + "entity": "ForumPost", + "data": { + "tenantId": "{{ $context.tenantId }}", + "threadId": "{{ $json.threadId }}", + "authorId": "{{ $context.user.id }}", + "content": "{{ $json.content }}", + "editedAt": null, + "isDeleted": false, + "createdAt": "{{ new Date().toISOString() }}" + } + }, + { + "id": "increment_thread_count", + "type": "operation", + "op": "database_update", + "entity": "ForumThread", + "params": { + "filter": { + "id": "{{ $json.threadId }}" + }, + "data": { + "postCount": "{{ $steps.check_thread_exists.output.postCount + 1 }}", + "updatedAt": "{{ new Date().toISOString() }}" + } + } + }, + { + "id": "emit_event", + "type": "action", + "action": "emit_event", + "event": "post_created", + "channel": "{{ 'forum:thread:' + $json.threadId }}", + "data": { + "postId": "{{ $steps.create_post.output.id }}", + "threadId": "{{ $json.threadId }}", + "authorId": "{{ $context.user.id }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 201, + "body": "{{ $steps.create_post.output }}" + } + ] +} diff --git a/packages/forum_forge/workflow/create-post.jsonscript b/packages/forum_forge/workflow/create-post.jsonscript index 4872d682c..f40357091 100644 --- a/packages/forum_forge/workflow/create-post.jsonscript +++ b/packages/forum_forge/workflow/create-post.jsonscript @@ -1,95 +1,161 @@ { - "version": "2.2.0", "name": "Create Forum Post", - "description": "Create a new post (reply) in a forum thread", - "trigger": { - "type": "http", - "method": "POST", - "path": "/forum/threads/:threadId/posts" - }, + "active": false, "nodes": [ { "id": "validate_tenant", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required" - }, - { - "id": "validate_input", - "type": "operation", - "op": "validate", - "input": "{{ $json }}", - "rules": { - "content": "required|string|minLength:3|maxLength:5000" + "name": "Validate Tenant", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" } }, { - "id": "check_thread_exists", - "type": "operation", - "op": "database_read", - "entity": "ForumThread", - "params": { - "filter": { - "id": "{{ $json.threadId }}", - "tenantId": "{{ $context.tenantId }}" + "id": "validate_input", + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "content": "required|string|minLength:3|maxLength:5000" } } }, + { + "id": "check_thread_exists", + "name": "Check Thread Exists", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "filter": { + "id": "{{ $json.threadId }}", + "tenantId": "{{ $context.tenantId }}" + }, + "operation": "database_read", + "entity": "ForumThread" + } + }, { "id": "check_thread_locked", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.check_thread_exists.output.isLocked !== true }}" + "name": "Check Thread Locked", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "condition": "{{ $steps.check_thread_exists.output.isLocked !== true }}", + "operation": "condition" + } }, { "id": "create_post", - "type": "operation", - "op": "database_create", - "entity": "ForumPost", - "data": { - "tenantId": "{{ $context.tenantId }}", - "threadId": "{{ $json.threadId }}", - "authorId": "{{ $context.user.id }}", - "content": "{{ $json.content }}", - "editedAt": null, - "isDeleted": false, - "createdAt": "{{ new Date().toISOString() }}" + "name": "Create Post", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "data": { + "tenantId": "{{ $context.tenantId }}", + "threadId": "{{ $json.threadId }}", + "authorId": "{{ $context.user.id }}", + "content": "{{ $json.content }}", + "editedAt": null, + "isDeleted": false, + "createdAt": "{{ new Date().toISOString() }}" + }, + "operation": "database_create", + "entity": "ForumPost" } }, { "id": "increment_thread_count", - "type": "operation", - "op": "database_update", - "entity": "ForumThread", - "params": { + "name": "Increment Thread Count", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { "filter": { "id": "{{ $json.threadId }}" }, "data": { "postCount": "{{ $steps.check_thread_exists.output.postCount + 1 }}", "updatedAt": "{{ new Date().toISOString() }}" - } + }, + "operation": "database_update", + "entity": "ForumThread" } }, { "id": "emit_event", - "type": "action", - "action": "emit_event", - "event": "post_created", - "channel": "{{ 'forum:thread:' + $json.threadId }}", - "data": { - "postId": "{{ $steps.create_post.output.id }}", - "threadId": "{{ $json.threadId }}", - "authorId": "{{ $context.user.id }}" + "name": "Emit Event", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "data": { + "postId": "{{ $steps.create_post.output.id }}", + "threadId": "{{ $json.threadId }}", + "authorId": "{{ $context.user.id }}" + }, + "action": "emit_event", + "event": "post_created", + "channel": "{{ 'forum:thread:' + $json.threadId }}" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 201, - "body": "{{ $steps.create_post.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { + "action": "http_response", + "status": 201, + "body": "{{ $steps.create_post.output }}" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Create a new post (reply) in a forum thread" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/forum_forge/workflow/create-thread.backup.jsonscript b/packages/forum_forge/workflow/create-thread.backup.jsonscript new file mode 100644 index 000000000..cccc92822 --- /dev/null +++ b/packages/forum_forge/workflow/create-thread.backup.jsonscript @@ -0,0 +1,89 @@ +{ + "version": "2.2.0", + "name": "Create Forum Thread", + "description": "Create a new forum thread with validation and slug generation", + "trigger": { + "type": "http", + "method": "POST", + "path": "/forum/threads" + }, + "nodes": [ + { + "id": "validate_tenant", + "type": "operation", + "op": "condition", + "condition": "{{ $context.tenantId !== undefined }}" + }, + { + "id": "validate_user", + "type": "operation", + "op": "condition", + "condition": "{{ $context.user.id !== undefined }}" + }, + { + "id": "validate_input", + "type": "operation", + "op": "validate", + "input": "{{ $json }}", + "rules": { + "categoryId": "required|string", + "title": "required|string|minLength:3|maxLength:200", + "content": "required|string|minLength:10|maxLength:5000" + } + }, + { + "id": "generate_slug", + "type": "operation", + "op": "transform_data", + "output": "{{ $json.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') }}" + }, + { + "id": "create_thread", + "type": "operation", + "op": "database_create", + "entity": "ForumThread", + "data": { + "tenantId": "{{ $context.tenantId }}", + "categoryId": "{{ $json.categoryId }}", + "authorId": "{{ $context.user.id }}", + "title": "{{ $json.title }}", + "slug": "{{ $steps.generate_slug.output }}", + "content": "{{ $json.content }}", + "viewCount": 0, + "postCount": 1, + "isLocked": false, + "isPinned": false, + "createdAt": "{{ new Date().toISOString() }}", + "updatedAt": "{{ new Date().toISOString() }}" + } + }, + { + "id": "emit_created", + "type": "action", + "action": "emit_event", + "event": "thread_created", + "channel": "{{ 'forum:' + $context.tenantId }}", + "data": { + "threadId": "{{ $steps.create_thread.output.id }}", + "title": "{{ $json.title }}", + "authorId": "{{ $context.user.id }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 201, + "body": "{{ $steps.create_thread.output }}" + } + ], + "errorHandler": { + "type": "action", + "action": "http_response", + "status": 400, + "body": { + "error": "Failed to create thread", + "message": "{{ $error.message }}" + } + } +} diff --git a/packages/forum_forge/workflow/create-thread.jsonscript b/packages/forum_forge/workflow/create-thread.jsonscript index cccc92822..1c0caa7ee 100644 --- a/packages/forum_forge/workflow/create-thread.jsonscript +++ b/packages/forum_forge/workflow/create-thread.jsonscript @@ -1,89 +1,142 @@ { - "version": "2.2.0", "name": "Create Forum Thread", - "description": "Create a new forum thread with validation and slug generation", - "trigger": { - "type": "http", - "method": "POST", - "path": "/forum/threads" - }, + "active": false, "nodes": [ { "id": "validate_tenant", - "type": "operation", - "op": "condition", - "condition": "{{ $context.tenantId !== undefined }}" + "name": "Validate Tenant", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "condition": "{{ $context.tenantId !== undefined }}", + "operation": "condition" + } }, { "id": "validate_user", - "type": "operation", - "op": "condition", - "condition": "{{ $context.user.id !== undefined }}" + "name": "Validate User", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "condition": "{{ $context.user.id !== undefined }}", + "operation": "condition" + } }, { "id": "validate_input", - "type": "operation", - "op": "validate", - "input": "{{ $json }}", - "rules": { - "categoryId": "required|string", - "title": "required|string|minLength:3|maxLength:200", - "content": "required|string|minLength:10|maxLength:5000" + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "categoryId": "required|string", + "title": "required|string|minLength:3|maxLength:200", + "content": "required|string|minLength:10|maxLength:5000" + } } }, { "id": "generate_slug", - "type": "operation", - "op": "transform_data", - "output": "{{ $json.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') }}" + "name": "Generate Slug", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "output": "{{ $json.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') }}", + "operation": "transform_data" + } }, { "id": "create_thread", - "type": "operation", - "op": "database_create", - "entity": "ForumThread", - "data": { - "tenantId": "{{ $context.tenantId }}", - "categoryId": "{{ $json.categoryId }}", - "authorId": "{{ $context.user.id }}", - "title": "{{ $json.title }}", - "slug": "{{ $steps.generate_slug.output }}", - "content": "{{ $json.content }}", - "viewCount": 0, - "postCount": 1, - "isLocked": false, - "isPinned": false, - "createdAt": "{{ new Date().toISOString() }}", - "updatedAt": "{{ new Date().toISOString() }}" + "name": "Create Thread", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "data": { + "tenantId": "{{ $context.tenantId }}", + "categoryId": "{{ $json.categoryId }}", + "authorId": "{{ $context.user.id }}", + "title": "{{ $json.title }}", + "slug": "{{ $steps.generate_slug.output }}", + "content": "{{ $json.content }}", + "viewCount": 0, + "postCount": 1, + "isLocked": false, + "isPinned": false, + "createdAt": "{{ new Date().toISOString() }}", + "updatedAt": "{{ new Date().toISOString() }}" + }, + "operation": "database_create", + "entity": "ForumThread" } }, { "id": "emit_created", - "type": "action", - "action": "emit_event", - "event": "thread_created", - "channel": "{{ 'forum:' + $context.tenantId }}", - "data": { - "threadId": "{{ $steps.create_thread.output.id }}", - "title": "{{ $json.title }}", - "authorId": "{{ $context.user.id }}" + "name": "Emit Created", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "data": { + "threadId": "{{ $steps.create_thread.output.id }}", + "title": "{{ $json.title }}", + "authorId": "{{ $context.user.id }}" + }, + "action": "emit_event", + "event": "thread_created", + "channel": "{{ 'forum:' + $context.tenantId }}" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 201, - "body": "{{ $steps.create_thread.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "action": "http_response", + "status": 201, + "body": "{{ $steps.create_thread.output }}" + } } ], - "errorHandler": { - "type": "action", - "action": "http_response", - "status": 400, - "body": { - "error": "Failed to create thread", - "message": "{{ $error.message }}" - } + "connections": {}, + "staticData": {}, + "meta": { + "description": "Create a new forum thread with validation and slug generation" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" } } diff --git a/packages/forum_forge/workflow/delete-post.backup.jsonscript b/packages/forum_forge/workflow/delete-post.backup.jsonscript new file mode 100644 index 000000000..56cfc3e5a --- /dev/null +++ b/packages/forum_forge/workflow/delete-post.backup.jsonscript @@ -0,0 +1,96 @@ +{ + "version": "2.2.0", + "name": "Delete Forum Post", + "description": "Delete or soft-delete a forum post with authorization checks", + "trigger": { + "type": "http", + "method": "DELETE", + "path": "/forum/posts/:postId" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required" + }, + { + "id": "fetch_post", + "type": "operation", + "op": "database_read", + "entity": "ForumPost", + "params": { + "filter": { + "id": "{{ $json.postId }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "check_authorization", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.fetch_post.output.authorId === $context.user.id || $context.user.level >= 3 }}" + }, + { + "id": "soft_delete_post", + "type": "operation", + "op": "database_update", + "entity": "ForumPost", + "params": { + "filter": { + "id": "{{ $json.postId }}" + }, + "data": { + "isDeleted": true, + "deletedAt": "{{ new Date().toISOString() }}" + } + } + }, + { + "id": "decrement_thread_count", + "type": "operation", + "op": "database_read", + "entity": "ForumThread", + "params": { + "filter": { + "id": "{{ $steps.fetch_post.output.threadId }}" + } + } + }, + { + "id": "update_thread_count", + "type": "operation", + "op": "database_update", + "entity": "ForumThread", + "params": { + "filter": { + "id": "{{ $steps.fetch_post.output.threadId }}" + }, + "data": { + "postCount": "{{ Math.max($steps.decrement_thread_count.output.postCount - 1, 0) }}" + } + } + }, + { + "id": "emit_deleted", + "type": "action", + "action": "emit_event", + "event": "post_deleted", + "channel": "{{ 'forum:thread:' + $steps.fetch_post.output.threadId }}", + "data": { + "postId": "{{ $json.postId }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": { + "message": "Post deleted successfully" + } + } + ] +} diff --git a/packages/forum_forge/workflow/delete-post.jsonscript b/packages/forum_forge/workflow/delete-post.jsonscript index 56cfc3e5a..5703be4e0 100644 --- a/packages/forum_forge/workflow/delete-post.jsonscript +++ b/packages/forum_forge/workflow/delete-post.jsonscript @@ -1,96 +1,158 @@ { - "version": "2.2.0", "name": "Delete Forum Post", - "description": "Delete or soft-delete a forum post with authorization checks", - "trigger": { - "type": "http", - "method": "DELETE", - "path": "/forum/posts/:postId" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" + } }, { "id": "fetch_post", - "type": "operation", - "op": "database_read", - "entity": "ForumPost", - "params": { + "name": "Fetch Post", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { "filter": { "id": "{{ $json.postId }}", "tenantId": "{{ $context.tenantId }}" - } + }, + "operation": "database_read", + "entity": "ForumPost" } }, { "id": "check_authorization", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.fetch_post.output.authorId === $context.user.id || $context.user.level >= 3 }}" + "name": "Check Authorization", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "condition": "{{ $steps.fetch_post.output.authorId === $context.user.id || $context.user.level >= 3 }}", + "operation": "condition" + } }, { "id": "soft_delete_post", - "type": "operation", - "op": "database_update", - "entity": "ForumPost", - "params": { + "name": "Soft Delete Post", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { "filter": { "id": "{{ $json.postId }}" }, "data": { "isDeleted": true, "deletedAt": "{{ new Date().toISOString() }}" - } + }, + "operation": "database_update", + "entity": "ForumPost" } }, { "id": "decrement_thread_count", - "type": "operation", - "op": "database_read", - "entity": "ForumThread", - "params": { + "name": "Decrement Thread Count", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { "filter": { "id": "{{ $steps.fetch_post.output.threadId }}" - } + }, + "operation": "database_read", + "entity": "ForumThread" } }, { "id": "update_thread_count", - "type": "operation", - "op": "database_update", - "entity": "ForumThread", - "params": { + "name": "Update Thread Count", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { "filter": { "id": "{{ $steps.fetch_post.output.threadId }}" }, "data": { "postCount": "{{ Math.max($steps.decrement_thread_count.output.postCount - 1, 0) }}" - } + }, + "operation": "database_update", + "entity": "ForumThread" } }, { "id": "emit_deleted", - "type": "action", - "action": "emit_event", - "event": "post_deleted", - "channel": "{{ 'forum:thread:' + $steps.fetch_post.output.threadId }}", - "data": { - "postId": "{{ $json.postId }}" + "name": "Emit Deleted", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "data": { + "postId": "{{ $json.postId }}" + }, + "action": "emit_event", + "event": "post_deleted", + "channel": "{{ 'forum:thread:' + $steps.fetch_post.output.threadId }}" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": { - "message": "Post deleted successfully" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": { + "message": "Post deleted successfully" + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Delete or soft-delete a forum post with authorization checks" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/forum_forge/workflow/list-threads.backup.jsonscript b/packages/forum_forge/workflow/list-threads.backup.jsonscript new file mode 100644 index 000000000..f6c40e0b8 --- /dev/null +++ b/packages/forum_forge/workflow/list-threads.backup.jsonscript @@ -0,0 +1,87 @@ +{ + "version": "2.2.0", + "name": "List Forum Threads", + "description": "List forum threads in a category with pagination and sorting", + "trigger": { + "type": "http", + "method": "GET", + "path": "/forum/categories/:categoryId/threads" + }, + "nodes": [ + { + "id": "validate_tenant", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required" + }, + { + "id": "extract_params", + "type": "operation", + "op": "transform_data", + "output": { + "categoryId": "{{ $json.categoryId }}", + "sortBy": "{{ $json.sortBy || 'updatedAt' }}", + "sortOrder": "{{ $json.sortOrder || 'desc' }}", + "limit": "{{ Math.min($json.limit || 20, 100) }}", + "page": "{{ $json.page || 1 }}" + } + }, + { + "id": "calculate_offset", + "type": "operation", + "op": "transform_data", + "output": "{{ ($steps.extract_params.output.page - 1) * $steps.extract_params.output.limit }}" + }, + { + "id": "fetch_threads", + "type": "operation", + "op": "database_read", + "entity": "ForumThread", + "params": { + "filter": { + "tenantId": "{{ $context.tenantId }}", + "categoryId": "{{ $steps.extract_params.output.categoryId }}" + }, + "sort": { + "{{ $steps.extract_params.output.sortBy }}": "{{ $steps.extract_params.output.sortOrder === 'asc' ? 1 : -1 }}" + }, + "limit": "{{ $steps.extract_params.output.limit }}", + "offset": "{{ $steps.calculate_offset.output }}" + } + }, + { + "id": "fetch_total", + "type": "operation", + "op": "database_count", + "entity": "ForumThread", + "params": { + "filter": { + "tenantId": "{{ $context.tenantId }}", + "categoryId": "{{ $steps.extract_params.output.categoryId }}" + } + } + }, + { + "id": "format_response", + "type": "operation", + "op": "transform_data", + "output": { + "threads": "{{ $steps.fetch_threads.output }}", + "pagination": { + "total": "{{ $steps.fetch_total.output }}", + "page": "{{ $steps.extract_params.output.page }}", + "limit": "{{ $steps.extract_params.output.limit }}", + "totalPages": "{{ Math.ceil($steps.fetch_total.output / $steps.extract_params.output.limit) }}" + } + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } + ] +} diff --git a/packages/forum_forge/workflow/list-threads.jsonscript b/packages/forum_forge/workflow/list-threads.jsonscript index f6c40e0b8..19ff8b99e 100644 --- a/packages/forum_forge/workflow/list-threads.jsonscript +++ b/packages/forum_forge/workflow/list-threads.jsonscript @@ -1,44 +1,66 @@ { - "version": "2.2.0", "name": "List Forum Threads", - "description": "List forum threads in a category with pagination and sorting", - "trigger": { - "type": "http", - "method": "GET", - "path": "/forum/categories/:categoryId/threads" - }, + "active": false, "nodes": [ { "id": "validate_tenant", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required" + "name": "Validate Tenant", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" + } }, { "id": "extract_params", - "type": "operation", - "op": "transform_data", - "output": { - "categoryId": "{{ $json.categoryId }}", - "sortBy": "{{ $json.sortBy || 'updatedAt' }}", - "sortOrder": "{{ $json.sortOrder || 'desc' }}", - "limit": "{{ Math.min($json.limit || 20, 100) }}", - "page": "{{ $json.page || 1 }}" + "name": "Extract Params", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "output": { + "categoryId": "{{ $json.categoryId }}", + "sortBy": "{{ $json.sortBy || 'updatedAt' }}", + "sortOrder": "{{ $json.sortOrder || 'desc' }}", + "limit": "{{ Math.min($json.limit || 20, 100) }}", + "page": "{{ $json.page || 1 }}" + }, + "operation": "transform_data" } }, { "id": "calculate_offset", - "type": "operation", - "op": "transform_data", - "output": "{{ ($steps.extract_params.output.page - 1) * $steps.extract_params.output.limit }}" + "name": "Calculate Offset", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "output": "{{ ($steps.extract_params.output.page - 1) * $steps.extract_params.output.limit }}", + "operation": "transform_data" + } }, { "id": "fetch_threads", - "type": "operation", - "op": "database_read", - "entity": "ForumThread", - "params": { + "name": "Fetch Threads", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { "filter": { "tenantId": "{{ $context.tenantId }}", "categoryId": "{{ $steps.extract_params.output.categoryId }}" @@ -47,41 +69,77 @@ "{{ $steps.extract_params.output.sortBy }}": "{{ $steps.extract_params.output.sortOrder === 'asc' ? 1 : -1 }}" }, "limit": "{{ $steps.extract_params.output.limit }}", - "offset": "{{ $steps.calculate_offset.output }}" + "offset": "{{ $steps.calculate_offset.output }}", + "operation": "database_read", + "entity": "ForumThread" } }, { "id": "fetch_total", - "type": "operation", - "op": "database_count", - "entity": "ForumThread", - "params": { + "name": "Fetch Total", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { "filter": { "tenantId": "{{ $context.tenantId }}", "categoryId": "{{ $steps.extract_params.output.categoryId }}" - } + }, + "operation": "database_count", + "entity": "ForumThread" } }, { "id": "format_response", - "type": "operation", - "op": "transform_data", - "output": { - "threads": "{{ $steps.fetch_threads.output }}", - "pagination": { - "total": "{{ $steps.fetch_total.output }}", - "page": "{{ $steps.extract_params.output.page }}", - "limit": "{{ $steps.extract_params.output.limit }}", - "totalPages": "{{ Math.ceil($steps.fetch_total.output / $steps.extract_params.output.limit) }}" - } + "name": "Format Response", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "output": { + "threads": "{{ $steps.fetch_threads.output }}", + "pagination": { + "total": "{{ $steps.fetch_total.output }}", + "page": "{{ $steps.extract_params.output.page }}", + "limit": "{{ $steps.extract_params.output.limit }}", + "totalPages": "{{ Math.ceil($steps.fetch_total.output / $steps.extract_params.output.limit) }}" + } + }, + "operation": "transform_data" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.format_response.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "List forum threads in a category with pagination and sorting" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/irc_webchat/workflow/handle-command.backup.jsonscript b/packages/irc_webchat/workflow/handle-command.backup.jsonscript new file mode 100644 index 000000000..925908870 --- /dev/null +++ b/packages/irc_webchat/workflow/handle-command.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"Handle IRC Commands","description":"Process IRC commands (/help, /users, /me, /clear, /kick, /ban)","trigger":{"type":"http","method":"POST","path":"/irc/channels/:channelId/command"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"parse_command","type":"operation","op":"transform_data","output":{"command":"{{ $json.message.split(' ')[0].substring(1).toLowerCase() }}","args":"{{ $json.message.split(' ').slice(1) }}"}},{"id":"handle_help","type":"operation","op":"condition","condition":"{{ $steps.parse_command.output.command === 'help' }}"},{"id":"handle_users","type":"operation","op":"condition","condition":"{{ $steps.parse_command.output.command === 'users' }}"},{"id":"handle_me","type":"operation","op":"condition","condition":"{{ $steps.parse_command.output.command === 'me' }}"},{"id":"handle_kick","type":"operation","op":"condition","condition":"{{ $steps.parse_command.output.command === 'kick' && $context.user.level >= 2 }}"},{"id":"handle_ban","type":"operation","op":"condition","condition":"{{ $steps.parse_command.output.command === 'ban' && $context.user.level >= 3 }}"}] +} diff --git a/packages/irc_webchat/workflow/handle-command.jsonscript b/packages/irc_webchat/workflow/handle-command.jsonscript index 925908870..ec4c9f988 100644 --- a/packages/irc_webchat/workflow/handle-command.jsonscript +++ b/packages/irc_webchat/workflow/handle-command.jsonscript @@ -1,3 +1,120 @@ { - "version":"2.2.0","name":"Handle IRC Commands","description":"Process IRC commands (/help, /users, /me, /clear, /kick, /ban)","trigger":{"type":"http","method":"POST","path":"/irc/channels/:channelId/command"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"parse_command","type":"operation","op":"transform_data","output":{"command":"{{ $json.message.split(' ')[0].substring(1).toLowerCase() }}","args":"{{ $json.message.split(' ').slice(1) }}"}},{"id":"handle_help","type":"operation","op":"condition","condition":"{{ $steps.parse_command.output.command === 'help' }}"},{"id":"handle_users","type":"operation","op":"condition","condition":"{{ $steps.parse_command.output.command === 'users' }}"},{"id":"handle_me","type":"operation","op":"condition","condition":"{{ $steps.parse_command.output.command === 'me' }}"},{"id":"handle_kick","type":"operation","op":"condition","condition":"{{ $steps.parse_command.output.command === 'kick' && $context.user.level >= 2 }}"},{"id":"handle_ban","type":"operation","op":"condition","condition":"{{ $steps.parse_command.output.command === 'ban' && $context.user.level >= 3 }}"}] + "name": "Handle IRC Commands", + "active": false, + "nodes": [ + { + "id": "validate_context", + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } + }, + { + "id": "parse_command", + "name": "Parse Command", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "output": { + "command": "{{ $json.message.split(' ')[0].substring(1).toLowerCase() }}", + "args": "{{ $json.message.split(' ').slice(1) }}" + }, + "operation": "transform_data" + } + }, + { + "id": "handle_help", + "name": "Handle Help", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "condition": "{{ $steps.parse_command.output.command === 'help' }}", + "operation": "condition" + } + }, + { + "id": "handle_users", + "name": "Handle Users", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "condition": "{{ $steps.parse_command.output.command === 'users' }}", + "operation": "condition" + } + }, + { + "id": "handle_me", + "name": "Handle Me", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "condition": "{{ $steps.parse_command.output.command === 'me' }}", + "operation": "condition" + } + }, + { + "id": "handle_kick", + "name": "Handle Kick", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "condition": "{{ $steps.parse_command.output.command === 'kick' && $context.user.level >= 2 }}", + "operation": "condition" + } + }, + { + "id": "handle_ban", + "name": "Handle Ban", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "condition": "{{ $steps.parse_command.output.command === 'ban' && $context.user.level >= 3 }}", + "operation": "condition" + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Process IRC commands (/help, /users, /me, /clear, /kick, /ban)" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/irc_webchat/workflow/join-channel.backup.jsonscript b/packages/irc_webchat/workflow/join-channel.backup.jsonscript new file mode 100644 index 000000000..3f48e2626 --- /dev/null +++ b/packages/irc_webchat/workflow/join-channel.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"Join IRC Channel","description":"Add user to IRC channel with membership tracking","trigger":{"type":"http","method":"POST","path":"/irc/channels/:channelId/join"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"fetch_channel","type":"operation","op":"database_read","entity":"IRCChannel","params":{"filter":{"id":"{{ $json.channelId }}","tenantId":"{{ $context.tenantId }}"}}},{"id":"check_channel_mode","type":"operation","op":"condition","condition":"{{ $steps.fetch_channel.output.mode === 'public' || ($context.user.level >= 2 && $steps.fetch_channel.output.mode === 'private') }}"},{"id":"create_membership","type":"operation","op":"database_create","entity":"IRCMembership","data":{"channelId":"{{ $json.channelId }}","userId":"{{ $context.user.id }}","joinedAt":"{{ new Date().toISOString() }}"}},{"id":"emit_join","type":"action","action":"emit_event","event":"user_joined","channel":"{{ 'irc:' + $json.channelId }}","data":{"userId":"{{ $context.user.id }}","channelId":"{{ $json.channelId }}"}}] +} diff --git a/packages/irc_webchat/workflow/join-channel.jsonscript b/packages/irc_webchat/workflow/join-channel.jsonscript index 3f48e2626..02befe40b 100644 --- a/packages/irc_webchat/workflow/join-channel.jsonscript +++ b/packages/irc_webchat/workflow/join-channel.jsonscript @@ -1,3 +1,103 @@ { - "version":"2.2.0","name":"Join IRC Channel","description":"Add user to IRC channel with membership tracking","trigger":{"type":"http","method":"POST","path":"/irc/channels/:channelId/join"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"fetch_channel","type":"operation","op":"database_read","entity":"IRCChannel","params":{"filter":{"id":"{{ $json.channelId }}","tenantId":"{{ $context.tenantId }}"}}},{"id":"check_channel_mode","type":"operation","op":"condition","condition":"{{ $steps.fetch_channel.output.mode === 'public' || ($context.user.level >= 2 && $steps.fetch_channel.output.mode === 'private') }}"},{"id":"create_membership","type":"operation","op":"database_create","entity":"IRCMembership","data":{"channelId":"{{ $json.channelId }}","userId":"{{ $context.user.id }}","joinedAt":"{{ new Date().toISOString() }}"}},{"id":"emit_join","type":"action","action":"emit_event","event":"user_joined","channel":"{{ 'irc:' + $json.channelId }}","data":{"userId":"{{ $context.user.id }}","channelId":"{{ $json.channelId }}"}}] + "name": "Join IRC Channel", + "active": false, + "nodes": [ + { + "id": "validate_context", + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } + }, + { + "id": "fetch_channel", + "name": "Fetch Channel", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "filter": { + "id": "{{ $json.channelId }}", + "tenantId": "{{ $context.tenantId }}" + }, + "operation": "database_read", + "entity": "IRCChannel" + } + }, + { + "id": "check_channel_mode", + "name": "Check Channel Mode", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "condition": "{{ $steps.fetch_channel.output.mode === 'public' || ($context.user.level >= 2 && $steps.fetch_channel.output.mode === 'private') }}", + "operation": "condition" + } + }, + { + "id": "create_membership", + "name": "Create Membership", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "data": { + "channelId": "{{ $json.channelId }}", + "userId": "{{ $context.user.id }}", + "joinedAt": "{{ new Date().toISOString() }}" + }, + "operation": "database_create", + "entity": "IRCMembership" + } + }, + { + "id": "emit_join", + "name": "Emit Join", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "data": { + "userId": "{{ $context.user.id }}", + "channelId": "{{ $json.channelId }}" + }, + "action": "emit_event", + "event": "user_joined", + "channel": "{{ 'irc:' + $json.channelId }}" + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Add user to IRC channel with membership tracking" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/irc_webchat/workflow/list-channels.backup.jsonscript b/packages/irc_webchat/workflow/list-channels.backup.jsonscript new file mode 100644 index 000000000..103f5dfd1 --- /dev/null +++ b/packages/irc_webchat/workflow/list-channels.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"List IRC Channels","description":"List IRC channels with mode filtering (public/private/secret)","trigger":{"type":"http","method":"GET","path":"/irc/channels"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.tenantId }}","validator":"required"},{"id":"extract_params","type":"operation","op":"transform_data","output":{"includePrivate":"{{ $context.user.level >= 2 }}","includeSecret":"{{ $context.user.level >= 3 }}"}},{"id":"build_filter","type":"operation","op":"transform_data","output":{"tenantId":"{{ $context.tenantId }}","mode":{"$in":"{{ [$steps.extract_params.output.includeSecret ? 'secret' : null, $steps.extract_params.output.includePrivate ? 'private' : null, 'public'].filter(x => x) }}"}}},{"id":"fetch_channels","type":"operation","op":"database_read","entity":"IRCChannel","params":{"filter":"{{ $steps.build_filter.output }}","sort":{"createdAt":-1}}},{"id":"return_success","type":"action","action":"http_response","status":200,"body":{"channels":"{{ $steps.fetch_channels.output }}"}}] +} diff --git a/packages/irc_webchat/workflow/list-channels.jsonscript b/packages/irc_webchat/workflow/list-channels.jsonscript index 103f5dfd1..8e6254d99 100644 --- a/packages/irc_webchat/workflow/list-channels.jsonscript +++ b/packages/irc_webchat/workflow/list-channels.jsonscript @@ -1,3 +1,104 @@ { - "version":"2.2.0","name":"List IRC Channels","description":"List IRC channels with mode filtering (public/private/secret)","trigger":{"type":"http","method":"GET","path":"/irc/channels"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.tenantId }}","validator":"required"},{"id":"extract_params","type":"operation","op":"transform_data","output":{"includePrivate":"{{ $context.user.level >= 2 }}","includeSecret":"{{ $context.user.level >= 3 }}"}},{"id":"build_filter","type":"operation","op":"transform_data","output":{"tenantId":"{{ $context.tenantId }}","mode":{"$in":"{{ [$steps.extract_params.output.includeSecret ? 'secret' : null, $steps.extract_params.output.includePrivate ? 'private' : null, 'public'].filter(x => x) }}"}}},{"id":"fetch_channels","type":"operation","op":"database_read","entity":"IRCChannel","params":{"filter":"{{ $steps.build_filter.output }}","sort":{"createdAt":-1}}},{"id":"return_success","type":"action","action":"http_response","status":200,"body":{"channels":"{{ $steps.fetch_channels.output }}"}}] + "name": "List IRC Channels", + "active": false, + "nodes": [ + { + "id": "validate_context", + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" + } + }, + { + "id": "extract_params", + "name": "Extract Params", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "output": { + "includePrivate": "{{ $context.user.level >= 2 }}", + "includeSecret": "{{ $context.user.level >= 3 }}" + }, + "operation": "transform_data" + } + }, + { + "id": "build_filter", + "name": "Build Filter", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "output": { + "tenantId": "{{ $context.tenantId }}", + "mode": { + "$in": "{{ [$steps.extract_params.output.includeSecret ? 'secret' : null, $steps.extract_params.output.includePrivate ? 'private' : null, 'public'].filter(x => x) }}" + } + }, + "operation": "transform_data" + } + }, + { + "id": "fetch_channels", + "name": "Fetch Channels", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "filter": "{{ $steps.build_filter.output }}", + "sort": { + "createdAt": -1 + }, + "operation": "database_read", + "entity": "IRCChannel" + } + }, + { + "id": "return_success", + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": { + "channels": "{{ $steps.fetch_channels.output }}" + } + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "List IRC channels with mode filtering (public/private/secret)" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/irc_webchat/workflow/send-message.backup.jsonscript b/packages/irc_webchat/workflow/send-message.backup.jsonscript new file mode 100644 index 000000000..5dfd77917 --- /dev/null +++ b/packages/irc_webchat/workflow/send-message.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"Send IRC Message","description":"Send message to IRC channel with slowmode rate limiting","trigger":{"type":"http","method":"POST","path":"/irc/channels/:channelId/messages"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"apply_slowmode","type":"operation","op":"rate_limit","key":"{{ 'irc:' + $context.user.id + ':' + $json.channelId }}","limit":1,"window":2000},{"id":"validate_input","type":"operation","op":"validate","input":"{{ $json }}","rules":{"message":"required|string|minLength:1|maxLength:500"}},{"id":"create_message","type":"operation","op":"database_create","entity":"IRCMessage","data":{"channelId":"{{ $json.channelId }}","userId":"{{ $context.user.id }}","tenantId":"{{ $context.tenantId }}","message":"{{ $json.message }}","createdAt":"{{ new Date().toISOString() }}"}},{"id":"emit_message","type":"action","action":"emit_event","event":"message_sent","channel":"{{ 'irc:' + $json.channelId }}","data":{"messageId":"{{ $steps.create_message.output.id }}","userId":"{{ $context.user.id }}","message":"{{ $json.message }}"}}] +} diff --git a/packages/irc_webchat/workflow/send-message.jsonscript b/packages/irc_webchat/workflow/send-message.jsonscript index 5dfd77917..05c066d0a 100644 --- a/packages/irc_webchat/workflow/send-message.jsonscript +++ b/packages/irc_webchat/workflow/send-message.jsonscript @@ -1,3 +1,107 @@ { - "version":"2.2.0","name":"Send IRC Message","description":"Send message to IRC channel with slowmode rate limiting","trigger":{"type":"http","method":"POST","path":"/irc/channels/:channelId/messages"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"apply_slowmode","type":"operation","op":"rate_limit","key":"{{ 'irc:' + $context.user.id + ':' + $json.channelId }}","limit":1,"window":2000},{"id":"validate_input","type":"operation","op":"validate","input":"{{ $json }}","rules":{"message":"required|string|minLength:1|maxLength:500"}},{"id":"create_message","type":"operation","op":"database_create","entity":"IRCMessage","data":{"channelId":"{{ $json.channelId }}","userId":"{{ $context.user.id }}","tenantId":"{{ $context.tenantId }}","message":"{{ $json.message }}","createdAt":"{{ new Date().toISOString() }}"}},{"id":"emit_message","type":"action","action":"emit_event","event":"message_sent","channel":"{{ 'irc:' + $json.channelId }}","data":{"messageId":"{{ $steps.create_message.output.id }}","userId":"{{ $context.user.id }}","message":"{{ $json.message }}"}}] + "name": "Send IRC Message", + "active": false, + "nodes": [ + { + "id": "validate_context", + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } + }, + { + "id": "apply_slowmode", + "name": "Apply Slowmode", + "type": "metabuilder.rateLimit", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "operation": "rate_limit", + "key": "{{ 'irc:' + $context.user.id + ':' + $json.channelId }}", + "limit": 1, + "window": 2000 + } + }, + { + "id": "validate_input", + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "message": "required|string|minLength:1|maxLength:500" + } + } + }, + { + "id": "create_message", + "name": "Create Message", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "data": { + "channelId": "{{ $json.channelId }}", + "userId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}", + "message": "{{ $json.message }}", + "createdAt": "{{ new Date().toISOString() }}" + }, + "operation": "database_create", + "entity": "IRCMessage" + } + }, + { + "id": "emit_message", + "name": "Emit Message", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "data": { + "messageId": "{{ $steps.create_message.output.id }}", + "userId": "{{ $context.user.id }}", + "message": "{{ $json.message }}" + }, + "action": "emit_event", + "event": "message_sent", + "channel": "{{ 'irc:' + $json.channelId }}" + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Send message to IRC channel with slowmode rate limiting" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/media_center/workflow/delete-media.backup.jsonscript b/packages/media_center/workflow/delete-media.backup.jsonscript new file mode 100644 index 000000000..898eecb3a --- /dev/null +++ b/packages/media_center/workflow/delete-media.backup.jsonscript @@ -0,0 +1,78 @@ +{ + "version": "2.2.0", + "name": "Delete Media Asset", + "description": "Delete media asset with authorization and file cleanup", + "trigger": { + "type": "http", + "method": "DELETE", + "path": "/media/assets/:assetId" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required" + }, + { + "id": "fetch_asset", + "type": "operation", + "op": "database_read", + "entity": "MediaAsset", + "params": { + "filter": { + "id": "{{ $json.assetId }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "check_authorization", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.fetch_asset.output.uploadedBy === $context.user.id || $context.user.level >= 3 }}" + }, + { + "id": "delete_files", + "type": "operation", + "op": "file_operation", + "operation": "delete_recursive", + "paths": [ + "{{ $steps.fetch_asset.output.path }}", + "{{ $steps.fetch_asset.output.path }}-thumbnail }}", + "{{ $steps.fetch_asset.output.path }}-optimized }}" + ] + }, + { + "id": "delete_asset_record", + "type": "operation", + "op": "database_delete", + "entity": "MediaAsset", + "params": { + "filter": { + "id": "{{ $json.assetId }}" + } + } + }, + { + "id": "emit_deleted", + "type": "action", + "action": "emit_event", + "event": "media_deleted", + "channel": "{{ 'media:' + $context.tenantId }}", + "data": { + "assetId": "{{ $json.assetId }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": { + "message": "Media asset deleted successfully" + } + } + ] +} diff --git a/packages/media_center/workflow/delete-media.jsonscript b/packages/media_center/workflow/delete-media.jsonscript index 898eecb3a..ee2723a0a 100644 --- a/packages/media_center/workflow/delete-media.jsonscript +++ b/packages/media_center/workflow/delete-media.jsonscript @@ -1,78 +1,135 @@ { - "version": "2.2.0", "name": "Delete Media Asset", - "description": "Delete media asset with authorization and file cleanup", - "trigger": { - "type": "http", - "method": "DELETE", - "path": "/media/assets/:assetId" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" + } }, { "id": "fetch_asset", - "type": "operation", - "op": "database_read", - "entity": "MediaAsset", - "params": { + "name": "Fetch Asset", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { "filter": { "id": "{{ $json.assetId }}", "tenantId": "{{ $context.tenantId }}" - } + }, + "operation": "database_read", + "entity": "MediaAsset" } }, { "id": "check_authorization", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.fetch_asset.output.uploadedBy === $context.user.id || $context.user.level >= 3 }}" + "name": "Check Authorization", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "condition": "{{ $steps.fetch_asset.output.uploadedBy === $context.user.id || $context.user.level >= 3 }}", + "operation": "condition" + } }, { "id": "delete_files", - "type": "operation", - "op": "file_operation", - "operation": "delete_recursive", - "paths": [ - "{{ $steps.fetch_asset.output.path }}", - "{{ $steps.fetch_asset.output.path }}-thumbnail }}", - "{{ $steps.fetch_asset.output.path }}-optimized }}" - ] + "name": "Delete Files", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "operation": "delete_recursive", + "paths": [ + "{{ $steps.fetch_asset.output.path }}", + "{{ $steps.fetch_asset.output.path }}-thumbnail }}", + "{{ $steps.fetch_asset.output.path }}-optimized }}" + ] + } }, { "id": "delete_asset_record", - "type": "operation", - "op": "database_delete", - "entity": "MediaAsset", - "params": { + "name": "Delete Asset Record", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { "filter": { "id": "{{ $json.assetId }}" - } + }, + "operation": "database_delete", + "entity": "MediaAsset" } }, { "id": "emit_deleted", - "type": "action", - "action": "emit_event", - "event": "media_deleted", - "channel": "{{ 'media:' + $context.tenantId }}", - "data": { - "assetId": "{{ $json.assetId }}" + "name": "Emit Deleted", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "data": { + "assetId": "{{ $json.assetId }}" + }, + "action": "emit_event", + "event": "media_deleted", + "channel": "{{ 'media:' + $context.tenantId }}" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": { - "message": "Media asset deleted successfully" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": { + "message": "Media asset deleted successfully" + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Delete media asset with authorization and file cleanup" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/media_center/workflow/extract-image-metadata.backup.jsonscript b/packages/media_center/workflow/extract-image-metadata.backup.jsonscript new file mode 100644 index 000000000..ee47a1a26 --- /dev/null +++ b/packages/media_center/workflow/extract-image-metadata.backup.jsonscript @@ -0,0 +1,106 @@ +{ + "version": "2.2.0", + "name": "Extract Image Metadata", + "description": "Extract metadata (dimensions, format, EXIF) from uploaded images", + "trigger": { + "type": "http", + "method": "POST", + "path": "/media/extract/image-metadata" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required" + }, + { + "id": "validate_input", + "type": "operation", + "op": "validate", + "input": "{{ $json }}", + "rules": { + "assetId": "required|string", + "filePath": "required|string" + } + }, + { + "id": "fetch_asset", + "type": "operation", + "op": "database_read", + "entity": "MediaAsset", + "params": { + "filter": { + "id": "{{ $json.assetId }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "extract_image_info", + "type": "operation", + "op": "file_operation", + "operation": "analyze_image", + "filePath": "{{ $json.filePath }}", + "output": { + "width": true, + "height": true, + "format": true, + "colorSpace": true, + "hasAlpha": true, + "exif": true + } + }, + { + "id": "calculate_dimensions", + "type": "operation", + "op": "transform_data", + "output": { + "width": "{{ $steps.extract_image_info.output.width }}", + "height": "{{ $steps.extract_image_info.output.height }}", + "aspectRatio": "{{ $steps.extract_image_info.output.width / $steps.extract_image_info.output.height }}", + "format": "{{ $steps.extract_image_info.output.format }}" + } + }, + { + "id": "update_asset_metadata", + "type": "operation", + "op": "database_update", + "entity": "MediaAsset", + "params": { + "filter": { + "id": "{{ $json.assetId }}" + }, + "data": { + "metadata": { + "dimensions": "{{ $steps.calculate_dimensions.output }}", + "format": "{{ $steps.extract_image_info.output.format }}", + "colorSpace": "{{ $steps.extract_image_info.output.colorSpace }}", + "hasAlpha": "{{ $steps.extract_image_info.output.hasAlpha }}", + "exif": "{{ $steps.extract_image_info.output.exif }}" + }, + "extractedAt": "{{ new Date().toISOString() }}" + } + } + }, + { + "id": "emit_complete", + "type": "action", + "action": "emit_event", + "event": "image_metadata_extracted", + "channel": "{{ 'media:' + $context.tenantId }}", + "data": { + "assetId": "{{ $json.assetId }}", + "metadata": "{{ $steps.calculate_dimensions.output }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.update_asset_metadata.output }}" + } + ] +} diff --git a/packages/media_center/workflow/extract-image-metadata.jsonscript b/packages/media_center/workflow/extract-image-metadata.jsonscript index ee47a1a26..4824a2a91 100644 --- a/packages/media_center/workflow/extract-image-metadata.jsonscript +++ b/packages/media_center/workflow/extract-image-metadata.jsonscript @@ -1,74 +1,109 @@ { - "version": "2.2.0", "name": "Extract Image Metadata", - "description": "Extract metadata (dimensions, format, EXIF) from uploaded images", - "trigger": { - "type": "http", - "method": "POST", - "path": "/media/extract/image-metadata" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required" - }, - { - "id": "validate_input", - "type": "operation", - "op": "validate", - "input": "{{ $json }}", - "rules": { - "assetId": "required|string", - "filePath": "required|string" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" } }, { - "id": "fetch_asset", - "type": "operation", - "op": "database_read", - "entity": "MediaAsset", - "params": { - "filter": { - "id": "{{ $json.assetId }}", - "tenantId": "{{ $context.tenantId }}" + "id": "validate_input", + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "assetId": "required|string", + "filePath": "required|string" } } }, + { + "id": "fetch_asset", + "name": "Fetch Asset", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "filter": { + "id": "{{ $json.assetId }}", + "tenantId": "{{ $context.tenantId }}" + }, + "operation": "database_read", + "entity": "MediaAsset" + } + }, { "id": "extract_image_info", - "type": "operation", - "op": "file_operation", - "operation": "analyze_image", - "filePath": "{{ $json.filePath }}", - "output": { - "width": true, - "height": true, - "format": true, - "colorSpace": true, - "hasAlpha": true, - "exif": true + "name": "Extract Image Info", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "output": { + "width": true, + "height": true, + "format": true, + "colorSpace": true, + "hasAlpha": true, + "exif": true + }, + "operation": "analyze_image", + "filePath": "{{ $json.filePath }}" } }, { "id": "calculate_dimensions", - "type": "operation", - "op": "transform_data", - "output": { - "width": "{{ $steps.extract_image_info.output.width }}", - "height": "{{ $steps.extract_image_info.output.height }}", - "aspectRatio": "{{ $steps.extract_image_info.output.width / $steps.extract_image_info.output.height }}", - "format": "{{ $steps.extract_image_info.output.format }}" + "name": "Calculate Dimensions", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "output": { + "width": "{{ $steps.extract_image_info.output.width }}", + "height": "{{ $steps.extract_image_info.output.height }}", + "aspectRatio": "{{ $steps.extract_image_info.output.width / $steps.extract_image_info.output.height }}", + "format": "{{ $steps.extract_image_info.output.format }}" + }, + "operation": "transform_data" } }, { "id": "update_asset_metadata", - "type": "operation", - "op": "database_update", - "entity": "MediaAsset", - "params": { + "name": "Update Asset Metadata", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { "filter": { "id": "{{ $json.assetId }}" }, @@ -81,26 +116,56 @@ "exif": "{{ $steps.extract_image_info.output.exif }}" }, "extractedAt": "{{ new Date().toISOString() }}" - } + }, + "operation": "database_update", + "entity": "MediaAsset" } }, { "id": "emit_complete", - "type": "action", - "action": "emit_event", - "event": "image_metadata_extracted", - "channel": "{{ 'media:' + $context.tenantId }}", - "data": { - "assetId": "{{ $json.assetId }}", - "metadata": "{{ $steps.calculate_dimensions.output }}" + "name": "Emit Complete", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "data": { + "assetId": "{{ $json.assetId }}", + "metadata": "{{ $steps.calculate_dimensions.output }}" + }, + "action": "emit_event", + "event": "image_metadata_extracted", + "channel": "{{ 'media:' + $context.tenantId }}" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.update_asset_metadata.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.update_asset_metadata.output }}" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Extract metadata (dimensions, format, EXIF) from uploaded images" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/media_center/workflow/extract-video-metadata.backup.jsonscript b/packages/media_center/workflow/extract-video-metadata.backup.jsonscript new file mode 100644 index 000000000..61742ba4d --- /dev/null +++ b/packages/media_center/workflow/extract-video-metadata.backup.jsonscript @@ -0,0 +1,111 @@ +{ + "version": "2.2.0", + "name": "Extract Video Metadata", + "description": "Extract metadata (duration, codec, bitrate) from uploaded videos", + "trigger": { + "type": "http", + "method": "POST", + "path": "/media/extract/video-metadata" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required" + }, + { + "id": "validate_input", + "type": "operation", + "op": "validate", + "input": "{{ $json }}", + "rules": { + "assetId": "required|string", + "filePath": "required|string" + } + }, + { + "id": "fetch_asset", + "type": "operation", + "op": "database_read", + "entity": "MediaAsset", + "params": { + "filter": { + "id": "{{ $json.assetId }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "extract_video_info", + "type": "operation", + "op": "file_operation", + "operation": "analyze_video", + "filePath": "{{ $json.filePath }}", + "output": { + "duration": true, + "bitrate": true, + "codec": true, + "videoCodec": true, + "audioCodec": true, + "width": true, + "height": true, + "fps": true + } + }, + { + "id": "format_duration", + "type": "operation", + "op": "transform_data", + "output": { + "seconds": "{{ $steps.extract_video_info.output.duration }}", + "formatted": "{{ Math.floor($steps.extract_video_info.output.duration / 3600) }}:{{ Math.floor(($steps.extract_video_info.output.duration % 3600) / 60).toString().padStart(2, '0') }}:{{ ($steps.extract_video_info.output.duration % 60).toString().padStart(2, '0') }}" + } + }, + { + "id": "update_asset_metadata", + "type": "operation", + "op": "database_update", + "entity": "MediaAsset", + "params": { + "filter": { + "id": "{{ $json.assetId }}" + }, + "data": { + "metadata": { + "duration": "{{ $steps.format_duration.output }}", + "bitrate": "{{ $steps.extract_video_info.output.bitrate }}", + "codec": "{{ $steps.extract_video_info.output.codec }}", + "videoCodec": "{{ $steps.extract_video_info.output.videoCodec }}", + "audioCodec": "{{ $steps.extract_video_info.output.audioCodec }}", + "resolution": { + "width": "{{ $steps.extract_video_info.output.width }}", + "height": "{{ $steps.extract_video_info.output.height }}" + }, + "fps": "{{ $steps.extract_video_info.output.fps }}" + }, + "extractedAt": "{{ new Date().toISOString() }}" + } + } + }, + { + "id": "emit_complete", + "type": "action", + "action": "emit_event", + "event": "video_metadata_extracted", + "channel": "{{ 'media:' + $context.tenantId }}", + "data": { + "assetId": "{{ $json.assetId }}", + "duration": "{{ $steps.format_duration.output.formatted }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.update_asset_metadata.output }}" + } + ] +} diff --git a/packages/media_center/workflow/extract-video-metadata.jsonscript b/packages/media_center/workflow/extract-video-metadata.jsonscript index 61742ba4d..c9e9ff679 100644 --- a/packages/media_center/workflow/extract-video-metadata.jsonscript +++ b/packages/media_center/workflow/extract-video-metadata.jsonscript @@ -1,74 +1,109 @@ { - "version": "2.2.0", "name": "Extract Video Metadata", - "description": "Extract metadata (duration, codec, bitrate) from uploaded videos", - "trigger": { - "type": "http", - "method": "POST", - "path": "/media/extract/video-metadata" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required" - }, - { - "id": "validate_input", - "type": "operation", - "op": "validate", - "input": "{{ $json }}", - "rules": { - "assetId": "required|string", - "filePath": "required|string" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" } }, { - "id": "fetch_asset", - "type": "operation", - "op": "database_read", - "entity": "MediaAsset", - "params": { - "filter": { - "id": "{{ $json.assetId }}", - "tenantId": "{{ $context.tenantId }}" + "id": "validate_input", + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "assetId": "required|string", + "filePath": "required|string" } } }, + { + "id": "fetch_asset", + "name": "Fetch Asset", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "filter": { + "id": "{{ $json.assetId }}", + "tenantId": "{{ $context.tenantId }}" + }, + "operation": "database_read", + "entity": "MediaAsset" + } + }, { "id": "extract_video_info", - "type": "operation", - "op": "file_operation", - "operation": "analyze_video", - "filePath": "{{ $json.filePath }}", - "output": { - "duration": true, - "bitrate": true, - "codec": true, - "videoCodec": true, - "audioCodec": true, - "width": true, - "height": true, - "fps": true + "name": "Extract Video Info", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "output": { + "duration": true, + "bitrate": true, + "codec": true, + "videoCodec": true, + "audioCodec": true, + "width": true, + "height": true, + "fps": true + }, + "operation": "analyze_video", + "filePath": "{{ $json.filePath }}" } }, { "id": "format_duration", - "type": "operation", - "op": "transform_data", - "output": { - "seconds": "{{ $steps.extract_video_info.output.duration }}", - "formatted": "{{ Math.floor($steps.extract_video_info.output.duration / 3600) }}:{{ Math.floor(($steps.extract_video_info.output.duration % 3600) / 60).toString().padStart(2, '0') }}:{{ ($steps.extract_video_info.output.duration % 60).toString().padStart(2, '0') }}" + "name": "Format Duration", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "output": { + "seconds": "{{ $steps.extract_video_info.output.duration }}", + "formatted": "{{ Math.floor($steps.extract_video_info.output.duration / 3600) }}:{{ Math.floor(($steps.extract_video_info.output.duration % 3600) / 60).toString().padStart(2, '0') }}:{{ ($steps.extract_video_info.output.duration % 60).toString().padStart(2, '0') }}" + }, + "operation": "transform_data" } }, { "id": "update_asset_metadata", - "type": "operation", - "op": "database_update", - "entity": "MediaAsset", - "params": { + "name": "Update Asset Metadata", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { "filter": { "id": "{{ $json.assetId }}" }, @@ -86,26 +121,56 @@ "fps": "{{ $steps.extract_video_info.output.fps }}" }, "extractedAt": "{{ new Date().toISOString() }}" - } + }, + "operation": "database_update", + "entity": "MediaAsset" } }, { "id": "emit_complete", - "type": "action", - "action": "emit_event", - "event": "video_metadata_extracted", - "channel": "{{ 'media:' + $context.tenantId }}", - "data": { - "assetId": "{{ $json.assetId }}", - "duration": "{{ $steps.format_duration.output.formatted }}" + "name": "Emit Complete", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "data": { + "assetId": "{{ $json.assetId }}", + "duration": "{{ $steps.format_duration.output.formatted }}" + }, + "action": "emit_event", + "event": "video_metadata_extracted", + "channel": "{{ 'media:' + $context.tenantId }}" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.update_asset_metadata.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.update_asset_metadata.output }}" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Extract metadata (duration, codec, bitrate) from uploaded videos" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/media_center/workflow/list-user-media.backup.jsonscript b/packages/media_center/workflow/list-user-media.backup.jsonscript new file mode 100644 index 000000000..947b24a72 --- /dev/null +++ b/packages/media_center/workflow/list-user-media.backup.jsonscript @@ -0,0 +1,98 @@ +{ + "version": "2.2.0", + "name": "List User Media", + "description": "List all media assets for current user with filtering and sorting", + "trigger": { + "type": "http", + "method": "GET", + "path": "/media/my-assets" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required" + }, + { + "id": "validate_user", + "type": "operation", + "op": "validate", + "input": "{{ $context.user.id }}", + "validator": "required" + }, + { + "id": "extract_params", + "type": "operation", + "op": "transform_data", + "output": { + "type": "{{ $json.type || null }}", + "sortBy": "{{ $json.sortBy || 'createdAt' }}", + "sortOrder": "{{ $json.sortOrder || 'desc' }}", + "limit": "{{ Math.min($json.limit || 50, 500) }}", + "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 50) }}" + } + }, + { + "id": "build_filter", + "type": "operation", + "op": "transform_data", + "output": { + "tenantId": "{{ $context.tenantId }}", + "uploadedBy": "{{ $context.user.id }}", + "type": "{{ $steps.extract_params.output.type }}" + } + }, + { + "id": "clean_filter", + "type": "operation", + "op": "transform_data", + "output": "{{ Object.entries($steps.build_filter.output).reduce((acc, [key, value]) => { if (value !== null && value !== undefined) acc[key] = value; return acc; }, {}) }}" + }, + { + "id": "fetch_media", + "type": "operation", + "op": "database_read", + "entity": "MediaAsset", + "params": { + "filter": "{{ $steps.clean_filter.output }}", + "sort": { + "{{ $steps.extract_params.output.sortBy }}": "{{ $steps.extract_params.output.sortOrder === 'asc' ? 1 : -1 }}" + }, + "limit": "{{ $steps.extract_params.output.limit }}", + "offset": "{{ $steps.extract_params.output.offset }}" + } + }, + { + "id": "count_total", + "type": "operation", + "op": "database_count", + "entity": "MediaAsset", + "params": { + "filter": "{{ $steps.clean_filter.output }}" + } + }, + { + "id": "format_response", + "type": "operation", + "op": "transform_data", + "output": { + "assets": "{{ $steps.fetch_media.output }}", + "pagination": { + "total": "{{ $steps.count_total.output }}", + "page": "{{ $json.page || 1 }}", + "limit": "{{ $steps.extract_params.output.limit }}", + "hasMore": "{{ $steps.count_total.output > ($steps.extract_params.output.offset + $steps.extract_params.output.limit) }}" + } + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } + ] +} diff --git a/packages/media_center/workflow/list-user-media.jsonscript b/packages/media_center/workflow/list-user-media.jsonscript index 947b24a72..2d3535717 100644 --- a/packages/media_center/workflow/list-user-media.jsonscript +++ b/packages/media_center/workflow/list-user-media.jsonscript @@ -1,98 +1,172 @@ { - "version": "2.2.0", "name": "List User Media", - "description": "List all media assets for current user with filtering and sorting", - "trigger": { - "type": "http", - "method": "GET", - "path": "/media/my-assets" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" + } }, { "id": "validate_user", - "type": "operation", - "op": "validate", - "input": "{{ $context.user.id }}", - "validator": "required" + "name": "Validate User", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } }, { "id": "extract_params", - "type": "operation", - "op": "transform_data", - "output": { - "type": "{{ $json.type || null }}", - "sortBy": "{{ $json.sortBy || 'createdAt' }}", - "sortOrder": "{{ $json.sortOrder || 'desc' }}", - "limit": "{{ Math.min($json.limit || 50, 500) }}", - "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 50) }}" + "name": "Extract Params", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "output": { + "type": "{{ $json.type || null }}", + "sortBy": "{{ $json.sortBy || 'createdAt' }}", + "sortOrder": "{{ $json.sortOrder || 'desc' }}", + "limit": "{{ Math.min($json.limit || 50, 500) }}", + "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 50) }}" + }, + "operation": "transform_data" } }, { "id": "build_filter", - "type": "operation", - "op": "transform_data", - "output": { - "tenantId": "{{ $context.tenantId }}", - "uploadedBy": "{{ $context.user.id }}", - "type": "{{ $steps.extract_params.output.type }}" + "name": "Build Filter", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "output": { + "tenantId": "{{ $context.tenantId }}", + "uploadedBy": "{{ $context.user.id }}", + "type": "{{ $steps.extract_params.output.type }}" + }, + "operation": "transform_data" } }, { "id": "clean_filter", - "type": "operation", - "op": "transform_data", - "output": "{{ Object.entries($steps.build_filter.output).reduce((acc, [key, value]) => { if (value !== null && value !== undefined) acc[key] = value; return acc; }, {}) }}" + "name": "Clean Filter", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "output": "{{ Object.entries($steps.build_filter.output).reduce((acc, [key, value]) => { if (value !== null && value !== undefined) acc[key] = value; return acc; }, {}) }}", + "operation": "transform_data" + } }, { "id": "fetch_media", - "type": "operation", - "op": "database_read", - "entity": "MediaAsset", - "params": { + "name": "Fetch Media", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { "filter": "{{ $steps.clean_filter.output }}", "sort": { "{{ $steps.extract_params.output.sortBy }}": "{{ $steps.extract_params.output.sortOrder === 'asc' ? 1 : -1 }}" }, "limit": "{{ $steps.extract_params.output.limit }}", - "offset": "{{ $steps.extract_params.output.offset }}" + "offset": "{{ $steps.extract_params.output.offset }}", + "operation": "database_read", + "entity": "MediaAsset" } }, { "id": "count_total", - "type": "operation", - "op": "database_count", - "entity": "MediaAsset", - "params": { - "filter": "{{ $steps.clean_filter.output }}" + "name": "Count Total", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "filter": "{{ $steps.clean_filter.output }}", + "operation": "database_count", + "entity": "MediaAsset" } }, { "id": "format_response", - "type": "operation", - "op": "transform_data", - "output": { - "assets": "{{ $steps.fetch_media.output }}", - "pagination": { - "total": "{{ $steps.count_total.output }}", - "page": "{{ $json.page || 1 }}", - "limit": "{{ $steps.extract_params.output.limit }}", - "hasMore": "{{ $steps.count_total.output > ($steps.extract_params.output.offset + $steps.extract_params.output.limit) }}" - } + "name": "Format Response", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { + "output": { + "assets": "{{ $steps.fetch_media.output }}", + "pagination": { + "total": "{{ $steps.count_total.output }}", + "page": "{{ $json.page || 1 }}", + "limit": "{{ $steps.extract_params.output.limit }}", + "hasMore": "{{ $steps.count_total.output > ($steps.extract_params.output.offset + $steps.extract_params.output.limit) }}" + } + }, + "operation": "transform_data" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.format_response.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 500 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "List all media assets for current user with filtering and sorting" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/notification_center/workflow/cleanup-expired.backup.jsonscript b/packages/notification_center/workflow/cleanup-expired.backup.jsonscript new file mode 100644 index 000000000..0e3bdb217 --- /dev/null +++ b/packages/notification_center/workflow/cleanup-expired.backup.jsonscript @@ -0,0 +1,92 @@ +{ + "version": "2.2.0", + "name": "Cleanup Expired Notifications", + "description": "Delete expired notifications and cleanup old read notifications", + "trigger": { + "type": "scheduled", + "schedule": "0 2 * * *" + }, + "nodes": [ + { + "id": "get_current_time", + "type": "operation", + "op": "transform_data", + "output": "{{ new Date().toISOString() }}" + }, + { + "id": "find_expired", + "type": "operation", + "op": "database_read", + "entity": "Notification", + "params": { + "filter": { + "expiresAt": { + "$lt": "{{ $steps.get_current_time.output }}" + } + }, + "limit": 10000 + } + }, + { + "id": "delete_expired", + "type": "operation", + "op": "database_delete_many", + "entity": "Notification", + "params": { + "filter": { + "expiresAt": { + "$lt": "{{ $steps.get_current_time.output }}" + } + } + } + }, + { + "id": "find_old_read", + "type": "operation", + "op": "database_read", + "entity": "Notification", + "params": { + "filter": { + "isRead": true, + "readAt": { + "$lt": "{{ new Date(Date.now() - 90 * 24 * 60 * 60 * 1000).toISOString() }}" + } + }, + "limit": 10000 + } + }, + { + "id": "delete_old_read", + "type": "operation", + "op": "database_delete_many", + "entity": "Notification", + "params": { + "filter": { + "isRead": true, + "readAt": { + "$lt": "{{ new Date(Date.now() - 90 * 24 * 60 * 60 * 1000).toISOString() }}" + } + } + } + }, + { + "id": "emit_cleanup_complete", + "type": "action", + "action": "emit_event", + "event": "cleanup_complete", + "channel": "admin", + "data": { + "expiredCount": "{{ $steps.find_expired.output.length }}", + "oldReadCount": "{{ $steps.find_old_read.output.length }}", + "timestamp": "{{ $steps.get_current_time.output }}" + } + }, + { + "id": "return_summary", + "type": "action", + "action": "log", + "level": "info", + "message": "Cleanup complete: {{ $steps.find_expired.output.length }} expired, {{ $steps.find_old_read.output.length }} old read notifications deleted" + } + ] +} diff --git a/packages/notification_center/workflow/cleanup-expired.jsonscript b/packages/notification_center/workflow/cleanup-expired.jsonscript index 0e3bdb217..d82511914 100644 --- a/packages/notification_center/workflow/cleanup-expired.jsonscript +++ b/packages/notification_center/workflow/cleanup-expired.jsonscript @@ -1,92 +1,147 @@ { - "version": "2.2.0", "name": "Cleanup Expired Notifications", - "description": "Delete expired notifications and cleanup old read notifications", - "trigger": { - "type": "scheduled", - "schedule": "0 2 * * *" - }, + "active": false, "nodes": [ { "id": "get_current_time", - "type": "operation", - "op": "transform_data", - "output": "{{ new Date().toISOString() }}" + "name": "Get Current Time", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "output": "{{ new Date().toISOString() }}", + "operation": "transform_data" + } }, { "id": "find_expired", - "type": "operation", - "op": "database_read", - "entity": "Notification", - "params": { + "name": "Find Expired", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { "filter": { "expiresAt": { "$lt": "{{ $steps.get_current_time.output }}" } }, - "limit": 10000 + "limit": 10000, + "operation": "database_read", + "entity": "Notification" } }, { "id": "delete_expired", - "type": "operation", - "op": "database_delete_many", - "entity": "Notification", - "params": { + "name": "Delete Expired", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { "filter": { "expiresAt": { "$lt": "{{ $steps.get_current_time.output }}" } - } + }, + "operation": "database_delete_many", + "entity": "Notification" } }, { "id": "find_old_read", - "type": "operation", - "op": "database_read", - "entity": "Notification", - "params": { + "name": "Find Old Read", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { "filter": { "isRead": true, "readAt": { "$lt": "{{ new Date(Date.now() - 90 * 24 * 60 * 60 * 1000).toISOString() }}" } }, - "limit": 10000 + "limit": 10000, + "operation": "database_read", + "entity": "Notification" } }, { "id": "delete_old_read", - "type": "operation", - "op": "database_delete_many", - "entity": "Notification", - "params": { + "name": "Delete Old Read", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { "filter": { "isRead": true, "readAt": { "$lt": "{{ new Date(Date.now() - 90 * 24 * 60 * 60 * 1000).toISOString() }}" } - } + }, + "operation": "database_delete_many", + "entity": "Notification" } }, { "id": "emit_cleanup_complete", - "type": "action", - "action": "emit_event", - "event": "cleanup_complete", - "channel": "admin", - "data": { - "expiredCount": "{{ $steps.find_expired.output.length }}", - "oldReadCount": "{{ $steps.find_old_read.output.length }}", - "timestamp": "{{ $steps.get_current_time.output }}" + "name": "Emit Cleanup Complete", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "data": { + "expiredCount": "{{ $steps.find_expired.output.length }}", + "oldReadCount": "{{ $steps.find_old_read.output.length }}", + "timestamp": "{{ $steps.get_current_time.output }}" + }, + "action": "emit_event", + "event": "cleanup_complete", + "channel": "admin" } }, { "id": "return_summary", - "type": "action", - "action": "log", - "level": "info", - "message": "Cleanup complete: {{ $steps.find_expired.output.length }} expired, {{ $steps.find_old_read.output.length }} old read notifications deleted" + "name": "Return Summary", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "action": "log", + "level": "info", + "message": "Cleanup complete: {{ $steps.find_expired.output.length }} expired, {{ $steps.find_old_read.output.length }} old read notifications deleted" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Delete expired notifications and cleanup old read notifications" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/notification_center/workflow/dispatch.backup.jsonscript b/packages/notification_center/workflow/dispatch.backup.jsonscript new file mode 100644 index 000000000..e8dac58bb --- /dev/null +++ b/packages/notification_center/workflow/dispatch.backup.jsonscript @@ -0,0 +1,148 @@ +{ + "version": "2.2.0", + "name": "Dispatch Notification", + "description": "Send notification via configured channels (in-app, email, push, webhook) with rate limiting", + "trigger": { + "type": "http", + "method": "POST", + "path": "/notifications/dispatch" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required" + }, + { + "id": "validate_input", + "type": "operation", + "op": "validate", + "input": "{{ $json }}", + "rules": { + "userId": "required|string", + "type": "required|string", + "title": "required|string|maxLength:200", + "message": "required|string|maxLength:1000", + "channels": "required|array" + } + }, + { + "id": "fetch_user_preferences", + "type": "operation", + "op": "database_read", + "entity": "NotificationPreference", + "params": { + "filter": { + "userId": "{{ $json.userId }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "create_notification_record", + "type": "operation", + "op": "database_create", + "entity": "Notification", + "data": { + "tenantId": "{{ $context.tenantId }}", + "userId": "{{ $json.userId }}", + "type": "{{ $json.type }}", + "title": "{{ $json.title }}", + "message": "{{ $json.message }}", + "isRead": false, + "metadata": "{{ $json.metadata || {} }}", + "createdAt": "{{ new Date().toISOString() }}", + "expiresAt": "{{ new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString() }}" + } + }, + { + "id": "dispatch_in_app", + "type": "operation", + "op": "condition", + "condition": "{{ $json.channels.includes('in_app') && $steps.fetch_user_preferences.output.enableInApp !== false }}" + }, + { + "id": "emit_in_app_notification", + "type": "action", + "action": "emit_event", + "event": "notification_received", + "channel": "{{ 'user:' + $json.userId }}", + "data": { + "notificationId": "{{ $steps.create_notification_record.output.id }}", + "title": "{{ $json.title }}", + "message": "{{ $json.message }}", + "type": "{{ $json.type }}" + } + }, + { + "id": "check_email_rate_limit", + "type": "operation", + "op": "condition", + "condition": "{{ $json.channels.includes('email') && $steps.fetch_user_preferences.output.enableEmail !== false }}" + }, + { + "id": "apply_email_rate_limit", + "type": "operation", + "op": "rate_limit", + "key": "{{ 'email:' + $json.userId }}", + "limit": 10, + "window": 3600000 + }, + { + "id": "fetch_user_email", + "type": "operation", + "op": "database_read", + "entity": "User", + "params": { + "filter": { + "id": "{{ $json.userId }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "send_email", + "type": "operation", + "op": "email_send", + "to": "{{ $steps.fetch_user_email.output.email }}", + "subject": "{{ $json.title }}", + "body": "{{ $json.message }}", + "template": "{{ $json.emailTemplate || 'default' }}" + }, + { + "id": "dispatch_push", + "type": "operation", + "op": "condition", + "condition": "{{ $json.channels.includes('push') && $steps.fetch_user_preferences.output.enablePush !== false }}" + }, + { + "id": "send_push_notification", + "type": "operation", + "op": "http_request", + "url": "https://fcm.googleapis.com/fcm/send", + "method": "POST", + "headers": { + "Authorization": "{{ 'Bearer ' + $env.FCM_KEY }}" + }, + "body": { + "to": "{{ $steps.fetch_user_email.output.fcmToken }}", + "notification": { + "title": "{{ $json.title }}", + "body": "{{ $json.message }}" + } + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 202, + "body": { + "notificationId": "{{ $steps.create_notification_record.output.id }}", + "message": "Notification dispatched successfully" + } + } + ] +} diff --git a/packages/notification_center/workflow/dispatch.jsonscript b/packages/notification_center/workflow/dispatch.jsonscript index e8dac58bb..e76cec28d 100644 --- a/packages/notification_center/workflow/dispatch.jsonscript +++ b/packages/notification_center/workflow/dispatch.jsonscript @@ -1,148 +1,254 @@ { - "version": "2.2.0", "name": "Dispatch Notification", - "description": "Send notification via configured channels (in-app, email, push, webhook) with rate limiting", - "trigger": { - "type": "http", - "method": "POST", - "path": "/notifications/dispatch" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" + } }, { "id": "validate_input", - "type": "operation", - "op": "validate", - "input": "{{ $json }}", - "rules": { - "userId": "required|string", - "type": "required|string", - "title": "required|string|maxLength:200", - "message": "required|string|maxLength:1000", - "channels": "required|array" + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "userId": "required|string", + "type": "required|string", + "title": "required|string|maxLength:200", + "message": "required|string|maxLength:1000", + "channels": "required|array" + } } }, { "id": "fetch_user_preferences", - "type": "operation", - "op": "database_read", - "entity": "NotificationPreference", - "params": { + "name": "Fetch User Preferences", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { "filter": { "userId": "{{ $json.userId }}", "tenantId": "{{ $context.tenantId }}" - } + }, + "operation": "database_read", + "entity": "NotificationPreference" } }, { "id": "create_notification_record", - "type": "operation", - "op": "database_create", - "entity": "Notification", - "data": { - "tenantId": "{{ $context.tenantId }}", - "userId": "{{ $json.userId }}", - "type": "{{ $json.type }}", - "title": "{{ $json.title }}", - "message": "{{ $json.message }}", - "isRead": false, - "metadata": "{{ $json.metadata || {} }}", - "createdAt": "{{ new Date().toISOString() }}", - "expiresAt": "{{ new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString() }}" + "name": "Create Notification Record", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "data": { + "tenantId": "{{ $context.tenantId }}", + "userId": "{{ $json.userId }}", + "type": "{{ $json.type }}", + "title": "{{ $json.title }}", + "message": "{{ $json.message }}", + "isRead": false, + "metadata": "{{ $json.metadata || {} }}", + "createdAt": "{{ new Date().toISOString() }}", + "expiresAt": "{{ new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString() }}" + }, + "operation": "database_create", + "entity": "Notification" } }, { "id": "dispatch_in_app", - "type": "operation", - "op": "condition", - "condition": "{{ $json.channels.includes('in_app') && $steps.fetch_user_preferences.output.enableInApp !== false }}" + "name": "Dispatch In App", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "condition": "{{ $json.channels.includes('in_app') && $steps.fetch_user_preferences.output.enableInApp !== false }}", + "operation": "condition" + } }, { "id": "emit_in_app_notification", - "type": "action", - "action": "emit_event", - "event": "notification_received", - "channel": "{{ 'user:' + $json.userId }}", - "data": { - "notificationId": "{{ $steps.create_notification_record.output.id }}", - "title": "{{ $json.title }}", - "message": "{{ $json.message }}", - "type": "{{ $json.type }}" + "name": "Emit In App Notification", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "data": { + "notificationId": "{{ $steps.create_notification_record.output.id }}", + "title": "{{ $json.title }}", + "message": "{{ $json.message }}", + "type": "{{ $json.type }}" + }, + "action": "emit_event", + "event": "notification_received", + "channel": "{{ 'user:' + $json.userId }}" } }, { "id": "check_email_rate_limit", - "type": "operation", - "op": "condition", - "condition": "{{ $json.channels.includes('email') && $steps.fetch_user_preferences.output.enableEmail !== false }}" + "name": "Check Email Rate Limit", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "condition": "{{ $json.channels.includes('email') && $steps.fetch_user_preferences.output.enableEmail !== false }}", + "operation": "condition" + } }, { "id": "apply_email_rate_limit", - "type": "operation", - "op": "rate_limit", - "key": "{{ 'email:' + $json.userId }}", - "limit": 10, - "window": 3600000 + "name": "Apply Email Rate Limit", + "type": "metabuilder.rateLimit", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { + "operation": "rate_limit", + "key": "{{ 'email:' + $json.userId }}", + "limit": 10, + "window": 3600000 + } }, { "id": "fetch_user_email", - "type": "operation", - "op": "database_read", - "entity": "User", - "params": { + "name": "Fetch User Email", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 500 + ], + "parameters": { "filter": { "id": "{{ $json.userId }}", "tenantId": "{{ $context.tenantId }}" - } + }, + "operation": "database_read", + "entity": "User" } }, { "id": "send_email", - "type": "operation", - "op": "email_send", - "to": "{{ $steps.fetch_user_email.output.email }}", - "subject": "{{ $json.title }}", - "body": "{{ $json.message }}", - "template": "{{ $json.emailTemplate || 'default' }}" + "name": "Send Email", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 700 + ], + "parameters": { + "operation": "email_send", + "to": "{{ $steps.fetch_user_email.output.email }}", + "subject": "{{ $json.title }}", + "body": "{{ $json.message }}", + "template": "{{ $json.emailTemplate || 'default' }}" + } }, { "id": "dispatch_push", - "type": "operation", - "op": "condition", - "condition": "{{ $json.channels.includes('push') && $steps.fetch_user_preferences.output.enablePush !== false }}" + "name": "Dispatch Push", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 400, + 700 + ], + "parameters": { + "condition": "{{ $json.channels.includes('push') && $steps.fetch_user_preferences.output.enablePush !== false }}", + "operation": "condition" + } }, { "id": "send_push_notification", - "type": "operation", - "op": "http_request", - "url": "https://fcm.googleapis.com/fcm/send", - "method": "POST", - "headers": { - "Authorization": "{{ 'Bearer ' + $env.FCM_KEY }}" - }, - "body": { - "to": "{{ $steps.fetch_user_email.output.fcmToken }}", - "notification": { - "title": "{{ $json.title }}", - "body": "{{ $json.message }}" + "name": "Send Push Notification", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 1, + "position": [ + 700, + 700 + ], + "parameters": { + "operation": "http_request", + "url": "https://fcm.googleapis.com/fcm/send", + "method": "POST", + "headers": { + "Authorization": "{{ 'Bearer ' + $env.FCM_KEY }}" + }, + "body": { + "to": "{{ $steps.fetch_user_email.output.fcmToken }}", + "notification": { + "title": "{{ $json.title }}", + "body": "{{ $json.message }}" + } } } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 202, - "body": { - "notificationId": "{{ $steps.create_notification_record.output.id }}", - "message": "Notification dispatched successfully" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 900 + ], + "parameters": { + "action": "http_response", + "status": 202, + "body": { + "notificationId": "{{ $steps.create_notification_record.output.id }}", + "message": "Notification dispatched successfully" + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Send notification via configured channels (in-app, email, push, webhook) with rate limiting" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/notification_center/workflow/list-unread.backup.jsonscript b/packages/notification_center/workflow/list-unread.backup.jsonscript new file mode 100644 index 000000000..34fbffc1a --- /dev/null +++ b/packages/notification_center/workflow/list-unread.backup.jsonscript @@ -0,0 +1,78 @@ +{ + "version": "2.2.0", + "name": "List Unread Notifications", + "description": "Fetch all unread notifications for current user with pagination", + "trigger": { + "type": "http", + "method": "GET", + "path": "/notifications/unread" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.user.id }}", + "validator": "required" + }, + { + "id": "extract_pagination", + "type": "operation", + "op": "transform_data", + "output": { + "limit": "{{ Math.min($json.limit || 50, 200) }}", + "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 50) }}" + } + }, + { + "id": "fetch_unread", + "type": "operation", + "op": "database_read", + "entity": "Notification", + "params": { + "filter": { + "userId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}", + "isRead": false + }, + "sort": {"createdAt": -1}, + "limit": "{{ $steps.extract_pagination.output.limit }}", + "offset": "{{ $steps.extract_pagination.output.offset }}" + } + }, + { + "id": "count_unread", + "type": "operation", + "op": "database_count", + "entity": "Notification", + "params": { + "filter": { + "userId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}", + "isRead": false + } + } + }, + { + "id": "format_response", + "type": "operation", + "op": "transform_data", + "output": { + "notifications": "{{ $steps.fetch_unread.output }}", + "unreadCount": "{{ $steps.count_unread.output }}", + "pagination": { + "page": "{{ $json.page || 1 }}", + "limit": "{{ $steps.extract_pagination.output.limit }}", + "hasMore": "{{ $steps.count_unread.output > ($steps.extract_pagination.output.offset + $steps.extract_pagination.output.limit) }}" + } + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } + ] +} diff --git a/packages/notification_center/workflow/list-unread.jsonscript b/packages/notification_center/workflow/list-unread.jsonscript index 34fbffc1a..b2ca4120b 100644 --- a/packages/notification_center/workflow/list-unread.jsonscript +++ b/packages/notification_center/workflow/list-unread.jsonscript @@ -1,78 +1,130 @@ { - "version": "2.2.0", "name": "List Unread Notifications", - "description": "Fetch all unread notifications for current user with pagination", - "trigger": { - "type": "http", - "method": "GET", - "path": "/notifications/unread" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.user.id }}", - "validator": "required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } }, { "id": "extract_pagination", - "type": "operation", - "op": "transform_data", - "output": { - "limit": "{{ Math.min($json.limit || 50, 200) }}", - "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 50) }}" + "name": "Extract Pagination", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "output": { + "limit": "{{ Math.min($json.limit || 50, 200) }}", + "offset": "{{ ($json.page || 1 - 1) * ($json.limit || 50) }}" + }, + "operation": "transform_data" } }, { "id": "fetch_unread", - "type": "operation", - "op": "database_read", - "entity": "Notification", - "params": { + "name": "Fetch Unread", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { "filter": { "userId": "{{ $context.user.id }}", "tenantId": "{{ $context.tenantId }}", "isRead": false }, - "sort": {"createdAt": -1}, + "sort": { + "createdAt": -1 + }, "limit": "{{ $steps.extract_pagination.output.limit }}", - "offset": "{{ $steps.extract_pagination.output.offset }}" + "offset": "{{ $steps.extract_pagination.output.offset }}", + "operation": "database_read", + "entity": "Notification" } }, { "id": "count_unread", - "type": "operation", - "op": "database_count", - "entity": "Notification", - "params": { + "name": "Count Unread", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { "filter": { "userId": "{{ $context.user.id }}", "tenantId": "{{ $context.tenantId }}", "isRead": false - } + }, + "operation": "database_count", + "entity": "Notification" } }, { "id": "format_response", - "type": "operation", - "op": "transform_data", - "output": { - "notifications": "{{ $steps.fetch_unread.output }}", - "unreadCount": "{{ $steps.count_unread.output }}", - "pagination": { - "page": "{{ $json.page || 1 }}", - "limit": "{{ $steps.extract_pagination.output.limit }}", - "hasMore": "{{ $steps.count_unread.output > ($steps.extract_pagination.output.offset + $steps.extract_pagination.output.limit) }}" - } + "name": "Format Response", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "output": { + "notifications": "{{ $steps.fetch_unread.output }}", + "unreadCount": "{{ $steps.count_unread.output }}", + "pagination": { + "page": "{{ $json.page || 1 }}", + "limit": "{{ $steps.extract_pagination.output.limit }}", + "hasMore": "{{ $steps.count_unread.output > ($steps.extract_pagination.output.offset + $steps.extract_pagination.output.limit) }}" + } + }, + "operation": "transform_data" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": "{{ $steps.format_response.output }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.format_response.output }}" + } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Fetch all unread notifications for current user with pagination" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/notification_center/workflow/mark-as-read.backup.jsonscript b/packages/notification_center/workflow/mark-as-read.backup.jsonscript new file mode 100644 index 000000000..edc81fbc3 --- /dev/null +++ b/packages/notification_center/workflow/mark-as-read.backup.jsonscript @@ -0,0 +1,87 @@ +{ + "version": "2.2.0", + "name": "Mark Notification as Read", + "description": "Mark single or multiple notifications as read by user", + "trigger": { + "type": "http", + "method": "POST", + "path": "/notifications/mark-read" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.tenantId }}", + "validator": "required" + }, + { + "id": "validate_user", + "type": "operation", + "op": "validate", + "input": "{{ $context.user.id }}", + "validator": "required" + }, + { + "id": "check_bulk_vs_single", + "type": "operation", + "op": "condition", + "condition": "{{ Array.isArray($json.notificationIds) }}" + }, + { + "id": "mark_single", + "type": "operation", + "op": "database_update", + "entity": "Notification", + "params": { + "filter": { + "id": "{{ $json.notificationId }}", + "userId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + }, + "data": { + "isRead": true, + "readAt": "{{ new Date().toISOString() }}" + } + } + }, + { + "id": "mark_bulk", + "type": "operation", + "op": "database_update_many", + "entity": "Notification", + "params": { + "filter": { + "id": { + "$in": "{{ $json.notificationIds }}" + }, + "userId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + }, + "data": { + "isRead": true, + "readAt": "{{ new Date().toISOString() }}" + } + } + }, + { + "id": "emit_read_event", + "type": "action", + "action": "emit_event", + "event": "notification_read", + "channel": "{{ 'user:' + $context.user.id }}", + "data": { + "notificationIds": "{{ Array.isArray($json.notificationIds) ? $json.notificationIds : [$json.notificationId] }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": { + "message": "Notification(s) marked as read" + } + } + ] +} diff --git a/packages/notification_center/workflow/mark-as-read.jsonscript b/packages/notification_center/workflow/mark-as-read.jsonscript index edc81fbc3..12e0a5bf1 100644 --- a/packages/notification_center/workflow/mark-as-read.jsonscript +++ b/packages/notification_center/workflow/mark-as-read.jsonscript @@ -1,39 +1,61 @@ { - "version": "2.2.0", "name": "Mark Notification as Read", - "description": "Mark single or multiple notifications as read by user", - "trigger": { - "type": "http", - "method": "POST", - "path": "/notifications/mark-read" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.tenantId }}", - "validator": "required" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" + } }, { "id": "validate_user", - "type": "operation", - "op": "validate", - "input": "{{ $context.user.id }}", - "validator": "required" + "name": "Validate User", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } }, { "id": "check_bulk_vs_single", - "type": "operation", - "op": "condition", - "condition": "{{ Array.isArray($json.notificationIds) }}" + "name": "Check Bulk Vs Single", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "condition": "{{ Array.isArray($json.notificationIds) }}", + "operation": "condition" + } }, { "id": "mark_single", - "type": "operation", - "op": "database_update", - "entity": "Notification", - "params": { + "name": "Mark Single", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { "filter": { "id": "{{ $json.notificationId }}", "userId": "{{ $context.user.id }}", @@ -42,15 +64,21 @@ "data": { "isRead": true, "readAt": "{{ new Date().toISOString() }}" - } + }, + "operation": "database_update", + "entity": "Notification" } }, { "id": "mark_bulk", - "type": "operation", - "op": "database_update_many", - "entity": "Notification", - "params": { + "name": "Mark Bulk", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { "filter": { "id": { "$in": "{{ $json.notificationIds }}" @@ -61,27 +89,57 @@ "data": { "isRead": true, "readAt": "{{ new Date().toISOString() }}" - } + }, + "operation": "database_update_many", + "entity": "Notification" } }, { "id": "emit_read_event", - "type": "action", - "action": "emit_event", - "event": "notification_read", - "channel": "{{ 'user:' + $context.user.id }}", - "data": { - "notificationIds": "{{ Array.isArray($json.notificationIds) ? $json.notificationIds : [$json.notificationId] }}" + "name": "Emit Read Event", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "data": { + "notificationIds": "{{ Array.isArray($json.notificationIds) ? $json.notificationIds : [$json.notificationId] }}" + }, + "action": "emit_event", + "event": "notification_read", + "channel": "{{ 'user:' + $context.user.id }}" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": { - "message": "Notification(s) marked as read" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": { + "message": "Notification(s) marked as read" + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Mark single or multiple notifications as read by user" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/stream_cast/workflow/scene-transition.backup.jsonscript b/packages/stream_cast/workflow/scene-transition.backup.jsonscript new file mode 100644 index 000000000..caacc3e7f --- /dev/null +++ b/packages/stream_cast/workflow/scene-transition.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"Handle Scene Transition","description":"Update stream scene and broadcast to viewers","trigger":{"type":"http","method":"POST","path":"/streams/:channelId/scenes/:sceneId/activate"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"check_authorization","type":"operation","op":"condition","condition":"{{ $context.user.level >= 2 }}"},{"id":"fetch_channel","type":"operation","op":"database_read","entity":"StreamChannel","params":{"filter":{"id":"{{ $json.channelId }}","tenantId":"{{ $context.tenantId }}"}}},{"id":"update_active_scene","type":"operation","op":"database_update","entity":"StreamChannel","params":{"filter":{"id":"{{ $json.channelId }}"},"data":{"activeSceneId":"{{ $json.sceneId }}","sceneChangedAt":"{{ new Date().toISOString() }}"}}},{"id":"emit_scene_change","type":"action","action":"emit_event","event":"scene_changed","channel":"{{ 'stream:' + $json.channelId }}","data":{"sceneId":"{{ $json.sceneId }}","transitionTime":"{{ new Date().toISOString() }}"}},{"id":"return_success","type":"action","action":"http_response","status":200,"body":{"message":"Scene updated"}}] +} diff --git a/packages/stream_cast/workflow/scene-transition.jsonscript b/packages/stream_cast/workflow/scene-transition.jsonscript index caacc3e7f..f6fb614bc 100644 --- a/packages/stream_cast/workflow/scene-transition.jsonscript +++ b/packages/stream_cast/workflow/scene-transition.jsonscript @@ -1,3 +1,122 @@ { - "version":"2.2.0","name":"Handle Scene Transition","description":"Update stream scene and broadcast to viewers","trigger":{"type":"http","method":"POST","path":"/streams/:channelId/scenes/:sceneId/activate"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"check_authorization","type":"operation","op":"condition","condition":"{{ $context.user.level >= 2 }}"},{"id":"fetch_channel","type":"operation","op":"database_read","entity":"StreamChannel","params":{"filter":{"id":"{{ $json.channelId }}","tenantId":"{{ $context.tenantId }}"}}},{"id":"update_active_scene","type":"operation","op":"database_update","entity":"StreamChannel","params":{"filter":{"id":"{{ $json.channelId }}"},"data":{"activeSceneId":"{{ $json.sceneId }}","sceneChangedAt":"{{ new Date().toISOString() }}"}}},{"id":"emit_scene_change","type":"action","action":"emit_event","event":"scene_changed","channel":"{{ 'stream:' + $json.channelId }}","data":{"sceneId":"{{ $json.sceneId }}","transitionTime":"{{ new Date().toISOString() }}"}},{"id":"return_success","type":"action","action":"http_response","status":200,"body":{"message":"Scene updated"}}] + "name": "Handle Scene Transition", + "active": false, + "nodes": [ + { + "id": "validate_context", + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } + }, + { + "id": "check_authorization", + "name": "Check Authorization", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "condition": "{{ $context.user.level >= 2 }}", + "operation": "condition" + } + }, + { + "id": "fetch_channel", + "name": "Fetch Channel", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "filter": { + "id": "{{ $json.channelId }}", + "tenantId": "{{ $context.tenantId }}" + }, + "operation": "database_read", + "entity": "StreamChannel" + } + }, + { + "id": "update_active_scene", + "name": "Update Active Scene", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "filter": { + "id": "{{ $json.channelId }}" + }, + "data": { + "activeSceneId": "{{ $json.sceneId }}", + "sceneChangedAt": "{{ new Date().toISOString() }}" + }, + "operation": "database_update", + "entity": "StreamChannel" + } + }, + { + "id": "emit_scene_change", + "name": "Emit Scene Change", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "data": { + "sceneId": "{{ $json.sceneId }}", + "transitionTime": "{{ new Date().toISOString() }}" + }, + "action": "emit_event", + "event": "scene_changed", + "channel": "{{ 'stream:' + $json.channelId }}" + } + }, + { + "id": "return_success", + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": { + "message": "Scene updated" + } + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Update stream scene and broadcast to viewers" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/stream_cast/workflow/stream-subscribe.backup.jsonscript b/packages/stream_cast/workflow/stream-subscribe.backup.jsonscript new file mode 100644 index 000000000..ee5934aa1 --- /dev/null +++ b/packages/stream_cast/workflow/stream-subscribe.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"Subscribe to Stream","description":"Subscribe user to stream updates via SSE","trigger":{"type":"http","method":"GET","path":"/streams/:channelId/subscribe"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"fetch_channel","type":"operation","op":"database_read","entity":"StreamChannel","params":{"filter":{"id":"{{ $json.channelId }}","tenantId":"{{ $context.tenantId }}"}}},{"id":"create_subscription","type":"operation","op":"database_create","entity":"StreamSubscription","data":{"channelId":"{{ $json.channelId }}","userId":"{{ $context.user.id }}","tenantId":"{{ $context.tenantId }}","subscribedAt":"{{ new Date().toISOString() }}"}},{"id":"setup_sse","type":"action","action":"sse_stream","channel":"{{ 'stream:' + $json.channelId }}","onConnect":"{{ { subscriptionId: $steps.create_subscription.output.id } }}"}] +} diff --git a/packages/stream_cast/workflow/stream-subscribe.jsonscript b/packages/stream_cast/workflow/stream-subscribe.jsonscript index ee5934aa1..7aa6ba214 100644 --- a/packages/stream_cast/workflow/stream-subscribe.jsonscript +++ b/packages/stream_cast/workflow/stream-subscribe.jsonscript @@ -1,3 +1,86 @@ { - "version":"2.2.0","name":"Subscribe to Stream","description":"Subscribe user to stream updates via SSE","trigger":{"type":"http","method":"GET","path":"/streams/:channelId/subscribe"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"fetch_channel","type":"operation","op":"database_read","entity":"StreamChannel","params":{"filter":{"id":"{{ $json.channelId }}","tenantId":"{{ $context.tenantId }}"}}},{"id":"create_subscription","type":"operation","op":"database_create","entity":"StreamSubscription","data":{"channelId":"{{ $json.channelId }}","userId":"{{ $context.user.id }}","tenantId":"{{ $context.tenantId }}","subscribedAt":"{{ new Date().toISOString() }}"}},{"id":"setup_sse","type":"action","action":"sse_stream","channel":"{{ 'stream:' + $json.channelId }}","onConnect":"{{ { subscriptionId: $steps.create_subscription.output.id } }}"}] + "name": "Subscribe to Stream", + "active": false, + "nodes": [ + { + "id": "validate_context", + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } + }, + { + "id": "fetch_channel", + "name": "Fetch Channel", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "filter": { + "id": "{{ $json.channelId }}", + "tenantId": "{{ $context.tenantId }}" + }, + "operation": "database_read", + "entity": "StreamChannel" + } + }, + { + "id": "create_subscription", + "name": "Create Subscription", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "data": { + "channelId": "{{ $json.channelId }}", + "userId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}", + "subscribedAt": "{{ new Date().toISOString() }}" + }, + "operation": "database_create", + "entity": "StreamSubscription" + } + }, + { + "id": "setup_sse", + "name": "Setup Sse", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "action": "sse_stream", + "channel": "{{ 'stream:' + $json.channelId }}", + "onConnect": "{{ { subscriptionId: $steps.create_subscription.output.id } }}" + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Subscribe user to stream updates via SSE" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/stream_cast/workflow/stream-unsubscribe.backup.jsonscript b/packages/stream_cast/workflow/stream-unsubscribe.backup.jsonscript new file mode 100644 index 000000000..a8f160b05 --- /dev/null +++ b/packages/stream_cast/workflow/stream-unsubscribe.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"Unsubscribe from Stream","description":"Remove user stream subscription","trigger":{"type":"http","method":"POST","path":"/streams/:channelId/unsubscribe"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"delete_subscription","type":"operation","op":"database_delete","entity":"StreamSubscription","params":{"filter":{"channelId":"{{ $json.channelId }}","userId":"{{ $context.user.id }}","tenantId":"{{ $context.tenantId }}"}}},{"id":"return_success","type":"action","action":"http_response","status":200,"body":{"message":"Unsubscribed successfully"}}] +} diff --git a/packages/stream_cast/workflow/stream-unsubscribe.jsonscript b/packages/stream_cast/workflow/stream-unsubscribe.jsonscript index a8f160b05..86c600d8a 100644 --- a/packages/stream_cast/workflow/stream-unsubscribe.jsonscript +++ b/packages/stream_cast/workflow/stream-unsubscribe.jsonscript @@ -1,3 +1,69 @@ { - "version":"2.2.0","name":"Unsubscribe from Stream","description":"Remove user stream subscription","trigger":{"type":"http","method":"POST","path":"/streams/:channelId/unsubscribe"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.user.id }}","validator":"required"},{"id":"delete_subscription","type":"operation","op":"database_delete","entity":"StreamSubscription","params":{"filter":{"channelId":"{{ $json.channelId }}","userId":"{{ $context.user.id }}","tenantId":"{{ $context.tenantId }}"}}},{"id":"return_success","type":"action","action":"http_response","status":200,"body":{"message":"Unsubscribed successfully"}}] + "name": "Unsubscribe from Stream", + "active": false, + "nodes": [ + { + "id": "validate_context", + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" + } + }, + { + "id": "delete_subscription", + "name": "Delete Subscription", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "filter": { + "channelId": "{{ $json.channelId }}", + "userId": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + }, + "operation": "database_delete", + "entity": "StreamSubscription" + } + }, + { + "id": "return_success", + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": { + "message": "Unsubscribed successfully" + } + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Remove user stream subscription" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/stream_cast/workflow/viewer-count-update.backup.jsonscript b/packages/stream_cast/workflow/viewer-count-update.backup.jsonscript new file mode 100644 index 000000000..921021357 --- /dev/null +++ b/packages/stream_cast/workflow/viewer-count-update.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"Update Viewer Count","description":"Update and broadcast current viewer count","trigger":{"type":"scheduled","schedule":"*/30 * * * *"},"nodes":[{"id":"fetch_active_streams","type":"operation","op":"database_read","entity":"StreamChannel","params":{"filter":{"isLive":true}}},{"id":"update_viewer_counts","type":"operation","op":"parallel","tasks":[{"id":"count_viewers","op":"database_count","entity":"StreamSubscription","params":{"filter":{"channelId":"{{ $steps.fetch_active_streams.output.id }}"}}},{"id":"fetch_channel_stats","op":"database_read","entity":"StreamChannel","params":{"filter":{"id":"{{ $steps.fetch_active_streams.output.id }}"}}}]},{"id":"broadcast_counts","type":"action","action":"emit_event","event":"viewer_count_updated","channel":"{{ 'stream:' + $steps.fetch_active_streams.output.id }}","data":{"viewerCount":"{{ $steps.update_viewer_counts.tasks.count_viewers.output }}","liveTime":"{{ new Date() - new Date($steps.update_viewer_counts.tasks.fetch_channel_stats.output.startedAt) }}"}}] +} diff --git a/packages/stream_cast/workflow/viewer-count-update.jsonscript b/packages/stream_cast/workflow/viewer-count-update.jsonscript index 921021357..4a7fa2403 100644 --- a/packages/stream_cast/workflow/viewer-count-update.jsonscript +++ b/packages/stream_cast/workflow/viewer-count-update.jsonscript @@ -1,3 +1,89 @@ { - "version":"2.2.0","name":"Update Viewer Count","description":"Update and broadcast current viewer count","trigger":{"type":"scheduled","schedule":"*/30 * * * *"},"nodes":[{"id":"fetch_active_streams","type":"operation","op":"database_read","entity":"StreamChannel","params":{"filter":{"isLive":true}}},{"id":"update_viewer_counts","type":"operation","op":"parallel","tasks":[{"id":"count_viewers","op":"database_count","entity":"StreamSubscription","params":{"filter":{"channelId":"{{ $steps.fetch_active_streams.output.id }}"}}},{"id":"fetch_channel_stats","op":"database_read","entity":"StreamChannel","params":{"filter":{"id":"{{ $steps.fetch_active_streams.output.id }}"}}}]},{"id":"broadcast_counts","type":"action","action":"emit_event","event":"viewer_count_updated","channel":"{{ 'stream:' + $steps.fetch_active_streams.output.id }}","data":{"viewerCount":"{{ $steps.update_viewer_counts.tasks.count_viewers.output }}","liveTime":"{{ new Date() - new Date($steps.update_viewer_counts.tasks.fetch_channel_stats.output.startedAt) }}"}}] + "name": "Update Viewer Count", + "active": false, + "nodes": [ + { + "id": "fetch_active_streams", + "name": "Fetch Active Streams", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "filter": { + "isLive": true + }, + "operation": "database_read", + "entity": "StreamChannel" + } + }, + { + "id": "update_viewer_counts", + "name": "Update Viewer Counts", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "operation": "parallel", + "tasks": [ + { + "id": "count_viewers", + "op": "database_count", + "entity": "StreamSubscription", + "params": { + "filter": { + "channelId": "{{ $steps.fetch_active_streams.output.id }}" + } + } + }, + { + "id": "fetch_channel_stats", + "op": "database_read", + "entity": "StreamChannel", + "params": { + "filter": { + "id": "{{ $steps.fetch_active_streams.output.id }}" + } + } + } + ] + } + }, + { + "id": "broadcast_counts", + "name": "Broadcast Counts", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "data": { + "viewerCount": "{{ $steps.update_viewer_counts.tasks.count_viewers.output }}", + "liveTime": "{{ new Date() - new Date($steps.update_viewer_counts.tasks.fetch_channel_stats.output.startedAt) }}" + }, + "action": "emit_event", + "event": "viewer_count_updated", + "channel": "{{ 'stream:' + $steps.fetch_active_streams.output.id }}" + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Update and broadcast current viewer count" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/ui_auth/workflow/login-workflow.backup.jsonscript b/packages/ui_auth/workflow/login-workflow.backup.jsonscript new file mode 100644 index 000000000..8d1390381 --- /dev/null +++ b/packages/ui_auth/workflow/login-workflow.backup.jsonscript @@ -0,0 +1,146 @@ +{ + "version": "2.2.0", + "name": "Login Workflow", + "description": "User login with email/password, rate limiting, and session creation", + "trigger": { + "type": "http", + "method": "POST", + "path": "/auth/login" + }, + "nodes": [ + { + "id": "apply_rate_limit", + "type": "operation", + "op": "rate_limit", + "key": "{{ $json.email }}", + "limit": 5, + "window": 60000, + "errorMessage": "Too many login attempts. Please try again in a few minutes." + }, + { + "id": "validate_input", + "type": "operation", + "op": "validate", + "input": "{{ $json }}", + "rules": { + "email": "required|email", + "password": "required|string|minLength:6" + } + }, + { + "id": "fetch_user", + "type": "operation", + "op": "database_read", + "entity": "User", + "params": { + "filter": { + "email": "{{ $json.email }}" + } + } + }, + { + "id": "check_user_exists", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.fetch_user.output !== null }}" + }, + { + "id": "verify_password", + "type": "operation", + "op": "crypto", + "operation": "bcrypt_compare", + "input": "{{ $json.password }}", + "hash": "{{ $steps.fetch_user.output.passwordHash }}" + }, + { + "id": "check_password_valid", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.verify_password.output === true }}" + }, + { + "id": "check_account_active", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.fetch_user.output.isActive !== false }}" + }, + { + "id": "generate_session", + "type": "operation", + "op": "crypto", + "operation": "generate_jwt", + "payload": { + "userId": "{{ $steps.fetch_user.output.id }}", + "email": "{{ $steps.fetch_user.output.email }}", + "tenantId": "{{ $steps.fetch_user.output.tenantId }}", + "level": "{{ $steps.fetch_user.output.level }}" + }, + "secret": "{{ $env.JWT_SECRET }}", + "expiresIn": "24h" + }, + { + "id": "create_session_record", + "type": "operation", + "op": "database_create", + "entity": "Session", + "data": { + "userId": "{{ $steps.fetch_user.output.id }}", + "tenantId": "{{ $steps.fetch_user.output.tenantId }}", + "token": "{{ $steps.generate_session.output }}", + "ipAddress": "{{ $json.ipAddress }}", + "userAgent": "{{ $json.userAgent }}", + "expiresAt": "{{ new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() }}" + } + }, + { + "id": "update_last_login", + "type": "operation", + "op": "database_update", + "entity": "User", + "params": { + "filter": { + "id": "{{ $steps.fetch_user.output.id }}" + }, + "data": { + "lastLogin": "{{ new Date().toISOString() }}" + } + } + }, + { + "id": "emit_login_event", + "type": "action", + "action": "emit_event", + "event": "user_login", + "channel": "{{ 'user:' + $steps.fetch_user.output.id }}", + "data": { + "userId": "{{ $steps.fetch_user.output.id }}", + "tenantId": "{{ $steps.fetch_user.output.tenantId }}", + "timestamp": "{{ new Date().toISOString() }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": { + "token": "{{ $steps.generate_session.output }}", + "user": { + "id": "{{ $steps.fetch_user.output.id }}", + "email": "{{ $steps.fetch_user.output.email }}", + "displayName": "{{ $steps.fetch_user.output.displayName }}", + "tenantId": "{{ $steps.fetch_user.output.tenantId }}" + } + } + } + ], + "errorHandler": { + "type": "action", + "action": "http_response", + "status": 401, + "body": { + "error": "Invalid credentials", + "message": "Email or password is incorrect" + } + } +} diff --git a/packages/ui_auth/workflow/login-workflow.jsonscript b/packages/ui_auth/workflow/login-workflow.jsonscript index 8d1390381..8d854be57 100644 --- a/packages/ui_auth/workflow/login-workflow.jsonscript +++ b/packages/ui_auth/workflow/login-workflow.jsonscript @@ -1,146 +1,233 @@ { - "version": "2.2.0", "name": "Login Workflow", - "description": "User login with email/password, rate limiting, and session creation", - "trigger": { - "type": "http", - "method": "POST", - "path": "/auth/login" - }, + "active": false, "nodes": [ { "id": "apply_rate_limit", - "type": "operation", - "op": "rate_limit", - "key": "{{ $json.email }}", - "limit": 5, - "window": 60000, - "errorMessage": "Too many login attempts. Please try again in a few minutes." - }, - { - "id": "validate_input", - "type": "operation", - "op": "validate", - "input": "{{ $json }}", - "rules": { - "email": "required|email", - "password": "required|string|minLength:6" + "name": "Apply Rate Limit", + "type": "metabuilder.rateLimit", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "operation": "rate_limit", + "key": "{{ $json.email }}", + "limit": 5, + "window": 60000, + "errorMessage": "Too many login attempts. Please try again in a few minutes." } }, { - "id": "fetch_user", - "type": "operation", - "op": "database_read", - "entity": "User", - "params": { - "filter": { - "email": "{{ $json.email }}" + "id": "validate_input", + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "email": "required|email", + "password": "required|string|minLength:6" } } }, + { + "id": "fetch_user", + "name": "Fetch User", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "filter": { + "email": "{{ $json.email }}" + }, + "operation": "database_read", + "entity": "User" + } + }, { "id": "check_user_exists", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.fetch_user.output !== null }}" + "name": "Check User Exists", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "condition": "{{ $steps.fetch_user.output !== null }}", + "operation": "condition" + } }, { "id": "verify_password", - "type": "operation", - "op": "crypto", - "operation": "bcrypt_compare", - "input": "{{ $json.password }}", - "hash": "{{ $steps.fetch_user.output.passwordHash }}" + "name": "Verify Password", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "input": "{{ $json.password }}", + "operation": "bcrypt_compare", + "hash": "{{ $steps.fetch_user.output.passwordHash }}" + } }, { "id": "check_password_valid", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.verify_password.output === true }}" + "name": "Check Password Valid", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "condition": "{{ $steps.verify_password.output === true }}", + "operation": "condition" + } }, { "id": "check_account_active", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.fetch_user.output.isActive !== false }}" + "name": "Check Account Active", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "condition": "{{ $steps.fetch_user.output.isActive !== false }}", + "operation": "condition" + } }, { "id": "generate_session", - "type": "operation", - "op": "crypto", - "operation": "generate_jwt", - "payload": { - "userId": "{{ $steps.fetch_user.output.id }}", - "email": "{{ $steps.fetch_user.output.email }}", - "tenantId": "{{ $steps.fetch_user.output.tenantId }}", - "level": "{{ $steps.fetch_user.output.level }}" - }, - "secret": "{{ $env.JWT_SECRET }}", - "expiresIn": "24h" + "name": "Generate Session", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { + "operation": "generate_jwt", + "payload": { + "userId": "{{ $steps.fetch_user.output.id }}", + "email": "{{ $steps.fetch_user.output.email }}", + "tenantId": "{{ $steps.fetch_user.output.tenantId }}", + "level": "{{ $steps.fetch_user.output.level }}" + }, + "secret": "{{ $env.JWT_SECRET }}", + "expiresIn": "24h" + } }, { "id": "create_session_record", - "type": "operation", - "op": "database_create", - "entity": "Session", - "data": { - "userId": "{{ $steps.fetch_user.output.id }}", - "tenantId": "{{ $steps.fetch_user.output.tenantId }}", - "token": "{{ $steps.generate_session.output }}", - "ipAddress": "{{ $json.ipAddress }}", - "userAgent": "{{ $json.userAgent }}", - "expiresAt": "{{ new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() }}" + "name": "Create Session Record", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 500 + ], + "parameters": { + "data": { + "userId": "{{ $steps.fetch_user.output.id }}", + "tenantId": "{{ $steps.fetch_user.output.tenantId }}", + "token": "{{ $steps.generate_session.output }}", + "ipAddress": "{{ $json.ipAddress }}", + "userAgent": "{{ $json.userAgent }}", + "expiresAt": "{{ new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() }}" + }, + "operation": "database_create", + "entity": "Session" } }, { "id": "update_last_login", - "type": "operation", - "op": "database_update", - "entity": "User", - "params": { + "name": "Update Last Login", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 700 + ], + "parameters": { "filter": { "id": "{{ $steps.fetch_user.output.id }}" }, "data": { "lastLogin": "{{ new Date().toISOString() }}" - } + }, + "operation": "database_update", + "entity": "User" } }, { "id": "emit_login_event", - "type": "action", - "action": "emit_event", - "event": "user_login", - "channel": "{{ 'user:' + $steps.fetch_user.output.id }}", - "data": { - "userId": "{{ $steps.fetch_user.output.id }}", - "tenantId": "{{ $steps.fetch_user.output.tenantId }}", - "timestamp": "{{ new Date().toISOString() }}" + "name": "Emit Login Event", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 700 + ], + "parameters": { + "data": { + "userId": "{{ $steps.fetch_user.output.id }}", + "tenantId": "{{ $steps.fetch_user.output.tenantId }}", + "timestamp": "{{ new Date().toISOString() }}" + }, + "action": "emit_event", + "event": "user_login", + "channel": "{{ 'user:' + $steps.fetch_user.output.id }}" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": { - "token": "{{ $steps.generate_session.output }}", - "user": { - "id": "{{ $steps.fetch_user.output.id }}", - "email": "{{ $steps.fetch_user.output.email }}", - "displayName": "{{ $steps.fetch_user.output.displayName }}", - "tenantId": "{{ $steps.fetch_user.output.tenantId }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 700 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": { + "token": "{{ $steps.generate_session.output }}", + "user": { + "id": "{{ $steps.fetch_user.output.id }}", + "email": "{{ $steps.fetch_user.output.email }}", + "displayName": "{{ $steps.fetch_user.output.displayName }}", + "tenantId": "{{ $steps.fetch_user.output.tenantId }}" + } } } } ], - "errorHandler": { - "type": "action", - "action": "http_response", - "status": 401, - "body": { - "error": "Invalid credentials", - "message": "Email or password is incorrect" - } + "connections": {}, + "staticData": {}, + "meta": { + "description": "User login with email/password, rate limiting, and session creation" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" } } diff --git a/packages/ui_auth/workflow/password-change-workflow.backup.jsonscript b/packages/ui_auth/workflow/password-change-workflow.backup.jsonscript new file mode 100644 index 000000000..aa788e8a1 --- /dev/null +++ b/packages/ui_auth/workflow/password-change-workflow.backup.jsonscript @@ -0,0 +1,124 @@ +{ + "version": "2.2.0", + "name": "Password Change Workflow", + "description": "Change password for authenticated user with old password verification", + "trigger": { + "type": "http", + "method": "POST", + "path": "/auth/change-password" + }, + "nodes": [ + { + "id": "validate_context", + "type": "operation", + "op": "validate", + "input": "{{ $context.user.id }}", + "validator": "required" + }, + { + "id": "validate_input", + "type": "operation", + "op": "validate", + "input": "{{ $json }}", + "rules": { + "currentPassword": "required|string", + "newPassword": "required|string|minLength:8|different:currentPassword", + "confirmPassword": "required|string|same:newPassword" + } + }, + { + "id": "fetch_user", + "type": "operation", + "op": "database_read", + "entity": "User", + "params": { + "filter": { + "id": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "verify_current_password", + "type": "operation", + "op": "crypto", + "operation": "bcrypt_compare", + "input": "{{ $json.currentPassword }}", + "hash": "{{ $steps.fetch_user.output.passwordHash }}" + }, + { + "id": "check_password_correct", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.verify_current_password.output === true }}" + }, + { + "id": "hash_new_password", + "type": "operation", + "op": "crypto", + "operation": "bcrypt_hash", + "input": "{{ $json.newPassword }}", + "rounds": 12 + }, + { + "id": "update_password", + "type": "operation", + "op": "database_update", + "entity": "User", + "params": { + "filter": { + "id": "{{ $context.user.id }}" + }, + "data": { + "passwordHash": "{{ $steps.hash_new_password.output }}", + "passwordChangedAt": "{{ new Date().toISOString() }}" + } + } + }, + { + "id": "invalidate_sessions", + "type": "operation", + "op": "database_delete_many", + "entity": "Session", + "params": { + "filter": { + "userId": "{{ $context.user.id }}", + "id": { + "$ne": "{{ $context.sessionId }}" + } + } + } + }, + { + "id": "send_confirmation_email", + "type": "operation", + "op": "email_send", + "to": "{{ $steps.fetch_user.output.email }}", + "subject": "Your password has been changed", + "template": "password_changed", + "data": { + "displayName": "{{ $steps.fetch_user.output.displayName }}", + "timestamp": "{{ new Date().toISOString() }}" + } + }, + { + "id": "emit_event", + "type": "action", + "action": "emit_event", + "event": "password_changed", + "channel": "{{ 'user:' + $context.user.id }}", + "data": { + "timestamp": "{{ new Date().toISOString() }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": { + "message": "Password changed successfully. All other sessions have been invalidated for security." + } + } + ] +} diff --git a/packages/ui_auth/workflow/password-change-workflow.jsonscript b/packages/ui_auth/workflow/password-change-workflow.jsonscript index aa788e8a1..6ea6dd4eb 100644 --- a/packages/ui_auth/workflow/password-change-workflow.jsonscript +++ b/packages/ui_auth/workflow/password-change-workflow.jsonscript @@ -1,124 +1,210 @@ { - "version": "2.2.0", "name": "Password Change Workflow", - "description": "Change password for authenticated user with old password verification", - "trigger": { - "type": "http", - "method": "POST", - "path": "/auth/change-password" - }, + "active": false, "nodes": [ { "id": "validate_context", - "type": "operation", - "op": "validate", - "input": "{{ $context.user.id }}", - "validator": "required" - }, - { - "id": "validate_input", - "type": "operation", - "op": "validate", - "input": "{{ $json }}", - "rules": { - "currentPassword": "required|string", - "newPassword": "required|string|minLength:8|different:currentPassword", - "confirmPassword": "required|string|same:newPassword" + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.user.id }}", + "operation": "validate", + "validator": "required" } }, { - "id": "fetch_user", - "type": "operation", - "op": "database_read", - "entity": "User", - "params": { - "filter": { - "id": "{{ $context.user.id }}", - "tenantId": "{{ $context.tenantId }}" + "id": "validate_input", + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "currentPassword": "required|string", + "newPassword": "required|string|minLength:8|different:currentPassword", + "confirmPassword": "required|string|same:newPassword" } } }, + { + "id": "fetch_user", + "name": "Fetch User", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "filter": { + "id": "{{ $context.user.id }}", + "tenantId": "{{ $context.tenantId }}" + }, + "operation": "database_read", + "entity": "User" + } + }, { "id": "verify_current_password", - "type": "operation", - "op": "crypto", - "operation": "bcrypt_compare", - "input": "{{ $json.currentPassword }}", - "hash": "{{ $steps.fetch_user.output.passwordHash }}" + "name": "Verify Current Password", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "input": "{{ $json.currentPassword }}", + "operation": "bcrypt_compare", + "hash": "{{ $steps.fetch_user.output.passwordHash }}" + } }, { "id": "check_password_correct", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.verify_current_password.output === true }}" + "name": "Check Password Correct", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "condition": "{{ $steps.verify_current_password.output === true }}", + "operation": "condition" + } }, { "id": "hash_new_password", - "type": "operation", - "op": "crypto", - "operation": "bcrypt_hash", - "input": "{{ $json.newPassword }}", - "rounds": 12 + "name": "Hash New Password", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "input": "{{ $json.newPassword }}", + "operation": "bcrypt_hash", + "rounds": 12 + } }, { "id": "update_password", - "type": "operation", - "op": "database_update", - "entity": "User", - "params": { + "name": "Update Password", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { "filter": { "id": "{{ $context.user.id }}" }, "data": { "passwordHash": "{{ $steps.hash_new_password.output }}", "passwordChangedAt": "{{ new Date().toISOString() }}" - } + }, + "operation": "database_update", + "entity": "User" } }, { "id": "invalidate_sessions", - "type": "operation", - "op": "database_delete_many", - "entity": "Session", - "params": { + "name": "Invalidate Sessions", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { "filter": { "userId": "{{ $context.user.id }}", "id": { "$ne": "{{ $context.sessionId }}" } - } + }, + "operation": "database_delete_many", + "entity": "Session" } }, { "id": "send_confirmation_email", - "type": "operation", - "op": "email_send", - "to": "{{ $steps.fetch_user.output.email }}", - "subject": "Your password has been changed", - "template": "password_changed", - "data": { - "displayName": "{{ $steps.fetch_user.output.displayName }}", - "timestamp": "{{ new Date().toISOString() }}" + "name": "Send Confirmation Email", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 500 + ], + "parameters": { + "data": { + "displayName": "{{ $steps.fetch_user.output.displayName }}", + "timestamp": "{{ new Date().toISOString() }}" + }, + "operation": "email_send", + "to": "{{ $steps.fetch_user.output.email }}", + "subject": "Your password has been changed", + "template": "password_changed" } }, { "id": "emit_event", - "type": "action", - "action": "emit_event", - "event": "password_changed", - "channel": "{{ 'user:' + $context.user.id }}", - "data": { - "timestamp": "{{ new Date().toISOString() }}" + "name": "Emit Event", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 700 + ], + "parameters": { + "data": { + "timestamp": "{{ new Date().toISOString() }}" + }, + "action": "emit_event", + "event": "password_changed", + "channel": "{{ 'user:' + $context.user.id }}" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": { - "message": "Password changed successfully. All other sessions have been invalidated for security." + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 700 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": { + "message": "Password changed successfully. All other sessions have been invalidated for security." + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Change password for authenticated user with old password verification" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/ui_auth/workflow/password-reset-workflow.backup.jsonscript b/packages/ui_auth/workflow/password-reset-workflow.backup.jsonscript new file mode 100644 index 000000000..7bee95643 --- /dev/null +++ b/packages/ui_auth/workflow/password-reset-workflow.backup.jsonscript @@ -0,0 +1,103 @@ +{ + "version": "2.2.0", + "name": "Password Reset Workflow", + "description": "Initiate password reset via email with secure token", + "trigger": { + "type": "http", + "method": "POST", + "path": "/auth/forgot-password" + }, + "nodes": [ + { + "id": "apply_rate_limit", + "type": "operation", + "op": "rate_limit", + "key": "{{ $json.email }}", + "limit": 3, + "window": 3600000 + }, + { + "id": "validate_email", + "type": "operation", + "op": "validate", + "input": "{{ $json }}", + "rules": { + "email": "required|email" + } + }, + { + "id": "fetch_user", + "type": "operation", + "op": "database_read", + "entity": "User", + "params": { + "filter": { + "email": "{{ $json.email }}" + } + } + }, + { + "id": "check_user_exists", + "type": "operation", + "op": "condition", + "condition": "{{ $steps.fetch_user.output !== null }}" + }, + { + "id": "generate_reset_token", + "type": "operation", + "op": "crypto", + "operation": "generate_random_token", + "length": 32 + }, + { + "id": "hash_reset_token", + "type": "operation", + "op": "crypto", + "operation": "sha256", + "input": "{{ $steps.generate_reset_token.output }}" + }, + { + "id": "create_reset_request", + "type": "operation", + "op": "database_create", + "entity": "PasswordResetToken", + "data": { + "userId": "{{ $steps.fetch_user.output.id }}", + "token": "{{ $steps.hash_reset_token.output }}", + "expiresAt": "{{ new Date(Date.now() + 60 * 60 * 1000).toISOString() }}" + } + }, + { + "id": "send_reset_email", + "type": "operation", + "op": "email_send", + "to": "{{ $json.email }}", + "subject": "Reset your password", + "template": "password_reset", + "data": { + "displayName": "{{ $steps.fetch_user.output.displayName }}", + "resetLink": "{{ $env.APP_URL }}/auth/reset-password/{{ $steps.generate_reset_token.output }}", + "expiresIn": "1 hour" + } + }, + { + "id": "emit_event", + "type": "action", + "action": "emit_event", + "event": "password_reset_requested", + "channel": "{{ 'user:' + $steps.fetch_user.output.id }}", + "data": { + "email": "{{ $json.email }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": { + "message": "If an account exists with that email, a password reset link has been sent." + } + } + ] +} diff --git a/packages/ui_auth/workflow/password-reset-workflow.jsonscript b/packages/ui_auth/workflow/password-reset-workflow.jsonscript index 7bee95643..4b67fd7c0 100644 --- a/packages/ui_auth/workflow/password-reset-workflow.jsonscript +++ b/packages/ui_auth/workflow/password-reset-workflow.jsonscript @@ -1,103 +1,185 @@ { - "version": "2.2.0", "name": "Password Reset Workflow", - "description": "Initiate password reset via email with secure token", - "trigger": { - "type": "http", - "method": "POST", - "path": "/auth/forgot-password" - }, + "active": false, "nodes": [ { "id": "apply_rate_limit", - "type": "operation", - "op": "rate_limit", - "key": "{{ $json.email }}", - "limit": 3, - "window": 3600000 - }, - { - "id": "validate_email", - "type": "operation", - "op": "validate", - "input": "{{ $json }}", - "rules": { - "email": "required|email" + "name": "Apply Rate Limit", + "type": "metabuilder.rateLimit", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "operation": "rate_limit", + "key": "{{ $json.email }}", + "limit": 3, + "window": 3600000 } }, { - "id": "fetch_user", - "type": "operation", - "op": "database_read", - "entity": "User", - "params": { - "filter": { - "email": "{{ $json.email }}" + "id": "validate_email", + "name": "Validate Email", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "email": "required|email" } } }, + { + "id": "fetch_user", + "name": "Fetch User", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "filter": { + "email": "{{ $json.email }}" + }, + "operation": "database_read", + "entity": "User" + } + }, { "id": "check_user_exists", - "type": "operation", - "op": "condition", - "condition": "{{ $steps.fetch_user.output !== null }}" + "name": "Check User Exists", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "condition": "{{ $steps.fetch_user.output !== null }}", + "operation": "condition" + } }, { "id": "generate_reset_token", - "type": "operation", - "op": "crypto", - "operation": "generate_random_token", - "length": 32 + "name": "Generate Reset Token", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "operation": "generate_random_token", + "length": 32 + } }, { "id": "hash_reset_token", - "type": "operation", - "op": "crypto", - "operation": "sha256", - "input": "{{ $steps.generate_reset_token.output }}" + "name": "Hash Reset Token", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "input": "{{ $steps.generate_reset_token.output }}", + "operation": "sha256" + } }, { "id": "create_reset_request", - "type": "operation", - "op": "database_create", - "entity": "PasswordResetToken", - "data": { - "userId": "{{ $steps.fetch_user.output.id }}", - "token": "{{ $steps.hash_reset_token.output }}", - "expiresAt": "{{ new Date(Date.now() + 60 * 60 * 1000).toISOString() }}" + "name": "Create Reset Request", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "data": { + "userId": "{{ $steps.fetch_user.output.id }}", + "token": "{{ $steps.hash_reset_token.output }}", + "expiresAt": "{{ new Date(Date.now() + 60 * 60 * 1000).toISOString() }}" + }, + "operation": "database_create", + "entity": "PasswordResetToken" } }, { "id": "send_reset_email", - "type": "operation", - "op": "email_send", - "to": "{{ $json.email }}", - "subject": "Reset your password", - "template": "password_reset", - "data": { - "displayName": "{{ $steps.fetch_user.output.displayName }}", - "resetLink": "{{ $env.APP_URL }}/auth/reset-password/{{ $steps.generate_reset_token.output }}", - "expiresIn": "1 hour" + "name": "Send Reset Email", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { + "data": { + "displayName": "{{ $steps.fetch_user.output.displayName }}", + "resetLink": "{{ $env.APP_URL }}/auth/reset-password/{{ $steps.generate_reset_token.output }}", + "expiresIn": "1 hour" + }, + "operation": "email_send", + "to": "{{ $json.email }}", + "subject": "Reset your password", + "template": "password_reset" } }, { "id": "emit_event", - "type": "action", - "action": "emit_event", - "event": "password_reset_requested", - "channel": "{{ 'user:' + $steps.fetch_user.output.id }}", - "data": { - "email": "{{ $json.email }}" + "name": "Emit Event", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 500 + ], + "parameters": { + "data": { + "email": "{{ $json.email }}" + }, + "action": "emit_event", + "event": "password_reset_requested", + "channel": "{{ 'user:' + $steps.fetch_user.output.id }}" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 200, - "body": { - "message": "If an account exists with that email, a password reset link has been sent." + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 700 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": { + "message": "If an account exists with that email, a password reset link has been sent." + } } } - ] + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Initiate password reset via email with secure token" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/ui_auth/workflow/register-workflow.backup.jsonscript b/packages/ui_auth/workflow/register-workflow.backup.jsonscript new file mode 100644 index 000000000..f94794359 --- /dev/null +++ b/packages/ui_auth/workflow/register-workflow.backup.jsonscript @@ -0,0 +1,109 @@ +{ + "version": "2.2.0", + "name": "Register Workflow", + "description": "User registration with validation, password hashing, and email verification", + "trigger": { + "type": "http", + "method": "POST", + "path": "/auth/register" + }, + "nodes": [ + { + "id": "apply_rate_limit", + "type": "operation", + "op": "rate_limit", + "key": "{{ $json.email }}", + "limit": 3, + "window": 3600000 + }, + { + "id": "validate_input", + "type": "operation", + "op": "validate", + "input": "{{ $json }}", + "rules": { + "email": "required|email|unique:User", + "password": "required|string|minLength:8|regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)/", + "displayName": "required|string|minLength:2|maxLength:100" + } + }, + { + "id": "hash_password", + "type": "operation", + "op": "crypto", + "operation": "bcrypt_hash", + "input": "{{ $json.password }}", + "rounds": 12 + }, + { + "id": "generate_verification_token", + "type": "operation", + "op": "crypto", + "operation": "generate_random_token", + "length": 32 + }, + { + "id": "create_user", + "type": "operation", + "op": "database_create", + "entity": "User", + "data": { + "email": "{{ $json.email }}", + "passwordHash": "{{ $steps.hash_password.output }}", + "displayName": "{{ $json.displayName }}", + "tenantId": "{{ $json.tenantId }}", + "level": 0, + "isActive": false, + "isEmailVerified": false, + "verificationToken": "{{ $steps.generate_verification_token.output }}", + "verificationTokenExpiresAt": "{{ new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() }}", + "firstLogin": true, + "createdAt": "{{ new Date().toISOString() }}" + } + }, + { + "id": "send_verification_email", + "type": "operation", + "op": "email_send", + "to": "{{ $json.email }}", + "subject": "Verify your email address", + "template": "email_verification", + "data": { + "displayName": "{{ $json.displayName }}", + "verificationLink": "{{ $env.APP_URL }}/auth/verify/{{ $steps.generate_verification_token.output }}" + } + }, + { + "id": "emit_register_event", + "type": "action", + "action": "emit_event", + "event": "user_registered", + "channel": "{{ 'tenant:' + $json.tenantId }}", + "data": { + "userId": "{{ $steps.create_user.output.id }}", + "email": "{{ $json.email }}", + "displayName": "{{ $json.displayName }}" + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 201, + "body": { + "message": "Registration successful. Please verify your email address.", + "userId": "{{ $steps.create_user.output.id }}", + "email": "{{ $json.email }}" + } + } + ], + "errorHandler": { + "type": "action", + "action": "http_response", + "status": 400, + "body": { + "error": "Registration failed", + "message": "{{ $error.message }}" + } + } +} diff --git a/packages/ui_auth/workflow/register-workflow.jsonscript b/packages/ui_auth/workflow/register-workflow.jsonscript index f94794359..30b3208f0 100644 --- a/packages/ui_auth/workflow/register-workflow.jsonscript +++ b/packages/ui_auth/workflow/register-workflow.jsonscript @@ -1,109 +1,168 @@ { - "version": "2.2.0", "name": "Register Workflow", - "description": "User registration with validation, password hashing, and email verification", - "trigger": { - "type": "http", - "method": "POST", - "path": "/auth/register" - }, + "active": false, "nodes": [ { "id": "apply_rate_limit", - "type": "operation", - "op": "rate_limit", - "key": "{{ $json.email }}", - "limit": 3, - "window": 3600000 + "name": "Apply Rate Limit", + "type": "metabuilder.rateLimit", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "operation": "rate_limit", + "key": "{{ $json.email }}", + "limit": 3, + "window": 3600000 + } }, { "id": "validate_input", - "type": "operation", - "op": "validate", - "input": "{{ $json }}", - "rules": { - "email": "required|email|unique:User", - "password": "required|string|minLength:8|regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)/", - "displayName": "required|string|minLength:2|maxLength:100" + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "email": "required|email|unique:User", + "password": "required|string|minLength:8|regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)/", + "displayName": "required|string|minLength:2|maxLength:100" + } } }, { "id": "hash_password", - "type": "operation", - "op": "crypto", - "operation": "bcrypt_hash", - "input": "{{ $json.password }}", - "rounds": 12 + "name": "Hash Password", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "input": "{{ $json.password }}", + "operation": "bcrypt_hash", + "rounds": 12 + } }, { "id": "generate_verification_token", - "type": "operation", - "op": "crypto", - "operation": "generate_random_token", - "length": 32 + "name": "Generate Verification Token", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "operation": "generate_random_token", + "length": 32 + } }, { "id": "create_user", - "type": "operation", - "op": "database_create", - "entity": "User", - "data": { - "email": "{{ $json.email }}", - "passwordHash": "{{ $steps.hash_password.output }}", - "displayName": "{{ $json.displayName }}", - "tenantId": "{{ $json.tenantId }}", - "level": 0, - "isActive": false, - "isEmailVerified": false, - "verificationToken": "{{ $steps.generate_verification_token.output }}", - "verificationTokenExpiresAt": "{{ new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() }}", - "firstLogin": true, - "createdAt": "{{ new Date().toISOString() }}" + "name": "Create User", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "data": { + "email": "{{ $json.email }}", + "passwordHash": "{{ $steps.hash_password.output }}", + "displayName": "{{ $json.displayName }}", + "tenantId": "{{ $json.tenantId }}", + "level": 0, + "isActive": false, + "isEmailVerified": false, + "verificationToken": "{{ $steps.generate_verification_token.output }}", + "verificationTokenExpiresAt": "{{ new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() }}", + "firstLogin": true, + "createdAt": "{{ new Date().toISOString() }}" + }, + "operation": "database_create", + "entity": "User" } }, { "id": "send_verification_email", - "type": "operation", - "op": "email_send", - "to": "{{ $json.email }}", - "subject": "Verify your email address", - "template": "email_verification", - "data": { - "displayName": "{{ $json.displayName }}", - "verificationLink": "{{ $env.APP_URL }}/auth/verify/{{ $steps.generate_verification_token.output }}" + "name": "Send Verification Email", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "data": { + "displayName": "{{ $json.displayName }}", + "verificationLink": "{{ $env.APP_URL }}/auth/verify/{{ $steps.generate_verification_token.output }}" + }, + "operation": "email_send", + "to": "{{ $json.email }}", + "subject": "Verify your email address", + "template": "email_verification" } }, { "id": "emit_register_event", - "type": "action", - "action": "emit_event", - "event": "user_registered", - "channel": "{{ 'tenant:' + $json.tenantId }}", - "data": { - "userId": "{{ $steps.create_user.output.id }}", - "email": "{{ $json.email }}", - "displayName": "{{ $json.displayName }}" + "name": "Emit Register Event", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "data": { + "userId": "{{ $steps.create_user.output.id }}", + "email": "{{ $json.email }}", + "displayName": "{{ $json.displayName }}" + }, + "action": "emit_event", + "event": "user_registered", + "channel": "{{ 'tenant:' + $json.tenantId }}" } }, { "id": "return_success", - "type": "action", - "action": "http_response", - "status": 201, - "body": { - "message": "Registration successful. Please verify your email address.", - "userId": "{{ $steps.create_user.output.id }}", - "email": "{{ $json.email }}" + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { + "action": "http_response", + "status": 201, + "body": { + "message": "Registration successful. Please verify your email address.", + "userId": "{{ $steps.create_user.output.id }}", + "email": "{{ $json.email }}" + } } } ], - "errorHandler": { - "type": "action", - "action": "http_response", - "status": 400, - "body": { - "error": "Registration failed", - "message": "{{ $error.message }}" - } + "connections": {}, + "staticData": {}, + "meta": { + "description": "User registration with validation, password hashing, and email verification" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" } } diff --git a/packages/ui_json_script_editor/workflow/import-script.backup.jsonscript b/packages/ui_json_script_editor/workflow/import-script.backup.jsonscript new file mode 100644 index 000000000..889031bbf --- /dev/null +++ b/packages/ui_json_script_editor/workflow/import-script.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"Import JSON Script","description":"Parse and import JSON Script from file","trigger":{"type":"http","method":"POST","path":"/json-editor/import"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.tenantId }}","validator":"required"},{"id":"check_permission","type":"operation","op":"condition","condition":"{{ $context.user.level >= 3 }}"},{"id":"parse_script","type":"operation","op":"transform_data","input":"{{ $json.fileContent }}","output":"{{ JSON.parse($json.fileContent) }}"},{"id":"validate_format","type":"operation","op":"condition","condition":"{{ $steps.parse_script.output.version === '2.2.0' }}"},{"id":"create_script","type":"operation","op":"database_create","entity":"JSONScript","data":{"tenantId":"{{ $context.tenantId }}","createdBy":"{{ $context.user.id }}","name":"{{ $json.name || 'Imported Script' }}","script":"{{ JSON.stringify($steps.parse_script.output) }}","createdAt":"{{ new Date().toISOString() }}"}},{"id":"return_success","type":"action","action":"http_response","status":201,"body":{"id":"{{ $steps.create_script.output.id }}","message":"Script imported"}}] +} diff --git a/packages/ui_json_script_editor/workflow/import-script.jsonscript b/packages/ui_json_script_editor/workflow/import-script.jsonscript index 889031bbf..ff53c56f0 100644 --- a/packages/ui_json_script_editor/workflow/import-script.jsonscript +++ b/packages/ui_json_script_editor/workflow/import-script.jsonscript @@ -1,3 +1,115 @@ { - "version":"2.2.0","name":"Import JSON Script","description":"Parse and import JSON Script from file","trigger":{"type":"http","method":"POST","path":"/json-editor/import"},"nodes":[{"id":"validate_context","type":"operation","op":"validate","input":"{{ $context.tenantId }}","validator":"required"},{"id":"check_permission","type":"operation","op":"condition","condition":"{{ $context.user.level >= 3 }}"},{"id":"parse_script","type":"operation","op":"transform_data","input":"{{ $json.fileContent }}","output":"{{ JSON.parse($json.fileContent) }}"},{"id":"validate_format","type":"operation","op":"condition","condition":"{{ $steps.parse_script.output.version === '2.2.0' }}"},{"id":"create_script","type":"operation","op":"database_create","entity":"JSONScript","data":{"tenantId":"{{ $context.tenantId }}","createdBy":"{{ $context.user.id }}","name":"{{ $json.name || 'Imported Script' }}","script":"{{ JSON.stringify($steps.parse_script.output) }}","createdAt":"{{ new Date().toISOString() }}"}},{"id":"return_success","type":"action","action":"http_response","status":201,"body":{"id":"{{ $steps.create_script.output.id }}","message":"Script imported"}}] + "name": "Import JSON Script", + "active": false, + "nodes": [ + { + "id": "validate_context", + "name": "Validate Context", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $context.tenantId }}", + "operation": "validate", + "validator": "required" + } + }, + { + "id": "check_permission", + "name": "Check Permission", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "condition": "{{ $context.user.level >= 3 }}", + "operation": "condition" + } + }, + { + "id": "parse_script", + "name": "Parse Script", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "input": "{{ $json.fileContent }}", + "output": "{{ JSON.parse($json.fileContent) }}", + "operation": "transform_data" + } + }, + { + "id": "validate_format", + "name": "Validate Format", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "condition": "{{ $steps.parse_script.output.version === '2.2.0' }}", + "operation": "condition" + } + }, + { + "id": "create_script", + "name": "Create Script", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "data": { + "tenantId": "{{ $context.tenantId }}", + "createdBy": "{{ $context.user.id }}", + "name": "{{ $json.name || 'Imported Script' }}", + "script": "{{ JSON.stringify($steps.parse_script.output) }}", + "createdAt": "{{ new Date().toISOString() }}" + }, + "operation": "database_create", + "entity": "JSONScript" + } + }, + { + "id": "return_success", + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "action": "http_response", + "status": 201, + "body": { + "id": "{{ $steps.create_script.output.id }}", + "message": "Script imported" + } + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Parse and import JSON Script from file" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/ui_json_script_editor/workflow/save-script.backup.jsonscript b/packages/ui_json_script_editor/workflow/save-script.backup.jsonscript new file mode 100644 index 000000000..b360f6f66 --- /dev/null +++ b/packages/ui_json_script_editor/workflow/save-script.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"Save JSON Script","description":"Save JSON Script with permission checks (god/supergod only)","trigger":{"type":"http","method":"POST","path":"/json-editor/save"},"nodes":[{"id":"check_permission","type":"operation","op":"condition","condition":"{{ $context.user.level >= 3 }}"},{"id":"validate_input","type":"operation","op":"validate","input":"{{ $json }}","rules":{"name":"required|string","script":"required|string"}},{"id":"create_script","type":"operation","op":"database_create","entity":"JSONScript","data":{"tenantId":"{{ $context.tenantId }}","createdBy":"{{ $context.user.id }}","name":"{{ $json.name }}","description":"{{ $json.description }}","script":"{{ $json.script }}","createdAt":"{{ new Date().toISOString() }}"}},{"id":"return_success","type":"action","action":"http_response","status":201,"body":{"id":"{{ $steps.create_script.output.id }}","message":"Script saved"}}] +} diff --git a/packages/ui_json_script_editor/workflow/save-script.jsonscript b/packages/ui_json_script_editor/workflow/save-script.jsonscript index b360f6f66..cbb397090 100644 --- a/packages/ui_json_script_editor/workflow/save-script.jsonscript +++ b/packages/ui_json_script_editor/workflow/save-script.jsonscript @@ -1,3 +1,90 @@ { - "version":"2.2.0","name":"Save JSON Script","description":"Save JSON Script with permission checks (god/supergod only)","trigger":{"type":"http","method":"POST","path":"/json-editor/save"},"nodes":[{"id":"check_permission","type":"operation","op":"condition","condition":"{{ $context.user.level >= 3 }}"},{"id":"validate_input","type":"operation","op":"validate","input":"{{ $json }}","rules":{"name":"required|string","script":"required|string"}},{"id":"create_script","type":"operation","op":"database_create","entity":"JSONScript","data":{"tenantId":"{{ $context.tenantId }}","createdBy":"{{ $context.user.id }}","name":"{{ $json.name }}","description":"{{ $json.description }}","script":"{{ $json.script }}","createdAt":"{{ new Date().toISOString() }}"}},{"id":"return_success","type":"action","action":"http_response","status":201,"body":{"id":"{{ $steps.create_script.output.id }}","message":"Script saved"}}] + "name": "Save JSON Script", + "active": false, + "nodes": [ + { + "id": "check_permission", + "name": "Check Permission", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "condition": "{{ $context.user.level >= 3 }}", + "operation": "condition" + } + }, + { + "id": "validate_input", + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "name": "required|string", + "script": "required|string" + } + } + }, + { + "id": "create_script", + "name": "Create Script", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "data": { + "tenantId": "{{ $context.tenantId }}", + "createdBy": "{{ $context.user.id }}", + "name": "{{ $json.name }}", + "description": "{{ $json.description }}", + "script": "{{ $json.script }}", + "createdAt": "{{ new Date().toISOString() }}" + }, + "operation": "database_create", + "entity": "JSONScript" + } + }, + { + "id": "return_success", + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "action": "http_response", + "status": 201, + "body": { + "id": "{{ $steps.create_script.output.id }}", + "message": "Script saved" + } + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Save JSON Script with permission checks (god/supergod only)" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/ui_json_script_editor/workflow/validate-script.backup.jsonscript b/packages/ui_json_script_editor/workflow/validate-script.backup.jsonscript new file mode 100644 index 000000000..3c235ab3e --- /dev/null +++ b/packages/ui_json_script_editor/workflow/validate-script.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"Validate JSON Script","description":"Validate JSON Script v2.2.0 format and syntax","trigger":{"type":"http","method":"POST","path":"/json-editor/validate"},"nodes":[{"id":"validate_input","type":"operation","op":"validate","input":"{{ $json }}","rules":{"script":"required|string"}},{"id":"parse_json","type":"operation","op":"transform_data","input":"{{ $json.script }}","output":"{{ JSON.parse($json.script) }}"},{"id":"validate_version","type":"operation","op":"condition","condition":"{{ $steps.parse_json.output.version === '2.2.0' }}"},{"id":"validate_nodes","type":"operation","op":"condition","condition":"{{ Array.isArray($steps.parse_json.output.nodes) && $steps.parse_json.output.nodes.length > 0 }}"},{"id":"validate_node_structure","type":"operation","op":"transform_data","output":"{{ $steps.parse_json.output.nodes.every(node => node.id && node.type) }}"},{"id":"return_valid","type":"action","action":"http_response","status":200,"body":{"valid":true,"message":"Script is valid"}}] +} diff --git a/packages/ui_json_script_editor/workflow/validate-script.jsonscript b/packages/ui_json_script_editor/workflow/validate-script.jsonscript index 3c235ab3e..e6dac1f0e 100644 --- a/packages/ui_json_script_editor/workflow/validate-script.jsonscript +++ b/packages/ui_json_script_editor/workflow/validate-script.jsonscript @@ -1,3 +1,110 @@ { - "version":"2.2.0","name":"Validate JSON Script","description":"Validate JSON Script v2.2.0 format and syntax","trigger":{"type":"http","method":"POST","path":"/json-editor/validate"},"nodes":[{"id":"validate_input","type":"operation","op":"validate","input":"{{ $json }}","rules":{"script":"required|string"}},{"id":"parse_json","type":"operation","op":"transform_data","input":"{{ $json.script }}","output":"{{ JSON.parse($json.script) }}"},{"id":"validate_version","type":"operation","op":"condition","condition":"{{ $steps.parse_json.output.version === '2.2.0' }}"},{"id":"validate_nodes","type":"operation","op":"condition","condition":"{{ Array.isArray($steps.parse_json.output.nodes) && $steps.parse_json.output.nodes.length > 0 }}"},{"id":"validate_node_structure","type":"operation","op":"transform_data","output":"{{ $steps.parse_json.output.nodes.every(node => node.id && node.type) }}"},{"id":"return_valid","type":"action","action":"http_response","status":200,"body":{"valid":true,"message":"Script is valid"}}] + "name": "Validate JSON Script", + "active": false, + "nodes": [ + { + "id": "validate_input", + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "script": "required|string" + } + } + }, + { + "id": "parse_json", + "name": "Parse Json", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json.script }}", + "output": "{{ JSON.parse($json.script) }}", + "operation": "transform_data" + } + }, + { + "id": "validate_version", + "name": "Validate Version", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "condition": "{{ $steps.parse_json.output.version === '2.2.0' }}", + "operation": "condition" + } + }, + { + "id": "validate_nodes", + "name": "Validate Nodes", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "condition": "{{ Array.isArray($steps.parse_json.output.nodes) && $steps.parse_json.output.nodes.length > 0 }}", + "operation": "condition" + } + }, + { + "id": "validate_node_structure", + "name": "Validate Node Structure", + "type": "metabuilder.transform", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "output": "{{ $steps.parse_json.output.nodes.every(node => node.id && node.type) }}", + "operation": "transform_data" + } + }, + { + "id": "return_valid", + "name": "Return Valid", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": { + "valid": true, + "message": "Script is valid" + } + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Validate JSON Script v2.2.0 format and syntax" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/user_manager/workflow/create-user.backup.jsonscript b/packages/user_manager/workflow/create-user.backup.jsonscript new file mode 100644 index 000000000..d492ee8d0 --- /dev/null +++ b/packages/user_manager/workflow/create-user.backup.jsonscript @@ -0,0 +1,3 @@ +{ + "version":"2.2.0","name":"Create User","description":"Create new user with email verification","trigger":{"type":"http","method":"POST","path":"/users"},"nodes":[{"id":"check_permission","type":"operation","op":"condition","condition":"{{ $context.user.level >= 3 }}"},{"id":"validate_input","type":"operation","op":"validate","input":"{{ $json }}","rules":{"email":"required|email|unique:User","displayName":"required|string"}},{"id":"hash_password","type":"operation","op":"crypto","operation":"bcrypt_hash","input":"{{ $json.password || $utils.generateSecurePassword() }}","rounds":12},{"id":"create_user","type":"operation","op":"database_create","entity":"User","data":{"email":"{{ $json.email }}","displayName":"{{ $json.displayName }}","passwordHash":"{{ $steps.hash_password.output }}","tenantId":"{{ $context.tenantId }}","level":"{{ $json.level || 0 }}","isActive":true}},{"id":"send_welcome_email","type":"operation","op":"email_send","to":"{{ $json.email }}","subject":"Welcome","template":"user_welcome"},{"id":"return_success","type":"action","action":"http_response","status":201,"body":{"id":"{{ $steps.create_user.output.id }}","email":"{{ $json.email }}"}}] +} diff --git a/packages/user_manager/workflow/create-user.jsonscript b/packages/user_manager/workflow/create-user.jsonscript index d492ee8d0..e09959f0c 100644 --- a/packages/user_manager/workflow/create-user.jsonscript +++ b/packages/user_manager/workflow/create-user.jsonscript @@ -1,3 +1,121 @@ { - "version":"2.2.0","name":"Create User","description":"Create new user with email verification","trigger":{"type":"http","method":"POST","path":"/users"},"nodes":[{"id":"check_permission","type":"operation","op":"condition","condition":"{{ $context.user.level >= 3 }}"},{"id":"validate_input","type":"operation","op":"validate","input":"{{ $json }}","rules":{"email":"required|email|unique:User","displayName":"required|string"}},{"id":"hash_password","type":"operation","op":"crypto","operation":"bcrypt_hash","input":"{{ $json.password || $utils.generateSecurePassword() }}","rounds":12},{"id":"create_user","type":"operation","op":"database_create","entity":"User","data":{"email":"{{ $json.email }}","displayName":"{{ $json.displayName }}","passwordHash":"{{ $steps.hash_password.output }}","tenantId":"{{ $context.tenantId }}","level":"{{ $json.level || 0 }}","isActive":true}},{"id":"send_welcome_email","type":"operation","op":"email_send","to":"{{ $json.email }}","subject":"Welcome","template":"user_welcome"},{"id":"return_success","type":"action","action":"http_response","status":201,"body":{"id":"{{ $steps.create_user.output.id }}","email":"{{ $json.email }}"}}] + "name": "Create User", + "active": false, + "nodes": [ + { + "id": "check_permission", + "name": "Check Permission", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "condition": "{{ $context.user.level >= 3 }}", + "operation": "condition" + } + }, + { + "id": "validate_input", + "name": "Validate Input", + "type": "metabuilder.validate", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "input": "{{ $json }}", + "operation": "validate", + "rules": { + "email": "required|email|unique:User", + "displayName": "required|string" + } + } + }, + { + "id": "hash_password", + "name": "Hash Password", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "input": "{{ $json.password || $utils.generateSecurePassword() }}", + "operation": "bcrypt_hash", + "rounds": 12 + } + }, + { + "id": "create_user", + "name": "Create User", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "data": { + "email": "{{ $json.email }}", + "displayName": "{{ $json.displayName }}", + "passwordHash": "{{ $steps.hash_password.output }}", + "tenantId": "{{ $context.tenantId }}", + "level": "{{ $json.level || 0 }}", + "isActive": true + }, + "operation": "database_create", + "entity": "User" + } + }, + { + "id": "send_welcome_email", + "name": "Send Welcome Email", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "operation": "email_send", + "to": "{{ $json.email }}", + "subject": "Welcome", + "template": "user_welcome" + } + }, + { + "id": "return_success", + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "action": "http_response", + "status": 201, + "body": { + "id": "{{ $steps.create_user.output.id }}", + "email": "{{ $json.email }}" + } + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Create new user with email verification" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/packages/user_manager/workflow/update-user.backup.jsonscript b/packages/user_manager/workflow/update-user.backup.jsonscript new file mode 100644 index 000000000..e8b268ea2 --- /dev/null +++ b/packages/user_manager/workflow/update-user.backup.jsonscript @@ -0,0 +1,53 @@ +{ + "version": "2.2.0", + "name": "Update User", + "description": "Update user information with tenant safety checks", + "trigger": { + "type": "http", + "method": "PUT", + "path": "/users/:userId" + }, + "nodes": [ + { + "id": "check_permission", + "type": "operation", + "op": "condition", + "condition": "{{ $context.user.level >= 3 || $context.user.id === $json.userId }}" + }, + { + "id": "fetch_user", + "type": "operation", + "op": "database_read", + "entity": "User", + "params": { + "filter": { + "id": "{{ $json.userId }}", + "tenantId": "{{ $context.tenantId }}" + } + } + }, + { + "id": "update_user", + "type": "operation", + "op": "database_update", + "entity": "User", + "params": { + "filter": { + "id": "{{ $json.userId }}" + }, + "data": { + "displayName": "{{ $json.displayName || $steps.fetch_user.output.displayName }}", + "level": "{{ $context.user.level >= 3 ? ($json.level || $steps.fetch_user.output.level) : $steps.fetch_user.output.level }}", + "isActive": "{{ $json.isActive !== undefined ? $json.isActive : $steps.fetch_user.output.isActive }}" + } + } + }, + { + "id": "return_success", + "type": "action", + "action": "http_response", + "status": 200, + "body": "{{ $steps.update_user.output }}" + } + ] +} diff --git a/packages/user_manager/workflow/update-user.jsonscript b/packages/user_manager/workflow/update-user.jsonscript index 7f415eca5..70662e3d5 100644 --- a/packages/user_manager/workflow/update-user.jsonscript +++ b/packages/user_manager/workflow/update-user.jsonscript @@ -1,3 +1,87 @@ { - "version":"2.2.0","name":"Update User","description":"Update user information with tenant safety checks","trigger":{"type":"http","method":"PUT","path":"/users/:userId"},"nodes":[{"id":"check_permission","type":"operation","op":"condition","condition":"{{ $context.user.level >= 3 || $context.user.id === $json.userId }}"},{"id":"fetch_user","type":"operation","op":"database_read","entity":"User","params":{"filter":{"id":"{{ $json.userId }}","tenantId":"{{ $context.tenantId }}"}}},{"id":"update_user","type":"operation","op":"database_update","entity":"User","params":{"filter":{"id":"{{ $json.userId }}"},"data":{"displayName":"{{ $json.displayName || $steps.fetch_user.output.displayName }}","level":"{{ $context.user.level >= 3 ? ($json.level || $steps.fetch_user.output.level) : $steps.fetch_user.output.level }}","isActive":"{{ $json.isActive !== undefined ? $json.isActive : $steps.fetch_user.output.isActive }}"}}},{"id":"return_success","type":"action","action":"http_response","status":200,"body":"{{ $steps.update_user.output }}"}}] + "name": "Update User", + "active": false, + "nodes": [ + { + "id": "check_permission", + "name": "Check Permission", + "type": "metabuilder.condition", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "condition": "{{ $context.user.level >= 3 || $context.user.id === $json.userId }}", + "operation": "condition" + } + }, + { + "id": "fetch_user", + "name": "Fetch User", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "filter": { + "id": "{{ $json.userId }}", + "tenantId": "{{ $context.tenantId }}" + }, + "operation": "database_read", + "entity": "User" + } + }, + { + "id": "update_user", + "name": "Update User", + "type": "metabuilder.database", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "filter": { + "id": "{{ $json.userId }}" + }, + "data": { + "displayName": "{{ $json.displayName || $steps.fetch_user.output.displayName }}", + "level": "{{ $context.user.level >= 3 ? ($json.level || $steps.fetch_user.output.level) : $steps.fetch_user.output.level }}", + "isActive": "{{ $json.isActive !== undefined ? $json.isActive : $steps.fetch_user.output.isActive }}" + }, + "operation": "database_update", + "entity": "User" + } + }, + { + "id": "return_success", + "name": "Return Success", + "type": "metabuilder.action", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "action": "http_response", + "status": 200, + "body": "{{ $steps.update_user.output }}" + } + } + ], + "connections": {}, + "staticData": {}, + "meta": { + "description": "Update user information with tenant safety checks" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/scripts/migrate-workflows-to-n8n.ts b/scripts/migrate-workflows-to-n8n.ts index 2be600128..0bc9198f6 100644 --- a/scripts/migrate-workflows-to-n8n.ts +++ b/scripts/migrate-workflows-to-n8n.ts @@ -119,11 +119,14 @@ interface N8NWorkflow { * @example idToName('parse_body') → 'Parse Body' * @example idToName('create-app') → 'Create App' */ -function idToName(id: string): string { +function idToName(idInput: unknown): string { + // Handle non-string IDs + let id = typeof idInput === 'string' ? idInput : String(idInput ?? 'node') + return id .replace(/[_-]/g, ' ') .split(' ') - .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .map((word: string) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) .join(' ') } diff --git a/workflow/examples/cross-project-workflow.backup.json b/workflow/examples/cross-project-workflow.backup.json new file mode 100644 index 000000000..7ad68416b --- /dev/null +++ b/workflow/examples/cross-project-workflow.backup.json @@ -0,0 +1,123 @@ +{ + "version": "2.2.0", + "name": "cross-project-demo", + "description": "Demonstrates integration between multiple MetaBuilder standalone projects", + "nodes": [ + { + "id": "start", + "type": "trigger", + "op": "manual", + "description": "Manual trigger to start the workflow" + }, + { + "id": "check-postgres", + "type": "operation", + "op": "postgres.checkConnection", + "description": "Verify database is accessible", + "params": { + "host": "localhost", + "port": 5432, + "database": "metabuilder", + "user": "postgres" + } + }, + { + "id": "list-containers", + "type": "operation", + "op": "docker.listContainers", + "description": "Get running Docker containers", + "params": { + "all": false + } + }, + { + "id": "create-3d-model", + "type": "operation", + "op": "cadquery.box", + "description": "Create a sample 3D box model", + "params": { + "length": 100, + "width": 50, + "height": 25, + "outputPath": "/tmp/demo-box.step" + } + }, + { + "id": "run-mojo-benchmark", + "type": "operation", + "op": "mojo.runExample", + "description": "Run Mojo performance example", + "params": { + "example": "life/benchmark.mojo" + } + }, + { + "id": "aggregate-results", + "type": "operation", + "op": "transform", + "description": "Combine all results into a summary", + "params": { + "expression": { + "database": { + "connected": "{{ $nodes['check-postgres'].success }}", + "version": "{{ $nodes['check-postgres'].version }}" + }, + "docker": { + "containerCount": "{{ $nodes['list-containers'].containers.length }}", + "containers": "{{ $nodes['list-containers'].containers }}" + }, + "cadquery": { + "modelCreated": "{{ $nodes['create-3d-model'].success }}", + "outputPath": "{{ $nodes['create-3d-model'].outputPath }}" + }, + "mojo": { + "benchmarkRan": "{{ $nodes['run-mojo-benchmark'].success }}", + "executionTime": "{{ $nodes['run-mojo-benchmark'].executionTime }}" + } + } + } + }, + { + "id": "share-results", + "type": "operation", + "op": "pastebin.create", + "description": "Share results as a paste", + "params": { + "content": "{{ JSON.stringify($nodes['aggregate-results'].result, null, 2) }}", + "title": "Cross-Project Workflow Results", + "language": "json", + "expiresIn": "1d" + } + }, + { + "id": "send-notification", + "type": "operation", + "op": "smtp.sendEmail", + "description": "Email the results", + "params": { + "from": "workflow@metabuilder.local", + "to": "admin@example.com", + "subject": "Cross-Project Workflow Complete", + "body": "Workflow completed successfully.\n\nResults: {{ $nodes['share-results'].url }}\n\nSummary:\n- Database: {{ $nodes['check-postgres'].success ? 'Connected' : 'Failed' }}\n- Docker Containers: {{ $nodes['list-containers'].containers.length }}\n- 3D Model: {{ $nodes['create-3d-model'].success ? 'Created' : 'Failed' }}\n- Mojo Benchmark: {{ $nodes['run-mojo-benchmark'].executionTime }}ms" + } + } + ], + "connections": [ + { "from": "start", "to": "check-postgres" }, + { "from": "start", "to": "list-containers" }, + { "from": "start", "to": "create-3d-model" }, + { "from": "start", "to": "run-mojo-benchmark" }, + { "from": "check-postgres", "to": "aggregate-results" }, + { "from": "list-containers", "to": "aggregate-results" }, + { "from": "create-3d-model", "to": "aggregate-results" }, + { "from": "run-mojo-benchmark", "to": "aggregate-results" }, + { "from": "aggregate-results", "to": "share-results" }, + { "from": "share-results", "to": "send-notification" } + ], + "metadata": { + "author": "MetaBuilder", + "created": "2026-01-21", + "tags": ["demo", "cross-project", "integration"], + "projects": ["postgres", "docker", "cadquery", "mojo", "pastebin", "smtp"] + } +} diff --git a/workflow/examples/cross-project-workflow.json b/workflow/examples/cross-project-workflow.json index 7ad68416b..cce551e0e 100644 --- a/workflow/examples/cross-project-workflow.json +++ b/workflow/examples/cross-project-workflow.json @@ -1,62 +1,102 @@ { - "version": "2.2.0", "name": "cross-project-demo", - "description": "Demonstrates integration between multiple MetaBuilder standalone projects", + "active": false, "nodes": [ { "id": "start", - "type": "trigger", - "op": "manual", - "description": "Manual trigger to start the workflow" + "name": "Start", + "type": "metabuilder.trigger", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "operation": "manual" + }, + "notes": "Manual trigger to start the workflow", + "notesInFlow": false }, { "id": "check-postgres", - "type": "operation", - "op": "postgres.checkConnection", - "description": "Verify database is accessible", - "params": { + "name": "Check Postgres", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { "host": "localhost", "port": 5432, "database": "metabuilder", - "user": "postgres" - } + "user": "postgres", + "operation": "postgres.checkConnection" + }, + "notes": "Verify database is accessible", + "notesInFlow": false }, { "id": "list-containers", - "type": "operation", - "op": "docker.listContainers", - "description": "Get running Docker containers", - "params": { - "all": false - } + "name": "List Containers", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "all": false, + "operation": "docker.listContainers" + }, + "notes": "Get running Docker containers", + "notesInFlow": false }, { "id": "create-3d-model", - "type": "operation", - "op": "cadquery.box", - "description": "Create a sample 3D box model", - "params": { + "name": "Create 3d Model", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { "length": 100, "width": 50, "height": 25, - "outputPath": "/tmp/demo-box.step" - } + "outputPath": "/tmp/demo-box.step", + "operation": "cadquery.box" + }, + "notes": "Create a sample 3D box model", + "notesInFlow": false }, { "id": "run-mojo-benchmark", - "type": "operation", - "op": "mojo.runExample", - "description": "Run Mojo performance example", - "params": { - "example": "life/benchmark.mojo" - } + "name": "Run Mojo Benchmark", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "example": "life/benchmark.mojo", + "operation": "mojo.runExample" + }, + "notes": "Run Mojo performance example", + "notesInFlow": false }, { "id": "aggregate-results", - "type": "operation", - "op": "transform", - "description": "Combine all results into a summary", - "params": { + "name": "Aggregate Results", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { "expression": { "database": { "connected": "{{ $nodes['check-postgres'].success }}", @@ -74,50 +114,181 @@ "benchmarkRan": "{{ $nodes['run-mojo-benchmark'].success }}", "executionTime": "{{ $nodes['run-mojo-benchmark'].executionTime }}" } - } - } + }, + "operation": "transform" + }, + "notes": "Combine all results into a summary", + "notesInFlow": false }, { "id": "share-results", - "type": "operation", - "op": "pastebin.create", - "description": "Share results as a paste", - "params": { + "name": "Share Results", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { "content": "{{ JSON.stringify($nodes['aggregate-results'].result, null, 2) }}", "title": "Cross-Project Workflow Results", "language": "json", - "expiresIn": "1d" - } + "expiresIn": "1d", + "operation": "pastebin.create" + }, + "notes": "Share results as a paste", + "notesInFlow": false }, { "id": "send-notification", - "type": "operation", - "op": "smtp.sendEmail", - "description": "Email the results", - "params": { + "name": "Send Notification", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { "from": "workflow@metabuilder.local", "to": "admin@example.com", "subject": "Cross-Project Workflow Complete", - "body": "Workflow completed successfully.\n\nResults: {{ $nodes['share-results'].url }}\n\nSummary:\n- Database: {{ $nodes['check-postgres'].success ? 'Connected' : 'Failed' }}\n- Docker Containers: {{ $nodes['list-containers'].containers.length }}\n- 3D Model: {{ $nodes['create-3d-model'].success ? 'Created' : 'Failed' }}\n- Mojo Benchmark: {{ $nodes['run-mojo-benchmark'].executionTime }}ms" - } + "body": "Workflow completed successfully.\n\nResults: {{ $nodes['share-results'].url }}\n\nSummary:\n- Database: {{ $nodes['check-postgres'].success ? 'Connected' : 'Failed' }}\n- Docker Containers: {{ $nodes['list-containers'].containers.length }}\n- 3D Model: {{ $nodes['create-3d-model'].success ? 'Created' : 'Failed' }}\n- Mojo Benchmark: {{ $nodes['run-mojo-benchmark'].executionTime }}ms", + "operation": "smtp.sendEmail" + }, + "notes": "Email the results", + "notesInFlow": false } ], - "connections": [ - { "from": "start", "to": "check-postgres" }, - { "from": "start", "to": "list-containers" }, - { "from": "start", "to": "create-3d-model" }, - { "from": "start", "to": "run-mojo-benchmark" }, - { "from": "check-postgres", "to": "aggregate-results" }, - { "from": "list-containers", "to": "aggregate-results" }, - { "from": "create-3d-model", "to": "aggregate-results" }, - { "from": "run-mojo-benchmark", "to": "aggregate-results" }, - { "from": "aggregate-results", "to": "share-results" }, - { "from": "share-results", "to": "send-notification" } - ], - "metadata": { + "connections": { + "Start": { + "main": { + "0": [ + { + "node": "Check Postgres", + "type": "main", + "index": 0 + }, + { + "node": "List Containers", + "type": "main", + "index": 0 + }, + { + "node": "Create 3d Model", + "type": "main", + "index": 0 + }, + { + "node": "Run Mojo Benchmark", + "type": "main", + "index": 0 + } + ] + } + }, + "Check Postgres": { + "main": { + "0": [ + { + "node": "Aggregate Results", + "type": "main", + "index": 0 + } + ] + } + }, + "List Containers": { + "main": { + "0": [ + { + "node": "Aggregate Results", + "type": "main", + "index": 0 + } + ] + } + }, + "Create 3d Model": { + "main": { + "0": [ + { + "node": "Aggregate Results", + "type": "main", + "index": 0 + } + ] + } + }, + "Run Mojo Benchmark": { + "main": { + "0": [ + { + "node": "Aggregate Results", + "type": "main", + "index": 0 + } + ] + } + }, + "Aggregate Results": { + "main": { + "0": [ + { + "node": "Share Results", + "type": "main", + "index": 0 + } + ] + } + }, + "Share Results": { + "main": { + "0": [ + { + "node": "Send Notification", + "type": "main", + "index": 0 + } + ] + } + } + }, + "staticData": {}, + "meta": { + "description": "Demonstrates integration between multiple MetaBuilder standalone projects", "author": "MetaBuilder", "created": "2026-01-21", - "tags": ["demo", "cross-project", "integration"], - "projects": ["postgres", "docker", "cadquery", "mojo", "pastebin", "smtp"] + "tags": [ + "demo", + "cross-project", + "integration" + ], + "projects": [ + "postgres", + "docker", + "cadquery", + "mojo", + "pastebin", + "smtp" + ] + }, + "tags": [ + { + "name": "demo" + }, + { + "name": "cross-project" + }, + { + "name": "integration" + } + ], + "createdAt": "2026-01-21T00:00:00.000Z", + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" } } diff --git a/workflow/examples/python/backend_bootstrap/workflow.backup.json b/workflow/examples/python/backend_bootstrap/workflow.backup.json new file mode 100644 index 000000000..dc81df058 --- /dev/null +++ b/workflow/examples/python/backend_bootstrap/workflow.backup.json @@ -0,0 +1,159 @@ +{ + "name": "Backend Bootstrap", + "active": false, + "nodes": [ + { + "id": "load_messages", + "name": "Load Messages", + "type": "backend.load_messages", + "typeVersion": 1, + "position": [0, 50], + "parameters": {} + }, + { + "id": "load_metadata", + "name": "Load Metadata", + "type": "backend.load_metadata", + "typeVersion": 1, + "position": [300, 50], + "parameters": {} + }, + { + "id": "load_prompt", + "name": "Load Prompt", + "type": "backend.load_prompt", + "typeVersion": 1, + "position": [600, 50], + "parameters": {} + }, + { + "id": "create_github", + "name": "Create GitHub Client", + "type": "backend.create_github", + "typeVersion": 1, + "position": [900, 50], + "parameters": {} + }, + { + "id": "create_openai", + "name": "Create OpenAI Client", + "type": "backend.create_openai", + "typeVersion": 1, + "position": [1200, 50], + "parameters": {} + }, + { + "id": "load_tools", + "name": "Load Tools", + "type": "backend.load_tools", + "typeVersion": 1, + "position": [1500, 50], + "parameters": {} + }, + { + "id": "build_tool_map", + "name": "Build Tool Map", + "type": "backend.build_tool_map", + "typeVersion": 1, + "position": [1800, 50], + "parameters": {} + }, + { + "id": "load_plugins", + "name": "Load Plugins", + "type": "backend.load_plugins", + "typeVersion": 1, + "position": [2100, 50], + "parameters": {} + } + ], + "connections": { + "Load Messages": { + "main": { + "0": [ + { + "node": "Load Metadata", + "type": "main", + "index": 0 + } + ] + } + }, + "Load Metadata": { + "main": { + "0": [ + { + "node": "Load Prompt", + "type": "main", + "index": 0 + } + ] + } + }, + "Load Prompt": { + "main": { + "0": [ + { + "node": "Create GitHub Client", + "type": "main", + "index": 0 + } + ] + } + }, + "Create GitHub Client": { + "main": { + "0": [ + { + "node": "Create OpenAI Client", + "type": "main", + "index": 0 + } + ] + } + }, + "Create OpenAI Client": { + "main": { + "0": [ + { + "node": "Load Tools", + "type": "main", + "index": 0 + } + ] + } + }, + "Load Tools": { + "main": { + "0": [ + { + "node": "Build Tool Map", + "type": "main", + "index": 0 + } + ] + } + }, + "Build Tool Map": { + "main": { + "0": [ + { + "node": "Load Plugins", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "load_messages", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Initialize backend services and dependencies" + } + } + ] +} diff --git a/workflow/examples/python/backend_bootstrap/workflow.json b/workflow/examples/python/backend_bootstrap/workflow.json index dc81df058..de14bc4b7 100644 --- a/workflow/examples/python/backend_bootstrap/workflow.json +++ b/workflow/examples/python/backend_bootstrap/workflow.json @@ -7,64 +7,152 @@ "name": "Load Messages", "type": "backend.load_messages", "typeVersion": 1, - "position": [0, 50], - "parameters": {} + "position": [ + 100, + 100 + ], + "parameters": { + "name": "Load Messages", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": {} + } }, { "id": "load_metadata", "name": "Load Metadata", "type": "backend.load_metadata", "typeVersion": 1, - "position": [300, 50], - "parameters": {} + "position": [ + 400, + 100 + ], + "parameters": { + "name": "Load Metadata", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": {} + } }, { "id": "load_prompt", "name": "Load Prompt", "type": "backend.load_prompt", "typeVersion": 1, - "position": [600, 50], - "parameters": {} + "position": [ + 700, + 100 + ], + "parameters": { + "name": "Load Prompt", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": {} + } }, { "id": "create_github", - "name": "Create GitHub Client", + "name": "Create Github", "type": "backend.create_github", "typeVersion": 1, - "position": [900, 50], - "parameters": {} + "position": [ + 100, + 300 + ], + "parameters": { + "name": "Create GitHub Client", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": {} + } }, { "id": "create_openai", - "name": "Create OpenAI Client", + "name": "Create Openai", "type": "backend.create_openai", "typeVersion": 1, - "position": [1200, 50], - "parameters": {} + "position": [ + 400, + 300 + ], + "parameters": { + "name": "Create OpenAI Client", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": {} + } }, { "id": "load_tools", "name": "Load Tools", "type": "backend.load_tools", "typeVersion": 1, - "position": [1500, 50], - "parameters": {} + "position": [ + 700, + 300 + ], + "parameters": { + "name": "Load Tools", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": {} + } }, { "id": "build_tool_map", "name": "Build Tool Map", "type": "backend.build_tool_map", "typeVersion": 1, - "position": [1800, 50], - "parameters": {} + "position": [ + 100, + 500 + ], + "parameters": { + "name": "Build Tool Map", + "typeVersion": 1, + "position": [ + 1800, + 50 + ], + "parameters": {} + } }, { "id": "load_plugins", "name": "Load Plugins", "type": "backend.load_plugins", "typeVersion": 1, - "position": [2100, 50], - "parameters": {} + "position": [ + 400, + 500 + ], + "parameters": { + "name": "Load Plugins", + "typeVersion": 1, + "position": [ + 2100, + 50 + ], + "parameters": {} + } } ], "connections": { @@ -72,7 +160,7 @@ "main": { "0": [ { - "node": "Load Metadata", + "node": "[object Object]", "type": "main", "index": 0 } @@ -83,7 +171,7 @@ "main": { "0": [ { - "node": "Load Prompt", + "node": "[object Object]", "type": "main", "index": 0 } @@ -94,29 +182,29 @@ "main": { "0": [ { - "node": "Create GitHub Client", + "node": "[object Object]", "type": "main", "index": 0 } ] } }, - "Create GitHub Client": { + "Create Github Client": { "main": { "0": [ { - "node": "Create OpenAI Client", + "node": "[object Object]", "type": "main", "index": 0 } ] } }, - "Create OpenAI Client": { + "Create Openai Client": { "main": { "0": [ { - "node": "Load Tools", + "node": "[object Object]", "type": "main", "index": 0 } @@ -127,7 +215,7 @@ "main": { "0": [ { - "node": "Build Tool Map", + "node": "[object Object]", "type": "main", "index": 0 } @@ -138,7 +226,7 @@ "main": { "0": [ { - "node": "Load Plugins", + "node": "[object Object]", "type": "main", "index": 0 } @@ -146,14 +234,13 @@ } } }, - "triggers": [ - { - "nodeId": "load_messages", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Initialize backend services and dependencies" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/blank/workflow.backup.json b/workflow/examples/python/blank/workflow.backup.json new file mode 100644 index 000000000..3f5108aa1 --- /dev/null +++ b/workflow/examples/python/blank/workflow.backup.json @@ -0,0 +1,18 @@ +{ + "name": "Blank Canvas", + "active": false, + "nodes": [ + { + "id": "start", + "name": "Start", + "type": "core.start", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": {} + } + ], + "connections": {} +} diff --git a/workflow/examples/python/blank/workflow.json b/workflow/examples/python/blank/workflow.json index 3f5108aa1..56f9644d7 100644 --- a/workflow/examples/python/blank/workflow.json +++ b/workflow/examples/python/blank/workflow.json @@ -8,11 +8,28 @@ "type": "core.start", "typeVersion": 1, "position": [ - 0, - 0 + 100, + 100 ], - "parameters": {} + "parameters": { + "name": "Start", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": {} + } } ], - "connections": {} + "connections": {}, + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/conditional_logic_demo/workflow.backup.json b/workflow/examples/python/conditional_logic_demo/workflow.backup.json new file mode 100644 index 000000000..3dad7412a --- /dev/null +++ b/workflow/examples/python/conditional_logic_demo/workflow.backup.json @@ -0,0 +1,116 @@ +{ + "name": "Conditional Logic Demo", + "active": false, + "nodes": [ + { + "id": "create_user_data", + "name": "Create User Data", + "type": "var.set", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "key": "user", + "value": { + "name": "Alice", + "age": 25, + "score": 85, + "role": "developer" + } + } + }, + { + "id": "extract_age", + "name": "Extract Age", + "type": "dict.get", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": { + "object": "$user", + "key": "age" + } + }, + { + "id": "check_adult", + "name": "Check If Adult", + "type": "logic.gte", + "typeVersion": 1, + "position": [ + 600, + 100 + ], + "parameters": { + "a": "$age", + "b": 18 + } + }, + { + "id": "format_report", + "name": "Format Final Report", + "type": "string.format", + "typeVersion": 1, + "position": [ + 900, + 100 + ], + "parameters": { + "template": "User: {name}, Age: {age}, Adult: {is_adult}", + "variables": { + "name": "Alice", + "age": "$age", + "is_adult": "$is_adult" + } + } + } + ], + "connections": { + "Create User Data": { + "main": { + "0": [ + { + "node": "Extract Age", + "type": "main", + "index": 0 + } + ] + } + }, + "Extract Age": { + "main": { + "0": [ + { + "node": "Check If Adult", + "type": "main", + "index": 0 + } + ] + } + }, + "Check If Adult": { + "main": { + "0": [ + { + "node": "Format Final Report", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "create_user_data", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered Conditional Logic Demo workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/conditional_logic_demo/workflow.json b/workflow/examples/python/conditional_logic_demo/workflow.json index 3dad7412a..49a2cedb5 100644 --- a/workflow/examples/python/conditional_logic_demo/workflow.json +++ b/workflow/examples/python/conditional_logic_demo/workflow.json @@ -8,16 +8,24 @@ "type": "var.set", "typeVersion": 1, "position": [ - 0, + 100, 100 ], "parameters": { - "key": "user", - "value": { - "name": "Alice", - "age": 25, - "score": 85, - "role": "developer" + "name": "Create User Data", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "key": "user", + "value": { + "name": "Alice", + "age": 25, + "score": 85, + "role": "developer" + } } } }, @@ -27,43 +35,67 @@ "type": "dict.get", "typeVersion": 1, "position": [ - 300, - 50 + 400, + 100 ], "parameters": { - "object": "$user", - "key": "age" + "name": "Extract Age", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": { + "object": "$user", + "key": "age" + } } }, { "id": "check_adult", - "name": "Check If Adult", + "name": "Check Adult", "type": "logic.gte", "typeVersion": 1, "position": [ - 600, + 700, 100 ], "parameters": { - "a": "$age", - "b": 18 + "name": "Check If Adult", + "typeVersion": 1, + "position": [ + 600, + 100 + ], + "parameters": { + "a": "$age", + "b": 18 + } } }, { "id": "format_report", - "name": "Format Final Report", + "name": "Format Report", "type": "string.format", "typeVersion": 1, "position": [ - 900, - 100 + 100, + 300 ], "parameters": { - "template": "User: {name}, Age: {age}, Adult: {is_adult}", - "variables": { - "name": "Alice", - "age": "$age", - "is_adult": "$is_adult" + "name": "Format Final Report", + "typeVersion": 1, + "position": [ + 900, + 100 + ], + "parameters": { + "template": "User: {name}, Age: {age}, Adult: {is_adult}", + "variables": { + "name": "Alice", + "age": "$age", + "is_adult": "$is_adult" + } } } } @@ -73,7 +105,7 @@ "main": { "0": [ { - "node": "Extract Age", + "node": "[object Object]", "type": "main", "index": 0 } @@ -84,7 +116,7 @@ "main": { "0": [ { - "node": "Check If Adult", + "node": "[object Object]", "type": "main", "index": 0 } @@ -95,7 +127,7 @@ "main": { "0": [ { - "node": "Format Final Report", + "node": "[object Object]", "type": "main", "index": 0 } @@ -103,14 +135,13 @@ } } }, - "triggers": [ - { - "nodeId": "create_user_data", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered Conditional Logic Demo workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/contextual_iterative_loop/workflow.backup.json b/workflow/examples/python/contextual_iterative_loop/workflow.backup.json new file mode 100644 index 000000000..d71c2e570 --- /dev/null +++ b/workflow/examples/python/contextual_iterative_loop/workflow.backup.json @@ -0,0 +1,187 @@ +{ + "name": "meta.workflow_packages.contextual_iterative_loop.label", + "active": false, + "nodes": [ + { + "id": "list_files", + "name": "List Files", + "type": "tools.list_files", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": { + "path": "." + } + }, + { + "id": "filter_python", + "name": "Filter Python", + "type": "utils.filter_list", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": { + "items": "$repo_files", + "mode": "regex", + "pattern": "\\.py$" + } + }, + { + "id": "map_python", + "name": "Map Python", + "type": "utils.map_list", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "items": "$python_files", + "template": "PY: {item}" + } + }, + { + "id": "reduce_python", + "name": "Reduce Python", + "type": "utils.reduce_list", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "items": "$python_lines", + "separator": "\\n" + } + }, + { + "id": "seed_messages", + "name": "Seed Messages", + "type": "core.seed_messages", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": {} + }, + { + "id": "append_repo_summary", + "name": "Append Repo Summary", + "type": "core.append_context_message", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": { + "messages": "$messages", + "context": "$python_summary" + } + }, + { + "id": "append_user_instruction", + "name": "Append User Instruction", + "type": "core.append_user_instruction", + "typeVersion": 1, + "position": [ + 1800, + 50 + ], + "parameters": { + "messages": "$messages" + } + }, + { + "id": "main_loop", + "name": "Main Loop", + "type": "control.loop", + "typeVersion": 1, + "position": [ + 2100, + 50 + ], + "parameters": { + "max_iterations": 5, + "stop_when": "$no_tool_calls", + "stop_on": "true" + } + } + ], + "connections": { + "List Files": { + "main": { + "0": [ + { + "node": "Filter Python", + "type": "main", + "index": 0 + } + ] + } + }, + "Filter Python": { + "main": { + "0": [ + { + "node": "Map Python", + "type": "main", + "index": 0 + } + ] + } + }, + "Map Python": { + "main": { + "0": [ + { + "node": "Reduce Python", + "type": "main", + "index": 0 + } + ] + } + }, + "Append User Instruction": { + "main": { + "0": [ + { + "node": "Append Repo Summary", + "type": "main", + "index": 0 + }, + { + "node": "Append User Instruction", + "type": "main", + "index": 0 + } + ] + } + }, + "Reduce Python": { + "main": { + "0": [ + { + "node": "Append Repo Summary", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "list_files", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered meta.workflow_packages.contextual_iterative_loop.label workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/contextual_iterative_loop/workflow.json b/workflow/examples/python/contextual_iterative_loop/workflow.json index d71c2e570..04ab6fd96 100644 --- a/workflow/examples/python/contextual_iterative_loop/workflow.json +++ b/workflow/examples/python/contextual_iterative_loop/workflow.json @@ -8,11 +8,19 @@ "type": "tools.list_files", "typeVersion": 1, "position": [ - 0, - 50 + 100, + 100 ], "parameters": { - "path": "." + "name": "List Files", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": { + "path": "." + } } }, { @@ -21,13 +29,21 @@ "type": "utils.filter_list", "typeVersion": 1, "position": [ - 300, - 50 + 400, + 100 ], "parameters": { - "items": "$repo_files", - "mode": "regex", - "pattern": "\\.py$" + "name": "Filter Python", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": { + "items": "$repo_files", + "mode": "regex", + "pattern": "\\.py$" + } } }, { @@ -36,12 +52,20 @@ "type": "utils.map_list", "typeVersion": 1, "position": [ - 600, - 50 + 700, + 100 ], "parameters": { - "items": "$python_files", - "template": "PY: {item}" + "name": "Map Python", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "items": "$python_files", + "template": "PY: {item}" + } } }, { @@ -50,12 +74,20 @@ "type": "utils.reduce_list", "typeVersion": 1, "position": [ - 900, - 50 + 100, + 300 ], "parameters": { - "items": "$python_lines", - "separator": "\\n" + "name": "Reduce Python", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "items": "$python_lines", + "separator": "\\n" + } } }, { @@ -64,10 +96,18 @@ "type": "core.seed_messages", "typeVersion": 1, "position": [ - 1200, - 50 + 400, + 300 ], - "parameters": {} + "parameters": { + "name": "Seed Messages", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": {} + } }, { "id": "append_repo_summary", @@ -75,12 +115,20 @@ "type": "core.append_context_message", "typeVersion": 1, "position": [ - 1500, - 50 + 700, + 300 ], "parameters": { - "messages": "$messages", - "context": "$python_summary" + "name": "Append Repo Summary", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": { + "messages": "$messages", + "context": "$python_summary" + } } }, { @@ -89,11 +137,19 @@ "type": "core.append_user_instruction", "typeVersion": 1, "position": [ - 1800, - 50 + 100, + 500 ], "parameters": { - "messages": "$messages" + "name": "Append User Instruction", + "typeVersion": 1, + "position": [ + 1800, + 50 + ], + "parameters": { + "messages": "$messages" + } } }, { @@ -102,13 +158,21 @@ "type": "control.loop", "typeVersion": 1, "position": [ - 2100, - 50 + 400, + 500 ], "parameters": { - "max_iterations": 5, - "stop_when": "$no_tool_calls", - "stop_on": "true" + "name": "Main Loop", + "typeVersion": 1, + "position": [ + 2100, + 50 + ], + "parameters": { + "max_iterations": 5, + "stop_when": "$no_tool_calls", + "stop_on": "true" + } } } ], @@ -117,7 +181,7 @@ "main": { "0": [ { - "node": "Filter Python", + "node": "[object Object]", "type": "main", "index": 0 } @@ -128,7 +192,7 @@ "main": { "0": [ { - "node": "Map Python", + "node": "[object Object]", "type": "main", "index": 0 } @@ -139,7 +203,7 @@ "main": { "0": [ { - "node": "Reduce Python", + "node": "[object Object]", "type": "main", "index": 0 } @@ -150,12 +214,7 @@ "main": { "0": [ { - "node": "Append Repo Summary", - "type": "main", - "index": 0 - }, - { - "node": "Append User Instruction", + "node": "[object Object]", "type": "main", "index": 0 } @@ -166,7 +225,7 @@ "main": { "0": [ { - "node": "Append Repo Summary", + "node": "[object Object]", "type": "main", "index": 0 } @@ -174,14 +233,13 @@ } } }, - "triggers": [ - { - "nodeId": "list_files", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered meta.workflow_packages.contextual_iterative_loop.label workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/data_processing_demo/workflow.backup.json b/workflow/examples/python/data_processing_demo/workflow.backup.json new file mode 100644 index 000000000..d92a3b5f8 --- /dev/null +++ b/workflow/examples/python/data_processing_demo/workflow.backup.json @@ -0,0 +1,253 @@ +{ + "name": "Data Processing Demo", + "active": false, + "nodes": [ + { + "id": "create_sample_data", + "name": "Create Sample Data", + "type": "var.set", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": { + "key": "numbers", + "value": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ] + } + }, + { + "id": "filter_even", + "name": "Filter Even Numbers", + "type": "utils.filter_list", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": { + "items": "$numbers", + "mode": "lambda", + "condition": "lambda x: x % 2 == 0" + } + }, + { + "id": "map_square", + "name": "Square Each Number", + "type": "utils.map_list", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "items": "$filtered_numbers", + "transform": "lambda x: x * x" + } + }, + { + "id": "reduce_sum", + "name": "Sum All Values", + "type": "math.add", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "numbers": "$squared_numbers" + } + }, + { + "id": "check_threshold", + "name": "Check If Sum > 50", + "type": "logic.gt", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": { + "a": "$sum", + "b": 50 + } + }, + { + "id": "branch_result", + "name": "Branch On Result", + "type": "utils.branch_condition", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": { + "condition": "$is_greater" + } + }, + { + "id": "format_success", + "name": "Format Success Message", + "type": "string.format", + "typeVersion": 1, + "position": [ + 1800, + 0 + ], + "parameters": { + "template": "Success! Sum is {sum}, which is greater than 50.", + "variables": { + "sum": "$sum" + } + } + }, + { + "id": "format_failure", + "name": "Format Failure Message", + "type": "string.format", + "typeVersion": 1, + "position": [ + 1800, + 100 + ], + "parameters": { + "template": "Sum is {sum}, which is not greater than 50.", + "variables": { + "sum": "$sum" + } + } + }, + { + "id": "store_result", + "name": "Store Final Result", + "type": "var.set", + "typeVersion": 1, + "position": [ + 2100, + 50 + ], + "parameters": { + "key": "final_message", + "value": "$message" + } + } + ], + "connections": { + "Create Sample Data": { + "main": { + "0": [ + { + "node": "Filter Even Numbers", + "type": "main", + "index": 0 + } + ] + } + }, + "Filter Even Numbers": { + "main": { + "0": [ + { + "node": "Square Each Number", + "type": "main", + "index": 0 + } + ] + } + }, + "Square Each Number": { + "main": { + "0": [ + { + "node": "Sum All Values", + "type": "main", + "index": 0 + } + ] + } + }, + "Sum All Values": { + "main": { + "0": [ + { + "node": "Check If Sum > 50", + "type": "main", + "index": 0 + } + ] + } + }, + "Check If Sum > 50": { + "main": { + "0": [ + { + "node": "Branch On Result", + "type": "main", + "index": 0 + } + ] + } + }, + "Branch On Result": { + "main": { + "0": [ + { + "node": "Format Success Message", + "type": "main", + "index": 0 + } + ], + "1": [ + { + "node": "Format Failure Message", + "type": "main", + "index": 0 + } + ] + } + }, + "Format Success Message": { + "main": { + "0": [ + { + "node": "Store Final Result", + "type": "main", + "index": 0 + } + ] + } + }, + "Format Failure Message": { + "main": { + "0": [ + { + "node": "Store Final Result", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "create_sample_data", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered Data Processing Demo workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/data_processing_demo/workflow.json b/workflow/examples/python/data_processing_demo/workflow.json index d92a3b5f8..06b17b3f9 100644 --- a/workflow/examples/python/data_processing_demo/workflow.json +++ b/workflow/examples/python/data_processing_demo/workflow.json @@ -8,138 +8,210 @@ "type": "var.set", "typeVersion": 1, "position": [ - 0, - 50 + 100, + 100 ], "parameters": { - "key": "numbers", - "value": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10 - ] + "name": "Create Sample Data", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": { + "key": "numbers", + "value": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ] + } } }, { "id": "filter_even", - "name": "Filter Even Numbers", + "name": "Filter Even", "type": "utils.filter_list", "typeVersion": 1, "position": [ - 300, - 50 + 400, + 100 ], "parameters": { - "items": "$numbers", - "mode": "lambda", - "condition": "lambda x: x % 2 == 0" + "name": "Filter Even Numbers", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": { + "items": "$numbers", + "mode": "lambda", + "condition": "lambda x: x % 2 == 0" + } } }, { "id": "map_square", - "name": "Square Each Number", + "name": "Map Square", "type": "utils.map_list", "typeVersion": 1, "position": [ - 600, - 50 + 700, + 100 ], "parameters": { - "items": "$filtered_numbers", - "transform": "lambda x: x * x" + "name": "Square Each Number", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "items": "$filtered_numbers", + "transform": "lambda x: x * x" + } } }, { "id": "reduce_sum", - "name": "Sum All Values", + "name": "Reduce Sum", "type": "math.add", "typeVersion": 1, "position": [ - 900, - 50 + 100, + 300 ], "parameters": { - "numbers": "$squared_numbers" + "name": "Sum All Values", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "numbers": "$squared_numbers" + } } }, { "id": "check_threshold", - "name": "Check If Sum > 50", + "name": "Check Threshold", "type": "logic.gt", "typeVersion": 1, "position": [ - 1200, - 50 + 400, + 300 ], "parameters": { - "a": "$sum", - "b": 50 + "name": "Check If Sum > 50", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": { + "a": "$sum", + "b": 50 + } } }, { "id": "branch_result", - "name": "Branch On Result", + "name": "Branch Result", "type": "utils.branch_condition", "typeVersion": 1, "position": [ - 1500, - 50 + 700, + 300 ], "parameters": { - "condition": "$is_greater" + "name": "Branch On Result", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": { + "condition": "$is_greater" + } } }, { "id": "format_success", - "name": "Format Success Message", + "name": "Format Success", "type": "string.format", "typeVersion": 1, "position": [ - 1800, - 0 + 100, + 500 ], "parameters": { - "template": "Success! Sum is {sum}, which is greater than 50.", - "variables": { - "sum": "$sum" + "name": "Format Success Message", + "typeVersion": 1, + "position": [ + 1800, + 0 + ], + "parameters": { + "template": "Success! Sum is {sum}, which is greater than 50.", + "variables": { + "sum": "$sum" + } } } }, { "id": "format_failure", - "name": "Format Failure Message", + "name": "Format Failure", "type": "string.format", "typeVersion": 1, "position": [ - 1800, - 100 + 400, + 500 ], "parameters": { - "template": "Sum is {sum}, which is not greater than 50.", - "variables": { - "sum": "$sum" + "name": "Format Failure Message", + "typeVersion": 1, + "position": [ + 1800, + 100 + ], + "parameters": { + "template": "Sum is {sum}, which is not greater than 50.", + "variables": { + "sum": "$sum" + } } } }, { "id": "store_result", - "name": "Store Final Result", + "name": "Store Result", "type": "var.set", "typeVersion": 1, "position": [ - 2100, - 50 + 700, + 500 ], "parameters": { - "key": "final_message", - "value": "$message" + "name": "Store Final Result", + "typeVersion": 1, + "position": [ + 2100, + 50 + ], + "parameters": { + "key": "final_message", + "value": "$message" + } } } ], @@ -148,7 +220,7 @@ "main": { "0": [ { - "node": "Filter Even Numbers", + "node": "[object Object]", "type": "main", "index": 0 } @@ -159,7 +231,7 @@ "main": { "0": [ { - "node": "Square Each Number", + "node": "[object Object]", "type": "main", "index": 0 } @@ -170,7 +242,7 @@ "main": { "0": [ { - "node": "Sum All Values", + "node": "[object Object]", "type": "main", "index": 0 } @@ -181,7 +253,7 @@ "main": { "0": [ { - "node": "Check If Sum > 50", + "node": "[object Object]", "type": "main", "index": 0 } @@ -192,7 +264,7 @@ "main": { "0": [ { - "node": "Branch On Result", + "node": "[object Object]", "type": "main", "index": 0 } @@ -203,14 +275,7 @@ "main": { "0": [ { - "node": "Format Success Message", - "type": "main", - "index": 0 - } - ], - "1": [ - { - "node": "Format Failure Message", + "node": "[object Object]", "type": "main", "index": 0 } @@ -221,7 +286,7 @@ "main": { "0": [ { - "node": "Store Final Result", + "node": "[object Object]", "type": "main", "index": 0 } @@ -232,7 +297,7 @@ "main": { "0": [ { - "node": "Store Final Result", + "node": "[object Object]", "type": "main", "index": 0 } @@ -240,14 +305,13 @@ } } }, - "triggers": [ - { - "nodeId": "create_sample_data", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered Data Processing Demo workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/default_app_workflow/workflow.backup.json b/workflow/examples/python/default_app_workflow/workflow.backup.json new file mode 100644 index 000000000..5900bb953 --- /dev/null +++ b/workflow/examples/python/default_app_workflow/workflow.backup.json @@ -0,0 +1,110 @@ +{ + "version": "2.2.0", + "name": "default_app_workflow", + "description": "Default application workflow with backend bootstrap and iterative AI loop", + "active": false, + "trigger": { + "type": "manual", + "node": "load_messages" + }, + "nodes": [ + { + "id": "load_messages", + "type": "operation", + "op": "load_messages", + "description": "Load initial messages from storage" + }, + { + "id": "load_metadata", + "type": "operation", + "op": "load_metadata", + "description": "Load workflow metadata and configuration" + }, + { + "id": "load_prompts", + "type": "operation", + "op": "load_prompts", + "description": "Load prompt templates" + }, + { + "id": "create_github_client", + "type": "operation", + "op": "create_github_client", + "description": "Initialize GitHub API client" + }, + { + "id": "create_openai_client", + "type": "operation", + "op": "create_openai_client", + "description": "Initialize OpenAI API client" + }, + { + "id": "load_tools", + "type": "operation", + "op": "load_tools", + "description": "Load available tool definitions" + }, + { + "id": "load_plugins", + "type": "operation", + "op": "load_plugins", + "description": "Load and initialize plugins" + }, + { + "id": "seed_context", + "type": "operation", + "op": "seed_context", + "description": "Initialize execution context" + }, + { + "id": "seed_messages", + "type": "operation", + "op": "seed_messages", + "description": "Seed initial conversation messages" + }, + { + "id": "append_user_instructions", + "type": "operation", + "op": "append_message", + "description": "Append user instructions to messages" + }, + { + "id": "ai_loop", + "type": "loop", + "max_iterations": 10, + "when": "$no_tool_calls", + "nodes": [ + { + "id": "ai_request", + "type": "operation", + "op": "ai_request", + "description": "Make request to AI model" + }, + { + "id": "execute_tool_calls", + "type": "operation", + "op": "execute_tool_calls", + "description": "Execute any tool calls from AI response" + }, + { + "id": "append_results", + "type": "operation", + "op": "append_results", + "description": "Append tool results to conversation" + } + ] + } + ], + "connections": [ + { "from": "load_messages", "to": "load_metadata" }, + { "from": "load_metadata", "to": "load_prompts" }, + { "from": "load_prompts", "to": "create_github_client" }, + { "from": "create_github_client", "to": "create_openai_client" }, + { "from": "create_openai_client", "to": "load_tools" }, + { "from": "load_tools", "to": "load_plugins" }, + { "from": "load_plugins", "to": "seed_context" }, + { "from": "seed_context", "to": "seed_messages" }, + { "from": "seed_messages", "to": "append_user_instructions" }, + { "from": "append_user_instructions", "to": "ai_loop" } + ] +} diff --git a/workflow/examples/python/default_app_workflow/workflow.json b/workflow/examples/python/default_app_workflow/workflow.json index 5900bb953..a812556f9 100644 --- a/workflow/examples/python/default_app_workflow/workflow.json +++ b/workflow/examples/python/default_app_workflow/workflow.json @@ -1,110 +1,313 @@ { - "version": "2.2.0", "name": "default_app_workflow", - "description": "Default application workflow with backend bootstrap and iterative AI loop", "active": false, - "trigger": { - "type": "manual", - "node": "load_messages" - }, "nodes": [ { "id": "load_messages", - "type": "operation", - "op": "load_messages", - "description": "Load initial messages from storage" + "name": "Load Messages", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 100 + ], + "parameters": { + "operation": "load_messages" + }, + "notes": "Load initial messages from storage", + "notesInFlow": false }, { "id": "load_metadata", - "type": "operation", - "op": "load_metadata", - "description": "Load workflow metadata and configuration" + "name": "Load Metadata", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 100 + ], + "parameters": { + "operation": "load_metadata" + }, + "notes": "Load workflow metadata and configuration", + "notesInFlow": false }, { "id": "load_prompts", - "type": "operation", - "op": "load_prompts", - "description": "Load prompt templates" + "name": "Load Prompts", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 100 + ], + "parameters": { + "operation": "load_prompts" + }, + "notes": "Load prompt templates", + "notesInFlow": false }, { "id": "create_github_client", - "type": "operation", - "op": "create_github_client", - "description": "Initialize GitHub API client" + "name": "Create Github Client", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 300 + ], + "parameters": { + "operation": "create_github_client" + }, + "notes": "Initialize GitHub API client", + "notesInFlow": false }, { "id": "create_openai_client", - "type": "operation", - "op": "create_openai_client", - "description": "Initialize OpenAI API client" + "name": "Create Openai Client", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 300 + ], + "parameters": { + "operation": "create_openai_client" + }, + "notes": "Initialize OpenAI API client", + "notesInFlow": false }, { "id": "load_tools", - "type": "operation", - "op": "load_tools", - "description": "Load available tool definitions" + "name": "Load Tools", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 300 + ], + "parameters": { + "operation": "load_tools" + }, + "notes": "Load available tool definitions", + "notesInFlow": false }, { "id": "load_plugins", - "type": "operation", - "op": "load_plugins", - "description": "Load and initialize plugins" + "name": "Load Plugins", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 500 + ], + "parameters": { + "operation": "load_plugins" + }, + "notes": "Load and initialize plugins", + "notesInFlow": false }, { "id": "seed_context", - "type": "operation", - "op": "seed_context", - "description": "Initialize execution context" + "name": "Seed Context", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 400, + 500 + ], + "parameters": { + "operation": "seed_context" + }, + "notes": "Initialize execution context", + "notesInFlow": false }, { "id": "seed_messages", - "type": "operation", - "op": "seed_messages", - "description": "Seed initial conversation messages" + "name": "Seed Messages", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 700, + 500 + ], + "parameters": { + "operation": "seed_messages" + }, + "notes": "Seed initial conversation messages", + "notesInFlow": false }, { "id": "append_user_instructions", - "type": "operation", - "op": "append_message", - "description": "Append user instructions to messages" + "name": "Append User Instructions", + "type": "metabuilder.operation", + "typeVersion": 1, + "position": [ + 100, + 700 + ], + "parameters": { + "operation": "append_message" + }, + "notes": "Append user instructions to messages", + "notesInFlow": false }, { "id": "ai_loop", - "type": "loop", - "max_iterations": 10, - "when": "$no_tool_calls", - "nodes": [ - { - "id": "ai_request", - "type": "operation", - "op": "ai_request", - "description": "Make request to AI model" - }, - { - "id": "execute_tool_calls", - "type": "operation", - "op": "execute_tool_calls", - "description": "Execute any tool calls from AI response" - }, - { - "id": "append_results", - "type": "operation", - "op": "append_results", - "description": "Append tool results to conversation" - } - ] + "name": "Ai Loop", + "type": "metabuilder.loop", + "typeVersion": 1, + "position": [ + 400, + 700 + ], + "parameters": { + "max_iterations": 10, + "when": "$no_tool_calls", + "nodes": [ + { + "id": "ai_request", + "type": "operation", + "op": "ai_request", + "description": "Make request to AI model" + }, + { + "id": "execute_tool_calls", + "type": "operation", + "op": "execute_tool_calls", + "description": "Execute any tool calls from AI response" + }, + { + "id": "append_results", + "type": "operation", + "op": "append_results", + "description": "Append tool results to conversation" + } + ] + } } ], - "connections": [ - { "from": "load_messages", "to": "load_metadata" }, - { "from": "load_metadata", "to": "load_prompts" }, - { "from": "load_prompts", "to": "create_github_client" }, - { "from": "create_github_client", "to": "create_openai_client" }, - { "from": "create_openai_client", "to": "load_tools" }, - { "from": "load_tools", "to": "load_plugins" }, - { "from": "load_plugins", "to": "seed_context" }, - { "from": "seed_context", "to": "seed_messages" }, - { "from": "seed_messages", "to": "append_user_instructions" }, - { "from": "append_user_instructions", "to": "ai_loop" } - ] + "connections": { + "Load Messages": { + "main": { + "0": [ + { + "node": "Load Metadata", + "type": "main", + "index": 0 + } + ] + } + }, + "Load Metadata": { + "main": { + "0": [ + { + "node": "Load Prompts", + "type": "main", + "index": 0 + } + ] + } + }, + "Load Prompts": { + "main": { + "0": [ + { + "node": "Create Github Client", + "type": "main", + "index": 0 + } + ] + } + }, + "Create Github Client": { + "main": { + "0": [ + { + "node": "Create Openai Client", + "type": "main", + "index": 0 + } + ] + } + }, + "Create Openai Client": { + "main": { + "0": [ + { + "node": "Load Tools", + "type": "main", + "index": 0 + } + ] + } + }, + "Load Tools": { + "main": { + "0": [ + { + "node": "Load Plugins", + "type": "main", + "index": 0 + } + ] + } + }, + "Load Plugins": { + "main": { + "0": [ + { + "node": "Seed Context", + "type": "main", + "index": 0 + } + ] + } + }, + "Seed Context": { + "main": { + "0": [ + { + "node": "Seed Messages", + "type": "main", + "index": 0 + } + ] + } + }, + "Seed Messages": { + "main": { + "0": [ + { + "node": "Append User Instructions", + "type": "main", + "index": 0 + } + ] + } + }, + "Append User Instructions": { + "main": { + "0": [ + { + "node": "Ai Loop", + "type": "main", + "index": 0 + } + ] + } + } + }, + "staticData": {}, + "meta": { + "description": "Default application workflow with backend bootstrap and iterative AI loop" + }, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/dict_plugins_test/workflow.backup.json b/workflow/examples/python/dict_plugins_test/workflow.backup.json new file mode 100644 index 000000000..ad51b14c7 --- /dev/null +++ b/workflow/examples/python/dict_plugins_test/workflow.backup.json @@ -0,0 +1,312 @@ +{ + "name": "Dict Plugins Test Suite", + "active": false, + "nodes": [ + { + "id": "test_get", + "name": "Test Get", + "type": "dict.get", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": { + "object": { + "name": "Alice", + "age": 30 + }, + "key": "name" + } + }, + { + "id": "assert_get", + "name": "Assert Get Value", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": { + "actual": "$test_get.result", + "expected": "Alice", + "message": "dict.get should retrieve value" + } + }, + { + "id": "assert_get_found", + "name": "Assert Get Found", + "type": "test.assert_true", + "typeVersion": 1, + "position": [ + 600, + 0 + ], + "parameters": { + "value": "$test_get.found", + "message": "dict.get should set found flag" + } + }, + { + "id": "test_set", + "name": "Test Set", + "type": "dict.set", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "object": { + "a": 1 + }, + "key": "b", + "value": 2 + } + }, + { + "id": "test_get_new_key", + "name": "Test Get New Key", + "type": "dict.get", + "typeVersion": 1, + "position": [ + 300, + 100 + ], + "parameters": { + "object": "$test_set.result", + "key": "b" + } + }, + { + "id": "assert_set", + "name": "Assert Set Value", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 600, + 100 + ], + "parameters": { + "actual": "$test_get_new_key.result", + "expected": 2, + "message": "dict.set should add new key" + } + }, + { + "id": "test_keys", + "name": "Test Keys", + "type": "dict.keys", + "typeVersion": 1, + "position": [ + 0, + 200 + ], + "parameters": { + "object": { + "a": 1, + "b": 2, + "c": 3 + } + } + }, + { + "id": "assert_keys_length", + "name": "Assert Keys Length", + "type": "list.length", + "typeVersion": 1, + "position": [ + 300, + 200 + ], + "parameters": { + "items": "$test_keys.result" + } + }, + { + "id": "assert_keys", + "name": "Assert Keys Count", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 600, + 200 + ], + "parameters": { + "actual": "$assert_keys_length.result", + "expected": 3, + "message": "dict.keys should return all keys" + } + }, + { + "id": "test_merge", + "name": "Test Merge", + "type": "dict.merge", + "typeVersion": 1, + "position": [ + 0, + 300 + ], + "parameters": { + "objects": [ + { + "a": 1 + }, + { + "b": 2 + }, + { + "c": 3 + } + ] + } + }, + { + "id": "test_merged_keys", + "name": "Get Merged Keys", + "type": "dict.keys", + "typeVersion": 1, + "position": [ + 300, + 300 + ], + "parameters": { + "object": "$test_merge.result" + } + }, + { + "id": "assert_merge_length", + "name": "Assert Merge Length", + "type": "list.length", + "typeVersion": 1, + "position": [ + 600, + 300 + ], + "parameters": { + "items": "$test_merged_keys.result" + } + }, + { + "id": "assert_merge", + "name": "Assert Merge", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 900, + 300 + ], + "parameters": { + "actual": "$assert_merge_length.result", + "expected": 3, + "message": "dict.merge should merge dicts" + } + } + ], + "connections": { + "Test Get": { + "main": { + "0": [ + { + "node": "Assert Get Value", + "type": "main", + "index": 0 + }, + { + "node": "Assert Get Found", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Set": { + "main": { + "0": [ + { + "node": "Test Get New Key", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Get New Key": { + "main": { + "0": [ + { + "node": "Assert Set Value", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Keys": { + "main": { + "0": [ + { + "node": "Assert Keys Length", + "type": "main", + "index": 0 + } + ] + } + }, + "Assert Keys Length": { + "main": { + "0": [ + { + "node": "Assert Keys Count", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Merge": { + "main": { + "0": [ + { + "node": "Get Merged Keys", + "type": "main", + "index": 0 + } + ] + } + }, + "Get Merged Keys": { + "main": { + "0": [ + { + "node": "Assert Merge Length", + "type": "main", + "index": 0 + } + ] + } + }, + "Assert Merge Length": { + "main": { + "0": [ + { + "node": "Assert Merge", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "test_get", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered Dict Plugins Test Suite workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/dict_plugins_test/workflow.json b/workflow/examples/python/dict_plugins_test/workflow.json index ad51b14c7..c104b6a6c 100644 --- a/workflow/examples/python/dict_plugins_test/workflow.json +++ b/workflow/examples/python/dict_plugins_test/workflow.json @@ -8,30 +8,46 @@ "type": "dict.get", "typeVersion": 1, "position": [ - 0, - 0 + 100, + 100 ], "parameters": { - "object": { - "name": "Alice", - "age": 30 - }, - "key": "name" + "name": "Test Get", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": { + "object": { + "name": "Alice", + "age": 30 + }, + "key": "name" + } } }, { "id": "assert_get", - "name": "Assert Get Value", + "name": "Assert Get", "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 0 + 400, + 100 ], "parameters": { - "actual": "$test_get.result", - "expected": "Alice", - "message": "dict.get should retrieve value" + "name": "Assert Get Value", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": { + "actual": "$test_get.result", + "expected": "Alice", + "message": "dict.get should retrieve value" + } } }, { @@ -40,12 +56,20 @@ "type": "test.assert_true", "typeVersion": 1, "position": [ - 600, - 0 + 700, + 100 ], "parameters": { - "value": "$test_get.found", - "message": "dict.get should set found flag" + "name": "Assert Get Found", + "typeVersion": 1, + "position": [ + 600, + 0 + ], + "parameters": { + "value": "$test_get.found", + "message": "dict.get should set found flag" + } } }, { @@ -54,15 +78,23 @@ "type": "dict.set", "typeVersion": 1, "position": [ - 0, - 100 + 100, + 300 ], "parameters": { - "object": { - "a": 1 - }, - "key": "b", - "value": 2 + "name": "Test Set", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "object": { + "a": 1 + }, + "key": "b", + "value": 2 + } } }, { @@ -71,27 +103,43 @@ "type": "dict.get", "typeVersion": 1, "position": [ - 300, - 100 + 400, + 300 ], "parameters": { - "object": "$test_set.result", - "key": "b" + "name": "Test Get New Key", + "typeVersion": 1, + "position": [ + 300, + 100 + ], + "parameters": { + "object": "$test_set.result", + "key": "b" + } } }, { "id": "assert_set", - "name": "Assert Set Value", + "name": "Assert Set", "type": "test.assert_equals", "typeVersion": 1, "position": [ - 600, - 100 + 700, + 300 ], "parameters": { - "actual": "$test_get_new_key.result", - "expected": 2, - "message": "dict.set should add new key" + "name": "Assert Set Value", + "typeVersion": 1, + "position": [ + 600, + 100 + ], + "parameters": { + "actual": "$test_get_new_key.result", + "expected": 2, + "message": "dict.set should add new key" + } } }, { @@ -100,14 +148,22 @@ "type": "dict.keys", "typeVersion": 1, "position": [ - 0, - 200 + 100, + 500 ], "parameters": { - "object": { - "a": 1, - "b": 2, - "c": 3 + "name": "Test Keys", + "typeVersion": 1, + "position": [ + 0, + 200 + ], + "parameters": { + "object": { + "a": 1, + "b": 2, + "c": 3 + } } } }, @@ -117,26 +173,42 @@ "type": "list.length", "typeVersion": 1, "position": [ - 300, - 200 + 400, + 500 ], "parameters": { - "items": "$test_keys.result" + "name": "Assert Keys Length", + "typeVersion": 1, + "position": [ + 300, + 200 + ], + "parameters": { + "items": "$test_keys.result" + } } }, { "id": "assert_keys", - "name": "Assert Keys Count", + "name": "Assert Keys", "type": "test.assert_equals", "typeVersion": 1, "position": [ - 600, - 200 + 700, + 500 ], "parameters": { - "actual": "$assert_keys_length.result", - "expected": 3, - "message": "dict.keys should return all keys" + "name": "Assert Keys Count", + "typeVersion": 1, + "position": [ + 600, + 200 + ], + "parameters": { + "actual": "$assert_keys_length.result", + "expected": 3, + "message": "dict.keys should return all keys" + } } }, { @@ -145,34 +217,50 @@ "type": "dict.merge", "typeVersion": 1, "position": [ - 0, - 300 + 100, + 700 ], "parameters": { - "objects": [ - { - "a": 1 - }, - { - "b": 2 - }, - { - "c": 3 - } - ] + "name": "Test Merge", + "typeVersion": 1, + "position": [ + 0, + 300 + ], + "parameters": { + "objects": [ + { + "a": 1 + }, + { + "b": 2 + }, + { + "c": 3 + } + ] + } } }, { "id": "test_merged_keys", - "name": "Get Merged Keys", + "name": "Test Merged Keys", "type": "dict.keys", "typeVersion": 1, "position": [ - 300, - 300 + 400, + 700 ], "parameters": { - "object": "$test_merge.result" + "name": "Get Merged Keys", + "typeVersion": 1, + "position": [ + 300, + 300 + ], + "parameters": { + "object": "$test_merge.result" + } } }, { @@ -181,11 +269,19 @@ "type": "list.length", "typeVersion": 1, "position": [ - 600, - 300 + 700, + 700 ], "parameters": { - "items": "$test_merged_keys.result" + "name": "Assert Merge Length", + "typeVersion": 1, + "position": [ + 600, + 300 + ], + "parameters": { + "items": "$test_merged_keys.result" + } } }, { @@ -194,13 +290,21 @@ "type": "test.assert_equals", "typeVersion": 1, "position": [ - 900, - 300 + 100, + 900 ], "parameters": { - "actual": "$assert_merge_length.result", - "expected": 3, - "message": "dict.merge should merge dicts" + "name": "Assert Merge", + "typeVersion": 1, + "position": [ + 900, + 300 + ], + "parameters": { + "actual": "$assert_merge_length.result", + "expected": 3, + "message": "dict.merge should merge dicts" + } } } ], @@ -209,12 +313,7 @@ "main": { "0": [ { - "node": "Assert Get Value", - "type": "main", - "index": 0 - }, - { - "node": "Assert Get Found", + "node": "[object Object]", "type": "main", "index": 0 } @@ -225,7 +324,7 @@ "main": { "0": [ { - "node": "Test Get New Key", + "node": "[object Object]", "type": "main", "index": 0 } @@ -236,7 +335,7 @@ "main": { "0": [ { - "node": "Assert Set Value", + "node": "[object Object]", "type": "main", "index": 0 } @@ -247,7 +346,7 @@ "main": { "0": [ { - "node": "Assert Keys Length", + "node": "[object Object]", "type": "main", "index": 0 } @@ -258,7 +357,7 @@ "main": { "0": [ { - "node": "Assert Keys Count", + "node": "[object Object]", "type": "main", "index": 0 } @@ -269,7 +368,7 @@ "main": { "0": [ { - "node": "Get Merged Keys", + "node": "[object Object]", "type": "main", "index": 0 } @@ -280,7 +379,7 @@ "main": { "0": [ { - "node": "Assert Merge Length", + "node": "[object Object]", "type": "main", "index": 0 } @@ -291,7 +390,7 @@ "main": { "0": [ { - "node": "Assert Merge", + "node": "[object Object]", "type": "main", "index": 0 } @@ -299,14 +398,13 @@ } } }, - "triggers": [ - { - "nodeId": "test_get", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered Dict Plugins Test Suite workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/game_tick_loop/workflow.backup.json b/workflow/examples/python/game_tick_loop/workflow.backup.json new file mode 100644 index 000000000..b838892b4 --- /dev/null +++ b/workflow/examples/python/game_tick_loop/workflow.backup.json @@ -0,0 +1,123 @@ +{ + "name": "meta.workflow_packages.game_tick_loop.label", + "active": false, + "nodes": [ + { + "id": "seed_messages", + "name": "Seed Messages", + "type": "core.seed_messages", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": {} + }, + { + "id": "map_ticks", + "name": "Map Ticks", + "type": "utils.map_list", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": { + "items": [ + "tick_start", + "tick_update", + "tick_render" + ], + "template": "Tick: {item}" + } + }, + { + "id": "reduce_ticks", + "name": "Reduce Ticks", + "type": "utils.reduce_list", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "items": "$tick_lines", + "separator": "\\n" + } + }, + { + "id": "append_tick_context", + "name": "Append Tick Context", + "type": "core.append_context_message", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "messages": "$messages", + "context": "$tick_context" + } + }, + { + "id": "main_loop", + "name": "Main Loop", + "type": "control.loop", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": { + "max_iterations": 3, + "stop_when": "$no_tool_calls", + "stop_on": "true" + } + } + ], + "connections": { + "Map Ticks": { + "main": { + "0": [ + { + "node": "Reduce Ticks", + "type": "main", + "index": 0 + } + ] + } + }, + "Append Tick Context": { + "main": { + "0": [ + { + "node": "Append Tick Context", + "type": "main", + "index": 0 + } + ] + } + }, + "Reduce Ticks": { + "main": { + "0": [ + { + "node": "Append Tick Context", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "seed_messages", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered meta.workflow_packages.game_tick_loop.label workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/game_tick_loop/workflow.json b/workflow/examples/python/game_tick_loop/workflow.json index b838892b4..16d53eb5e 100644 --- a/workflow/examples/python/game_tick_loop/workflow.json +++ b/workflow/examples/python/game_tick_loop/workflow.json @@ -8,10 +8,18 @@ "type": "core.seed_messages", "typeVersion": 1, "position": [ - 0, - 50 + 100, + 100 ], - "parameters": {} + "parameters": { + "name": "Seed Messages", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": {} + } }, { "id": "map_ticks", @@ -19,16 +27,24 @@ "type": "utils.map_list", "typeVersion": 1, "position": [ - 300, - 50 + 400, + 100 ], "parameters": { - "items": [ - "tick_start", - "tick_update", - "tick_render" + "name": "Map Ticks", + "typeVersion": 1, + "position": [ + 300, + 50 ], - "template": "Tick: {item}" + "parameters": { + "items": [ + "tick_start", + "tick_update", + "tick_render" + ], + "template": "Tick: {item}" + } } }, { @@ -37,12 +53,20 @@ "type": "utils.reduce_list", "typeVersion": 1, "position": [ - 600, - 50 + 700, + 100 ], "parameters": { - "items": "$tick_lines", - "separator": "\\n" + "name": "Reduce Ticks", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "items": "$tick_lines", + "separator": "\\n" + } } }, { @@ -51,12 +75,20 @@ "type": "core.append_context_message", "typeVersion": 1, "position": [ - 900, - 50 + 100, + 300 ], "parameters": { - "messages": "$messages", - "context": "$tick_context" + "name": "Append Tick Context", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "messages": "$messages", + "context": "$tick_context" + } } }, { @@ -65,13 +97,21 @@ "type": "control.loop", "typeVersion": 1, "position": [ - 1200, - 50 + 400, + 300 ], "parameters": { - "max_iterations": 3, - "stop_when": "$no_tool_calls", - "stop_on": "true" + "name": "Main Loop", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": { + "max_iterations": 3, + "stop_when": "$no_tool_calls", + "stop_on": "true" + } } } ], @@ -80,7 +120,7 @@ "main": { "0": [ { - "node": "Reduce Ticks", + "node": "[object Object]", "type": "main", "index": 0 } @@ -91,7 +131,7 @@ "main": { "0": [ { - "node": "Append Tick Context", + "node": "[object Object]", "type": "main", "index": 0 } @@ -102,7 +142,7 @@ "main": { "0": [ { - "node": "Append Tick Context", + "node": "[object Object]", "type": "main", "index": 0 } @@ -110,14 +150,13 @@ } } }, - "triggers": [ - { - "nodeId": "seed_messages", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered meta.workflow_packages.game_tick_loop.label workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/iterative_loop/workflow.backup.json b/workflow/examples/python/iterative_loop/workflow.backup.json new file mode 100644 index 000000000..b96663936 --- /dev/null +++ b/workflow/examples/python/iterative_loop/workflow.backup.json @@ -0,0 +1,198 @@ +{ + "name": "Iterative Agent Loop", + "active": false, + "nodes": [ + { + "id": "load_context", + "name": "Load Context", + "type": "core.load_context", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": {} + }, + { + "id": "seed_messages", + "name": "Seed Messages", + "type": "core.seed_messages", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": {} + }, + { + "id": "append_context", + "name": "Append Context", + "type": "core.append_context_message", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": {} + }, + { + "id": "append_user_instruction", + "name": "Append User Instruction", + "type": "core.append_user_instruction", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": {} + }, + { + "id": "main_loop", + "name": "Main Loop", + "type": "control.loop", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "max_iterations": 10, + "stop_when": "$no_tool_calls", + "stop_on": "true" + } + }, + { + "id": "ai_request", + "name": "AI Request", + "type": "core.ai_request", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": {} + }, + { + "id": "run_tool_calls", + "name": "Run Tool Calls", + "type": "core.run_tool_calls", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": {} + }, + { + "id": "append_tool_results", + "name": "Append Tool Results", + "type": "core.append_tool_results", + "typeVersion": 1, + "position": [ + 1800, + 50 + ], + "parameters": {} + } + ], + "connections": { + "Load Context": { + "main": { + "0": [ + { + "node": "Append Context", + "type": "main", + "index": 0 + } + ] + } + }, + "Seed Messages": { + "main": { + "0": [ + { + "node": "Append Context", + "type": "main", + "index": 0 + } + ] + } + }, + "Append Context": { + "main": { + "0": [ + { + "node": "Append User Instruction", + "type": "main", + "index": 0 + } + ] + } + }, + "Append User Instruction": { + "main": { + "0": [ + { + "node": "Main Loop", + "type": "main", + "index": 0 + } + ] + } + }, + "Main Loop": { + "main": { + "0": [ + { + "node": "AI Request", + "type": "main", + "index": 0 + } + ] + } + }, + "AI Request": { + "main": { + "0": [ + { + "node": "Run Tool Calls", + "type": "main", + "index": 0 + } + ] + } + }, + "Run Tool Calls": { + "main": { + "0": [ + { + "node": "Append Tool Results", + "type": "main", + "index": 0 + } + ] + } + }, + "Append Tool Results": { + "main": { + "0": [ + { + "node": "Main Loop", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "load_context", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered Iterative Agent Loop workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/iterative_loop/workflow.json b/workflow/examples/python/iterative_loop/workflow.json index b96663936..0dcc432c2 100644 --- a/workflow/examples/python/iterative_loop/workflow.json +++ b/workflow/examples/python/iterative_loop/workflow.json @@ -8,10 +8,18 @@ "type": "core.load_context", "typeVersion": 1, "position": [ - 0, - 0 + 100, + 100 ], - "parameters": {} + "parameters": { + "name": "Load Context", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": {} + } }, { "id": "seed_messages", @@ -19,10 +27,18 @@ "type": "core.seed_messages", "typeVersion": 1, "position": [ - 0, + 400, 100 ], - "parameters": {} + "parameters": { + "name": "Seed Messages", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": {} + } }, { "id": "append_context", @@ -30,10 +46,18 @@ "type": "core.append_context_message", "typeVersion": 1, "position": [ - 300, - 50 + 700, + 100 ], - "parameters": {} + "parameters": { + "name": "Append Context", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": {} + } }, { "id": "append_user_instruction", @@ -41,10 +65,18 @@ "type": "core.append_user_instruction", "typeVersion": 1, "position": [ - 600, - 50 + 100, + 300 ], - "parameters": {} + "parameters": { + "name": "Append User Instruction", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": {} + } }, { "id": "main_loop", @@ -52,25 +84,41 @@ "type": "control.loop", "typeVersion": 1, "position": [ - 900, - 50 + 400, + 300 ], "parameters": { - "max_iterations": 10, - "stop_when": "$no_tool_calls", - "stop_on": "true" + "name": "Main Loop", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "max_iterations": 10, + "stop_when": "$no_tool_calls", + "stop_on": "true" + } } }, { "id": "ai_request", - "name": "AI Request", + "name": "Ai Request", "type": "core.ai_request", "typeVersion": 1, "position": [ - 1200, - 50 + 700, + 300 ], - "parameters": {} + "parameters": { + "name": "AI Request", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": {} + } }, { "id": "run_tool_calls", @@ -78,10 +126,18 @@ "type": "core.run_tool_calls", "typeVersion": 1, "position": [ - 1500, - 50 + 100, + 500 ], - "parameters": {} + "parameters": { + "name": "Run Tool Calls", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": {} + } }, { "id": "append_tool_results", @@ -89,10 +145,18 @@ "type": "core.append_tool_results", "typeVersion": 1, "position": [ - 1800, - 50 + 400, + 500 ], - "parameters": {} + "parameters": { + "name": "Append Tool Results", + "typeVersion": 1, + "position": [ + 1800, + 50 + ], + "parameters": {} + } } ], "connections": { @@ -100,7 +164,7 @@ "main": { "0": [ { - "node": "Append Context", + "node": "[object Object]", "type": "main", "index": 0 } @@ -111,7 +175,7 @@ "main": { "0": [ { - "node": "Append Context", + "node": "[object Object]", "type": "main", "index": 0 } @@ -122,7 +186,7 @@ "main": { "0": [ { - "node": "Append User Instruction", + "node": "[object Object]", "type": "main", "index": 0 } @@ -133,7 +197,7 @@ "main": { "0": [ { - "node": "Main Loop", + "node": "[object Object]", "type": "main", "index": 0 } @@ -144,18 +208,18 @@ "main": { "0": [ { - "node": "AI Request", + "node": "[object Object]", "type": "main", "index": 0 } ] } }, - "AI Request": { + "Ai Request": { "main": { "0": [ { - "node": "Run Tool Calls", + "node": "[object Object]", "type": "main", "index": 0 } @@ -166,7 +230,7 @@ "main": { "0": [ { - "node": "Append Tool Results", + "node": "[object Object]", "type": "main", "index": 0 } @@ -177,7 +241,7 @@ "main": { "0": [ { - "node": "Main Loop", + "node": "[object Object]", "type": "main", "index": 0 } @@ -185,14 +249,13 @@ } } }, - "triggers": [ - { - "nodeId": "load_context", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered Iterative Agent Loop workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/list_plugins_test/workflow.backup.json b/workflow/examples/python/list_plugins_test/workflow.backup.json new file mode 100644 index 000000000..7e3527c35 --- /dev/null +++ b/workflow/examples/python/list_plugins_test/workflow.backup.json @@ -0,0 +1,277 @@ +{ + "name": "List Plugins Test Suite", + "active": false, + "nodes": [ + { + "id": "test_concat", + "name": "Test Concat", + "type": "list.concat", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": { + "lists": [ + [ + 1, + 2 + ], + [ + 3, + 4 + ], + [ + 5 + ] + ] + } + }, + { + "id": "assert_concat_length", + "name": "Assert Concat Length", + "type": "list.length", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": { + "items": "$test_concat.result" + } + }, + { + "id": "assert_concat", + "name": "Assert Concat", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 600, + 0 + ], + "parameters": { + "actual": "$assert_concat_length.result", + "expected": 5, + "message": "list.concat should concatenate lists" + } + }, + { + "id": "test_length", + "name": "Test Length", + "type": "list.length", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "items": [ + 1, + 2, + 3, + 4, + 5 + ] + } + }, + { + "id": "assert_length", + "name": "Assert Length", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 100 + ], + "parameters": { + "actual": "$test_length.result", + "expected": 5, + "message": "list.length should count items" + } + }, + { + "id": "test_slice", + "name": "Test Slice", + "type": "list.slice", + "typeVersion": 1, + "position": [ + 0, + 200 + ], + "parameters": { + "items": [ + 1, + 2, + 3, + 4, + 5 + ], + "start": 1, + "end": 3 + } + }, + { + "id": "assert_slice_length", + "name": "Assert Slice Length", + "type": "list.length", + "typeVersion": 1, + "position": [ + 300, + 200 + ], + "parameters": { + "items": "$test_slice.result" + } + }, + { + "id": "assert_slice", + "name": "Assert Slice", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 600, + 200 + ], + "parameters": { + "actual": "$assert_slice_length.result", + "expected": 2, + "message": "list.slice should extract slice" + } + }, + { + "id": "test_find", + "name": "Test Find", + "type": "list.find", + "typeVersion": 1, + "position": [ + 0, + 300 + ], + "parameters": { + "items": [ + { + "id": 1, + "name": "Alice" + }, + { + "id": 2, + "name": "Bob" + } + ], + "key": "name", + "value": "Bob" + } + }, + { + "id": "assert_find", + "name": "Assert Find Result", + "type": "test.assert_exists", + "typeVersion": 1, + "position": [ + 300, + 300 + ], + "parameters": { + "value": "$test_find.result", + "message": "list.find should find item" + } + }, + { + "id": "assert_find_found", + "name": "Assert Found Flag", + "type": "test.assert_true", + "typeVersion": 1, + "position": [ + 600, + 300 + ], + "parameters": { + "value": "$test_find.found", + "message": "list.find should set found flag" + } + } + ], + "connections": { + "Test Concat": { + "main": { + "0": [ + { + "node": "Assert Concat Length", + "type": "main", + "index": 0 + } + ] + } + }, + "Assert Concat Length": { + "main": { + "0": [ + { + "node": "Assert Concat", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Length": { + "main": { + "0": [ + { + "node": "Assert Length", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Slice": { + "main": { + "0": [ + { + "node": "Assert Slice Length", + "type": "main", + "index": 0 + } + ] + } + }, + "Assert Slice Length": { + "main": { + "0": [ + { + "node": "Assert Slice", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Find": { + "main": { + "0": [ + { + "node": "Assert Find Result", + "type": "main", + "index": 0 + }, + { + "node": "Assert Found Flag", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "test_concat", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered List Plugins Test Suite workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/list_plugins_test/workflow.json b/workflow/examples/python/list_plugins_test/workflow.json index 7e3527c35..3e78ede48 100644 --- a/workflow/examples/python/list_plugins_test/workflow.json +++ b/workflow/examples/python/list_plugins_test/workflow.json @@ -8,23 +8,31 @@ "type": "list.concat", "typeVersion": 1, "position": [ - 0, - 0 + 100, + 100 ], "parameters": { - "lists": [ - [ - 1, - 2 - ], - [ - 3, - 4 - ], - [ - 5 + "name": "Test Concat", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": { + "lists": [ + [ + 1, + 2 + ], + [ + 3, + 4 + ], + [ + 5 + ] ] - ] + } } }, { @@ -33,11 +41,19 @@ "type": "list.length", "typeVersion": 1, "position": [ - 300, - 0 + 400, + 100 ], "parameters": { - "items": "$test_concat.result" + "name": "Assert Concat Length", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": { + "items": "$test_concat.result" + } } }, { @@ -46,13 +62,21 @@ "type": "test.assert_equals", "typeVersion": 1, "position": [ - 600, - 0 + 700, + 100 ], "parameters": { - "actual": "$assert_concat_length.result", - "expected": 5, - "message": "list.concat should concatenate lists" + "name": "Assert Concat", + "typeVersion": 1, + "position": [ + 600, + 0 + ], + "parameters": { + "actual": "$assert_concat_length.result", + "expected": 5, + "message": "list.concat should concatenate lists" + } } }, { @@ -61,17 +85,25 @@ "type": "list.length", "typeVersion": 1, "position": [ - 0, - 100 + 100, + 300 ], "parameters": { - "items": [ - 1, - 2, - 3, - 4, - 5 - ] + "name": "Test Length", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "items": [ + 1, + 2, + 3, + 4, + 5 + ] + } } }, { @@ -80,13 +112,21 @@ "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 100 + 400, + 300 ], "parameters": { - "actual": "$test_length.result", - "expected": 5, - "message": "list.length should count items" + "name": "Assert Length", + "typeVersion": 1, + "position": [ + 300, + 100 + ], + "parameters": { + "actual": "$test_length.result", + "expected": 5, + "message": "list.length should count items" + } } }, { @@ -95,19 +135,27 @@ "type": "list.slice", "typeVersion": 1, "position": [ - 0, - 200 + 700, + 300 ], "parameters": { - "items": [ - 1, - 2, - 3, - 4, - 5 + "name": "Test Slice", + "typeVersion": 1, + "position": [ + 0, + 200 ], - "start": 1, - "end": 3 + "parameters": { + "items": [ + 1, + 2, + 3, + 4, + 5 + ], + "start": 1, + "end": 3 + } } }, { @@ -116,11 +164,19 @@ "type": "list.length", "typeVersion": 1, "position": [ - 300, - 200 + 100, + 500 ], "parameters": { - "items": "$test_slice.result" + "name": "Assert Slice Length", + "typeVersion": 1, + "position": [ + 300, + 200 + ], + "parameters": { + "items": "$test_slice.result" + } } }, { @@ -129,13 +185,21 @@ "type": "test.assert_equals", "typeVersion": 1, "position": [ - 600, - 200 + 400, + 500 ], "parameters": { - "actual": "$assert_slice_length.result", - "expected": 2, - "message": "list.slice should extract slice" + "name": "Assert Slice", + "typeVersion": 1, + "position": [ + 600, + 200 + ], + "parameters": { + "actual": "$assert_slice_length.result", + "expected": 2, + "message": "list.slice should extract slice" + } } }, { @@ -144,50 +208,74 @@ "type": "list.find", "typeVersion": 1, "position": [ - 0, - 300 + 700, + 500 ], "parameters": { - "items": [ - { - "id": 1, - "name": "Alice" - }, - { - "id": 2, - "name": "Bob" - } + "name": "Test Find", + "typeVersion": 1, + "position": [ + 0, + 300 ], - "key": "name", - "value": "Bob" + "parameters": { + "items": [ + { + "id": 1, + "name": "Alice" + }, + { + "id": 2, + "name": "Bob" + } + ], + "key": "name", + "value": "Bob" + } } }, { "id": "assert_find", - "name": "Assert Find Result", + "name": "Assert Find", "type": "test.assert_exists", "typeVersion": 1, "position": [ - 300, - 300 + 100, + 700 ], "parameters": { - "value": "$test_find.result", - "message": "list.find should find item" + "name": "Assert Find Result", + "typeVersion": 1, + "position": [ + 300, + 300 + ], + "parameters": { + "value": "$test_find.result", + "message": "list.find should find item" + } } }, { "id": "assert_find_found", - "name": "Assert Found Flag", + "name": "Assert Find Found", "type": "test.assert_true", "typeVersion": 1, "position": [ - 600, - 300 + 400, + 700 ], "parameters": { - "value": "$test_find.found", - "message": "list.find should set found flag" + "name": "Assert Found Flag", + "typeVersion": 1, + "position": [ + 600, + 300 + ], + "parameters": { + "value": "$test_find.found", + "message": "list.find should set found flag" + } } } ], @@ -196,7 +284,7 @@ "main": { "0": [ { - "node": "Assert Concat Length", + "node": "[object Object]", "type": "main", "index": 0 } @@ -207,7 +295,7 @@ "main": { "0": [ { - "node": "Assert Concat", + "node": "[object Object]", "type": "main", "index": 0 } @@ -218,7 +306,7 @@ "main": { "0": [ { - "node": "Assert Length", + "node": "[object Object]", "type": "main", "index": 0 } @@ -229,7 +317,7 @@ "main": { "0": [ { - "node": "Assert Slice Length", + "node": "[object Object]", "type": "main", "index": 0 } @@ -240,7 +328,7 @@ "main": { "0": [ { - "node": "Assert Slice", + "node": "[object Object]", "type": "main", "index": 0 } @@ -251,12 +339,7 @@ "main": { "0": [ { - "node": "Assert Find Result", - "type": "main", - "index": 0 - }, - { - "node": "Assert Found Flag", + "node": "[object Object]", "type": "main", "index": 0 } @@ -264,14 +347,13 @@ } } }, - "triggers": [ - { - "nodeId": "test_concat", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered List Plugins Test Suite workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/logic_plugins_test/workflow.backup.json b/workflow/examples/python/logic_plugins_test/workflow.backup.json new file mode 100644 index 000000000..6b7908277 --- /dev/null +++ b/workflow/examples/python/logic_plugins_test/workflow.backup.json @@ -0,0 +1,342 @@ +{ + "name": "Logic Plugins Test Suite", + "active": false, + "nodes": [ + { + "id": "test_and_true", + "name": "Test AND (all true)", + "type": "logic.and", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": { + "values": [ + true, + true, + true + ] + } + }, + { + "id": "assert_and_true", + "name": "Assert AND result is true", + "type": "test.assert_true", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": { + "value": "$test_and_true.result", + "message": "logic.and with all true values should return true" + } + }, + { + "id": "test_and_false", + "name": "Test AND (with false)", + "type": "logic.and", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "values": [ + true, + false, + true + ] + } + }, + { + "id": "assert_and_false", + "name": "Assert AND result is false", + "type": "test.assert_false", + "typeVersion": 1, + "position": [ + 300, + 100 + ], + "parameters": { + "value": "$test_and_false.result", + "message": "logic.and with any false value should return false" + } + }, + { + "id": "test_or_true", + "name": "Test OR (with true)", + "type": "logic.or", + "typeVersion": 1, + "position": [ + 0, + 200 + ], + "parameters": { + "values": [ + false, + false, + true + ] + } + }, + { + "id": "assert_or_true", + "name": "Assert OR result is true", + "type": "test.assert_true", + "typeVersion": 1, + "position": [ + 300, + 200 + ], + "parameters": { + "value": "$test_or_true.result", + "message": "logic.or with any true value should return true" + } + }, + { + "id": "test_or_false", + "name": "Test OR (all false)", + "type": "logic.or", + "typeVersion": 1, + "position": [ + 0, + 300 + ], + "parameters": { + "values": [ + false, + false, + false + ] + } + }, + { + "id": "assert_or_false", + "name": "Assert OR result is false", + "type": "test.assert_false", + "typeVersion": 1, + "position": [ + 300, + 300 + ], + "parameters": { + "value": "$test_or_false.result", + "message": "logic.or with all false values should return false" + } + }, + { + "id": "test_equals_true", + "name": "Test Equals (same)", + "type": "logic.equals", + "typeVersion": 1, + "position": [ + 0, + 400 + ], + "parameters": { + "a": 42, + "b": 42 + } + }, + { + "id": "assert_equals_true", + "name": "Assert Equals is true", + "type": "test.assert_true", + "typeVersion": 1, + "position": [ + 300, + 400 + ], + "parameters": { + "value": "$test_equals_true.result", + "message": "logic.equals with same values should return true" + } + }, + { + "id": "test_equals_false", + "name": "Test Equals (different)", + "type": "logic.equals", + "typeVersion": 1, + "position": [ + 0, + 500 + ], + "parameters": { + "a": 42, + "b": 24 + } + }, + { + "id": "assert_equals_false", + "name": "Assert Equals is false", + "type": "test.assert_false", + "typeVersion": 1, + "position": [ + 300, + 500 + ], + "parameters": { + "value": "$test_equals_false.result", + "message": "logic.equals with different values should return false" + } + }, + { + "id": "test_gt", + "name": "Test Greater Than", + "type": "logic.gt", + "typeVersion": 1, + "position": [ + 0, + 600 + ], + "parameters": { + "a": 10, + "b": 5 + } + }, + { + "id": "assert_gt", + "name": "Assert GT is true", + "type": "test.assert_true", + "typeVersion": 1, + "position": [ + 300, + 600 + ], + "parameters": { + "value": "$test_gt.result", + "message": "logic.gt should return true when a > b" + } + }, + { + "id": "test_lt", + "name": "Test Less Than", + "type": "logic.lt", + "typeVersion": 1, + "position": [ + 0, + 700 + ], + "parameters": { + "a": 3, + "b": 7 + } + }, + { + "id": "assert_lt", + "name": "Assert LT is true", + "type": "test.assert_true", + "typeVersion": 1, + "position": [ + 300, + 700 + ], + "parameters": { + "value": "$test_lt.result", + "message": "logic.lt should return true when a < b" + } + } + ], + "connections": { + "Test AND (all true)": { + "main": { + "0": [ + { + "node": "Assert AND result is true", + "type": "main", + "index": 0 + } + ] + } + }, + "Test AND (with false)": { + "main": { + "0": [ + { + "node": "Assert AND result is false", + "type": "main", + "index": 0 + } + ] + } + }, + "Test OR (with true)": { + "main": { + "0": [ + { + "node": "Assert OR result is true", + "type": "main", + "index": 0 + } + ] + } + }, + "Test OR (all false)": { + "main": { + "0": [ + { + "node": "Assert OR result is false", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Equals (same)": { + "main": { + "0": [ + { + "node": "Assert Equals is true", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Equals (different)": { + "main": { + "0": [ + { + "node": "Assert Equals is false", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Greater Than": { + "main": { + "0": [ + { + "node": "Assert GT is true", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Less Than": { + "main": { + "0": [ + { + "node": "Assert LT is true", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "test_and_true", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered Logic Plugins Test Suite workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/logic_plugins_test/workflow.json b/workflow/examples/python/logic_plugins_test/workflow.json index 6b7908277..55a148524 100644 --- a/workflow/examples/python/logic_plugins_test/workflow.json +++ b/workflow/examples/python/logic_plugins_test/workflow.json @@ -4,280 +4,408 @@ "nodes": [ { "id": "test_and_true", - "name": "Test AND (all true)", + "name": "Test And True", "type": "logic.and", "typeVersion": 1, "position": [ - 0, - 0 + 100, + 100 ], "parameters": { - "values": [ - true, - true, - true - ] + "name": "Test AND (all true)", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": { + "values": [ + true, + true, + true + ] + } } }, { "id": "assert_and_true", - "name": "Assert AND result is true", + "name": "Assert And True", "type": "test.assert_true", "typeVersion": 1, "position": [ - 300, - 0 + 400, + 100 ], "parameters": { - "value": "$test_and_true.result", - "message": "logic.and with all true values should return true" + "name": "Assert AND result is true", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": { + "value": "$test_and_true.result", + "message": "logic.and with all true values should return true" + } } }, { "id": "test_and_false", - "name": "Test AND (with false)", + "name": "Test And False", "type": "logic.and", "typeVersion": 1, "position": [ - 0, + 700, 100 ], "parameters": { - "values": [ - true, - false, - true - ] + "name": "Test AND (with false)", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "values": [ + true, + false, + true + ] + } } }, { "id": "assert_and_false", - "name": "Assert AND result is false", + "name": "Assert And False", "type": "test.assert_false", "typeVersion": 1, "position": [ - 300, - 100 + 100, + 300 ], "parameters": { - "value": "$test_and_false.result", - "message": "logic.and with any false value should return false" + "name": "Assert AND result is false", + "typeVersion": 1, + "position": [ + 300, + 100 + ], + "parameters": { + "value": "$test_and_false.result", + "message": "logic.and with any false value should return false" + } } }, { "id": "test_or_true", - "name": "Test OR (with true)", + "name": "Test Or True", "type": "logic.or", "typeVersion": 1, "position": [ - 0, - 200 + 400, + 300 ], "parameters": { - "values": [ - false, - false, - true - ] + "name": "Test OR (with true)", + "typeVersion": 1, + "position": [ + 0, + 200 + ], + "parameters": { + "values": [ + false, + false, + true + ] + } } }, { "id": "assert_or_true", - "name": "Assert OR result is true", + "name": "Assert Or True", "type": "test.assert_true", "typeVersion": 1, "position": [ - 300, - 200 + 700, + 300 ], "parameters": { - "value": "$test_or_true.result", - "message": "logic.or with any true value should return true" + "name": "Assert OR result is true", + "typeVersion": 1, + "position": [ + 300, + 200 + ], + "parameters": { + "value": "$test_or_true.result", + "message": "logic.or with any true value should return true" + } } }, { "id": "test_or_false", - "name": "Test OR (all false)", + "name": "Test Or False", "type": "logic.or", "typeVersion": 1, "position": [ - 0, - 300 + 100, + 500 ], "parameters": { - "values": [ - false, - false, - false - ] + "name": "Test OR (all false)", + "typeVersion": 1, + "position": [ + 0, + 300 + ], + "parameters": { + "values": [ + false, + false, + false + ] + } } }, { "id": "assert_or_false", - "name": "Assert OR result is false", + "name": "Assert Or False", "type": "test.assert_false", "typeVersion": 1, "position": [ - 300, - 300 + 400, + 500 ], "parameters": { - "value": "$test_or_false.result", - "message": "logic.or with all false values should return false" + "name": "Assert OR result is false", + "typeVersion": 1, + "position": [ + 300, + 300 + ], + "parameters": { + "value": "$test_or_false.result", + "message": "logic.or with all false values should return false" + } } }, { "id": "test_equals_true", - "name": "Test Equals (same)", + "name": "Test Equals True", "type": "logic.equals", "typeVersion": 1, "position": [ - 0, - 400 + 700, + 500 ], "parameters": { - "a": 42, - "b": 42 + "name": "Test Equals (same)", + "typeVersion": 1, + "position": [ + 0, + 400 + ], + "parameters": { + "a": 42, + "b": 42 + } } }, { "id": "assert_equals_true", - "name": "Assert Equals is true", + "name": "Assert Equals True", "type": "test.assert_true", "typeVersion": 1, "position": [ - 300, - 400 + 100, + 700 ], "parameters": { - "value": "$test_equals_true.result", - "message": "logic.equals with same values should return true" + "name": "Assert Equals is true", + "typeVersion": 1, + "position": [ + 300, + 400 + ], + "parameters": { + "value": "$test_equals_true.result", + "message": "logic.equals with same values should return true" + } } }, { "id": "test_equals_false", - "name": "Test Equals (different)", + "name": "Test Equals False", "type": "logic.equals", "typeVersion": 1, "position": [ - 0, - 500 + 400, + 700 ], "parameters": { - "a": 42, - "b": 24 + "name": "Test Equals (different)", + "typeVersion": 1, + "position": [ + 0, + 500 + ], + "parameters": { + "a": 42, + "b": 24 + } } }, { "id": "assert_equals_false", - "name": "Assert Equals is false", + "name": "Assert Equals False", "type": "test.assert_false", "typeVersion": 1, "position": [ - 300, - 500 + 700, + 700 ], "parameters": { - "value": "$test_equals_false.result", - "message": "logic.equals with different values should return false" + "name": "Assert Equals is false", + "typeVersion": 1, + "position": [ + 300, + 500 + ], + "parameters": { + "value": "$test_equals_false.result", + "message": "logic.equals with different values should return false" + } } }, { "id": "test_gt", - "name": "Test Greater Than", + "name": "Test Gt", "type": "logic.gt", "typeVersion": 1, "position": [ - 0, - 600 + 100, + 900 ], "parameters": { - "a": 10, - "b": 5 + "name": "Test Greater Than", + "typeVersion": 1, + "position": [ + 0, + 600 + ], + "parameters": { + "a": 10, + "b": 5 + } } }, { "id": "assert_gt", - "name": "Assert GT is true", + "name": "Assert Gt", "type": "test.assert_true", "typeVersion": 1, "position": [ - 300, - 600 + 400, + 900 ], "parameters": { - "value": "$test_gt.result", - "message": "logic.gt should return true when a > b" + "name": "Assert GT is true", + "typeVersion": 1, + "position": [ + 300, + 600 + ], + "parameters": { + "value": "$test_gt.result", + "message": "logic.gt should return true when a > b" + } } }, { "id": "test_lt", - "name": "Test Less Than", + "name": "Test Lt", "type": "logic.lt", "typeVersion": 1, "position": [ - 0, - 700 + 700, + 900 ], "parameters": { - "a": 3, - "b": 7 + "name": "Test Less Than", + "typeVersion": 1, + "position": [ + 0, + 700 + ], + "parameters": { + "a": 3, + "b": 7 + } } }, { "id": "assert_lt", - "name": "Assert LT is true", + "name": "Assert Lt", "type": "test.assert_true", "typeVersion": 1, "position": [ - 300, - 700 + 100, + 1100 ], "parameters": { - "value": "$test_lt.result", - "message": "logic.lt should return true when a < b" + "name": "Assert LT is true", + "typeVersion": 1, + "position": [ + 300, + 700 + ], + "parameters": { + "value": "$test_lt.result", + "message": "logic.lt should return true when a < b" + } } } ], "connections": { - "Test AND (all true)": { + "Test And (all True)": { "main": { "0": [ { - "node": "Assert AND result is true", + "node": "[object Object]", "type": "main", "index": 0 } ] } }, - "Test AND (with false)": { + "Test And (with False)": { "main": { "0": [ { - "node": "Assert AND result is false", + "node": "[object Object]", "type": "main", "index": 0 } ] } }, - "Test OR (with true)": { + "Test Or (with True)": { "main": { "0": [ { - "node": "Assert OR result is true", + "node": "[object Object]", "type": "main", "index": 0 } ] } }, - "Test OR (all false)": { + "Test Or (all False)": { "main": { "0": [ { - "node": "Assert OR result is false", + "node": "[object Object]", "type": "main", "index": 0 } @@ -288,7 +416,7 @@ "main": { "0": [ { - "node": "Assert Equals is true", + "node": "[object Object]", "type": "main", "index": 0 } @@ -299,7 +427,7 @@ "main": { "0": [ { - "node": "Assert Equals is false", + "node": "[object Object]", "type": "main", "index": 0 } @@ -310,7 +438,7 @@ "main": { "0": [ { - "node": "Assert GT is true", + "node": "[object Object]", "type": "main", "index": 0 } @@ -321,7 +449,7 @@ "main": { "0": [ { - "node": "Assert LT is true", + "node": "[object Object]", "type": "main", "index": 0 } @@ -329,14 +457,13 @@ } } }, - "triggers": [ - { - "nodeId": "test_and_true", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered Logic Plugins Test Suite workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/math_plugins_test/workflow.backup.json b/workflow/examples/python/math_plugins_test/workflow.backup.json new file mode 100644 index 000000000..98a52f1ba --- /dev/null +++ b/workflow/examples/python/math_plugins_test/workflow.backup.json @@ -0,0 +1,276 @@ +{ + "name": "Math Plugins Test Suite", + "active": false, + "nodes": [ + { + "id": "test_add", + "name": "Test Add", + "type": "math.add", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": { + "numbers": [ + 1, + 2, + 3, + 4, + 5 + ] + } + }, + { + "id": "assert_add", + "name": "Assert Add equals 15", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": { + "actual": "$test_add.result", + "expected": 15, + "message": "math.add should sum all numbers" + } + }, + { + "id": "test_multiply", + "name": "Test Multiply", + "type": "math.multiply", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "numbers": [ + 2, + 3, + 4 + ] + } + }, + { + "id": "assert_multiply", + "name": "Assert Multiply equals 24", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 100 + ], + "parameters": { + "actual": "$test_multiply.result", + "expected": 24, + "message": "math.multiply should multiply all numbers" + } + }, + { + "id": "test_subtract", + "name": "Test Subtract", + "type": "math.subtract", + "typeVersion": 1, + "position": [ + 0, + 200 + ], + "parameters": { + "a": 10, + "b": 3 + } + }, + { + "id": "assert_subtract", + "name": "Assert Subtract equals 7", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 200 + ], + "parameters": { + "actual": "$test_subtract.result", + "expected": 7, + "message": "math.subtract should return a - b" + } + }, + { + "id": "test_divide", + "name": "Test Divide", + "type": "math.divide", + "typeVersion": 1, + "position": [ + 0, + 300 + ], + "parameters": { + "a": 20, + "b": 4 + } + }, + { + "id": "assert_divide", + "name": "Assert Divide equals 5", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 300 + ], + "parameters": { + "actual": "$test_divide.result", + "expected": 5, + "message": "math.divide should return a / b" + } + }, + { + "id": "test_max", + "name": "Test Max", + "type": "math.max", + "typeVersion": 1, + "position": [ + 0, + 400 + ], + "parameters": { + "numbers": [ + 3, + 7, + 2, + 9, + 1 + ] + } + }, + { + "id": "assert_max", + "name": "Assert Max equals 9", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 400 + ], + "parameters": { + "actual": "$test_max.result", + "expected": 9, + "message": "math.max should return maximum value" + } + }, + { + "id": "test_min", + "name": "Test Min", + "type": "math.min", + "typeVersion": 1, + "position": [ + 0, + 500 + ], + "parameters": { + "numbers": [ + 3, + 7, + 2, + 9, + 1 + ] + } + }, + { + "id": "assert_min", + "name": "Assert Min equals 1", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 500 + ], + "parameters": { + "actual": "$test_min.result", + "expected": 1, + "message": "math.min should return minimum value" + } + } + ], + "connections": { + "Test Add": { + "main": { + "0": [ + { + "node": "Assert Add equals 15", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Multiply": { + "main": { + "0": [ + { + "node": "Assert Multiply equals 24", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Subtract": { + "main": { + "0": [ + { + "node": "Assert Subtract equals 7", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Divide": { + "main": { + "0": [ + { + "node": "Assert Divide equals 5", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Max": { + "main": { + "0": [ + { + "node": "Assert Max equals 9", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Min": { + "main": { + "0": [ + { + "node": "Assert Min equals 1", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "test_add", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered Math Plugins Test Suite workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/math_plugins_test/workflow.json b/workflow/examples/python/math_plugins_test/workflow.json index 98a52f1ba..82d32247c 100644 --- a/workflow/examples/python/math_plugins_test/workflow.json +++ b/workflow/examples/python/math_plugins_test/workflow.json @@ -8,32 +8,48 @@ "type": "math.add", "typeVersion": 1, "position": [ - 0, - 0 + 100, + 100 ], "parameters": { - "numbers": [ - 1, - 2, - 3, - 4, - 5 - ] + "name": "Test Add", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": { + "numbers": [ + 1, + 2, + 3, + 4, + 5 + ] + } } }, { "id": "assert_add", - "name": "Assert Add equals 15", + "name": "Assert Add", "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 0 + 400, + 100 ], "parameters": { - "actual": "$test_add.result", - "expected": 15, - "message": "math.add should sum all numbers" + "name": "Assert Add equals 15", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": { + "actual": "$test_add.result", + "expected": 15, + "message": "math.add should sum all numbers" + } } }, { @@ -42,30 +58,46 @@ "type": "math.multiply", "typeVersion": 1, "position": [ - 0, + 700, 100 ], "parameters": { - "numbers": [ - 2, - 3, - 4 - ] + "name": "Test Multiply", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "numbers": [ + 2, + 3, + 4 + ] + } } }, { "id": "assert_multiply", - "name": "Assert Multiply equals 24", + "name": "Assert Multiply", "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 100 + 100, + 300 ], "parameters": { - "actual": "$test_multiply.result", - "expected": 24, - "message": "math.multiply should multiply all numbers" + "name": "Assert Multiply equals 24", + "typeVersion": 1, + "position": [ + 300, + 100 + ], + "parameters": { + "actual": "$test_multiply.result", + "expected": 24, + "message": "math.multiply should multiply all numbers" + } } }, { @@ -74,27 +106,43 @@ "type": "math.subtract", "typeVersion": 1, "position": [ - 0, - 200 + 400, + 300 ], "parameters": { - "a": 10, - "b": 3 + "name": "Test Subtract", + "typeVersion": 1, + "position": [ + 0, + 200 + ], + "parameters": { + "a": 10, + "b": 3 + } } }, { "id": "assert_subtract", - "name": "Assert Subtract equals 7", + "name": "Assert Subtract", "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 200 + 700, + 300 ], "parameters": { - "actual": "$test_subtract.result", - "expected": 7, - "message": "math.subtract should return a - b" + "name": "Assert Subtract equals 7", + "typeVersion": 1, + "position": [ + 300, + 200 + ], + "parameters": { + "actual": "$test_subtract.result", + "expected": 7, + "message": "math.subtract should return a - b" + } } }, { @@ -103,27 +151,43 @@ "type": "math.divide", "typeVersion": 1, "position": [ - 0, - 300 + 100, + 500 ], "parameters": { - "a": 20, - "b": 4 + "name": "Test Divide", + "typeVersion": 1, + "position": [ + 0, + 300 + ], + "parameters": { + "a": 20, + "b": 4 + } } }, { "id": "assert_divide", - "name": "Assert Divide equals 5", + "name": "Assert Divide", "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 300 + 400, + 500 ], "parameters": { - "actual": "$test_divide.result", - "expected": 5, - "message": "math.divide should return a / b" + "name": "Assert Divide equals 5", + "typeVersion": 1, + "position": [ + 300, + 300 + ], + "parameters": { + "actual": "$test_divide.result", + "expected": 5, + "message": "math.divide should return a / b" + } } }, { @@ -132,32 +196,48 @@ "type": "math.max", "typeVersion": 1, "position": [ - 0, - 400 + 700, + 500 ], "parameters": { - "numbers": [ - 3, - 7, - 2, - 9, - 1 - ] + "name": "Test Max", + "typeVersion": 1, + "position": [ + 0, + 400 + ], + "parameters": { + "numbers": [ + 3, + 7, + 2, + 9, + 1 + ] + } } }, { "id": "assert_max", - "name": "Assert Max equals 9", + "name": "Assert Max", "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 400 + 100, + 700 ], "parameters": { - "actual": "$test_max.result", - "expected": 9, - "message": "math.max should return maximum value" + "name": "Assert Max equals 9", + "typeVersion": 1, + "position": [ + 300, + 400 + ], + "parameters": { + "actual": "$test_max.result", + "expected": 9, + "message": "math.max should return maximum value" + } } }, { @@ -166,32 +246,48 @@ "type": "math.min", "typeVersion": 1, "position": [ - 0, - 500 + 400, + 700 ], "parameters": { - "numbers": [ - 3, - 7, - 2, - 9, - 1 - ] + "name": "Test Min", + "typeVersion": 1, + "position": [ + 0, + 500 + ], + "parameters": { + "numbers": [ + 3, + 7, + 2, + 9, + 1 + ] + } } }, { "id": "assert_min", - "name": "Assert Min equals 1", + "name": "Assert Min", "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 500 + 700, + 700 ], "parameters": { - "actual": "$test_min.result", - "expected": 1, - "message": "math.min should return minimum value" + "name": "Assert Min equals 1", + "typeVersion": 1, + "position": [ + 300, + 500 + ], + "parameters": { + "actual": "$test_min.result", + "expected": 1, + "message": "math.min should return minimum value" + } } } ], @@ -200,7 +296,7 @@ "main": { "0": [ { - "node": "Assert Add equals 15", + "node": "[object Object]", "type": "main", "index": 0 } @@ -211,7 +307,7 @@ "main": { "0": [ { - "node": "Assert Multiply equals 24", + "node": "[object Object]", "type": "main", "index": 0 } @@ -222,7 +318,7 @@ "main": { "0": [ { - "node": "Assert Subtract equals 7", + "node": "[object Object]", "type": "main", "index": 0 } @@ -233,7 +329,7 @@ "main": { "0": [ { - "node": "Assert Divide equals 5", + "node": "[object Object]", "type": "main", "index": 0 } @@ -244,7 +340,7 @@ "main": { "0": [ { - "node": "Assert Max equals 9", + "node": "[object Object]", "type": "main", "index": 0 } @@ -255,7 +351,7 @@ "main": { "0": [ { - "node": "Assert Min equals 1", + "node": "[object Object]", "type": "main", "index": 0 } @@ -263,14 +359,13 @@ } } }, - "triggers": [ - { - "nodeId": "test_add", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered Math Plugins Test Suite workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/plan_execute_summarize/workflow.backup.json b/workflow/examples/python/plan_execute_summarize/workflow.backup.json new file mode 100644 index 000000000..cb3f31752 --- /dev/null +++ b/workflow/examples/python/plan_execute_summarize/workflow.backup.json @@ -0,0 +1,184 @@ +{ + "name": "meta.workflow_packages.plan_execute_summarize.label", + "active": false, + "nodes": [ + { + "id": "load_context", + "name": "Load Context", + "type": "core.load_context", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": {} + }, + { + "id": "seed_messages", + "name": "Seed Messages", + "type": "core.seed_messages", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": {} + }, + { + "id": "append_context", + "name": "Append Context", + "type": "core.append_context_message", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "messages": "$messages", + "context": "$sdlc_context" + } + }, + { + "id": "append_user_instruction", + "name": "Append User Instruction", + "type": "core.append_user_instruction", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "messages": "$messages" + } + }, + { + "id": "planner_request", + "name": "Planner Request", + "type": "core.ai_request", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": { + "messages": "$messages" + } + }, + { + "id": "run_tool_calls", + "name": "Run Tool Calls", + "type": "core.run_tool_calls", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": { + "response": "$llm_response" + } + }, + { + "id": "append_tool_results", + "name": "Append Tool Results", + "type": "core.append_tool_results", + "typeVersion": 1, + "position": [ + 1800, + 50 + ], + "parameters": { + "messages": "$messages", + "tool_results": "$tool_results" + } + }, + { + "id": "summary_request", + "name": "Summary Request", + "type": "core.ai_request", + "typeVersion": 1, + "position": [ + 2100, + 50 + ], + "parameters": { + "messages": "$messages" + } + } + ], + "connections": { + "Append Tool Results": { + "main": { + "0": [ + { + "node": "Append Context", + "type": "main", + "index": 0 + }, + { + "node": "Append User Instruction", + "type": "main", + "index": 0 + }, + { + "node": "Planner Request", + "type": "main", + "index": 0 + }, + { + "node": "Append Tool Results", + "type": "main", + "index": 0 + }, + { + "node": "Summary Request", + "type": "main", + "index": 0 + } + ] + } + }, + "Load Context": { + "main": { + "0": [ + { + "node": "Append Context", + "type": "main", + "index": 0 + } + ] + } + }, + "Planner Request": { + "main": { + "0": [ + { + "node": "Run Tool Calls", + "type": "main", + "index": 0 + } + ] + } + }, + "Run Tool Calls": { + "main": { + "0": [ + { + "node": "Append Tool Results", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "load_context", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered meta.workflow_packages.plan_execute_summarize.label workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/plan_execute_summarize/workflow.json b/workflow/examples/python/plan_execute_summarize/workflow.json index cb3f31752..81c197768 100644 --- a/workflow/examples/python/plan_execute_summarize/workflow.json +++ b/workflow/examples/python/plan_execute_summarize/workflow.json @@ -8,10 +8,18 @@ "type": "core.load_context", "typeVersion": 1, "position": [ - 0, - 50 + 100, + 100 ], - "parameters": {} + "parameters": { + "name": "Load Context", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": {} + } }, { "id": "seed_messages", @@ -19,10 +27,18 @@ "type": "core.seed_messages", "typeVersion": 1, "position": [ - 300, - 50 + 400, + 100 ], - "parameters": {} + "parameters": { + "name": "Seed Messages", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": {} + } }, { "id": "append_context", @@ -30,12 +46,20 @@ "type": "core.append_context_message", "typeVersion": 1, "position": [ - 600, - 50 + 700, + 100 ], "parameters": { - "messages": "$messages", - "context": "$sdlc_context" + "name": "Append Context", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "messages": "$messages", + "context": "$sdlc_context" + } } }, { @@ -44,11 +68,19 @@ "type": "core.append_user_instruction", "typeVersion": 1, "position": [ - 900, - 50 + 100, + 300 ], "parameters": { - "messages": "$messages" + "name": "Append User Instruction", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "messages": "$messages" + } } }, { @@ -57,11 +89,19 @@ "type": "core.ai_request", "typeVersion": 1, "position": [ - 1200, - 50 + 400, + 300 ], "parameters": { - "messages": "$messages" + "name": "Planner Request", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": { + "messages": "$messages" + } } }, { @@ -70,11 +110,19 @@ "type": "core.run_tool_calls", "typeVersion": 1, "position": [ - 1500, - 50 + 700, + 300 ], "parameters": { - "response": "$llm_response" + "name": "Run Tool Calls", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": { + "response": "$llm_response" + } } }, { @@ -83,12 +131,20 @@ "type": "core.append_tool_results", "typeVersion": 1, "position": [ - 1800, - 50 + 100, + 500 ], "parameters": { - "messages": "$messages", - "tool_results": "$tool_results" + "name": "Append Tool Results", + "typeVersion": 1, + "position": [ + 1800, + 50 + ], + "parameters": { + "messages": "$messages", + "tool_results": "$tool_results" + } } }, { @@ -97,11 +153,19 @@ "type": "core.ai_request", "typeVersion": 1, "position": [ - 2100, - 50 + 400, + 500 ], "parameters": { - "messages": "$messages" + "name": "Summary Request", + "typeVersion": 1, + "position": [ + 2100, + 50 + ], + "parameters": { + "messages": "$messages" + } } } ], @@ -110,27 +174,7 @@ "main": { "0": [ { - "node": "Append Context", - "type": "main", - "index": 0 - }, - { - "node": "Append User Instruction", - "type": "main", - "index": 0 - }, - { - "node": "Planner Request", - "type": "main", - "index": 0 - }, - { - "node": "Append Tool Results", - "type": "main", - "index": 0 - }, - { - "node": "Summary Request", + "node": "[object Object]", "type": "main", "index": 0 } @@ -141,7 +185,7 @@ "main": { "0": [ { - "node": "Append Context", + "node": "[object Object]", "type": "main", "index": 0 } @@ -152,7 +196,7 @@ "main": { "0": [ { - "node": "Run Tool Calls", + "node": "[object Object]", "type": "main", "index": 0 } @@ -163,7 +207,7 @@ "main": { "0": [ { - "node": "Append Tool Results", + "node": "[object Object]", "type": "main", "index": 0 } @@ -171,14 +215,13 @@ } } }, - "triggers": [ - { - "nodeId": "load_context", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered meta.workflow_packages.plan_execute_summarize.label workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/repo_scan_context/workflow.backup.json b/workflow/examples/python/repo_scan_context/workflow.backup.json new file mode 100644 index 000000000..65efcb2ae --- /dev/null +++ b/workflow/examples/python/repo_scan_context/workflow.backup.json @@ -0,0 +1,219 @@ +{ + "name": "meta.workflow_packages.repo_scan_context.label", + "active": false, + "nodes": [ + { + "id": "list_files", + "name": "List Files", + "type": "tools.list_files", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": { + "path": "." + } + }, + { + "id": "filter_python", + "name": "Filter Python", + "type": "utils.filter_list", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": { + "items": "$repo_files", + "mode": "regex", + "pattern": "\\.py$" + } + }, + { + "id": "reduce_python", + "name": "Reduce Python", + "type": "utils.reduce_list", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "items": "$python_files", + "separator": "\\n" + } + }, + { + "id": "seed_messages", + "name": "Seed Messages", + "type": "core.seed_messages", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": {} + }, + { + "id": "append_repo_summary", + "name": "Append Repo Summary", + "type": "core.append_context_message", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": { + "messages": "$messages", + "context": "$python_summary" + } + }, + { + "id": "append_user_instruction", + "name": "Append User Instruction", + "type": "core.append_user_instruction", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": { + "messages": "$messages" + } + }, + { + "id": "ai_request", + "name": "Ai Request", + "type": "core.ai_request", + "typeVersion": 1, + "position": [ + 1800, + 50 + ], + "parameters": { + "messages": "$messages" + } + }, + { + "id": "run_tool_calls", + "name": "Run Tool Calls", + "type": "core.run_tool_calls", + "typeVersion": 1, + "position": [ + 2100, + 50 + ], + "parameters": { + "response": "$llm_response" + } + }, + { + "id": "append_tool_results", + "name": "Append Tool Results", + "type": "core.append_tool_results", + "typeVersion": 1, + "position": [ + 2400, + 50 + ], + "parameters": { + "messages": "$messages", + "tool_results": "$tool_results" + } + } + ], + "connections": { + "List Files": { + "main": { + "0": [ + { + "node": "Filter Python", + "type": "main", + "index": 0 + } + ] + } + }, + "Filter Python": { + "main": { + "0": [ + { + "node": "Reduce Python", + "type": "main", + "index": 0 + } + ] + } + }, + "Append Tool Results": { + "main": { + "0": [ + { + "node": "Append Repo Summary", + "type": "main", + "index": 0 + }, + { + "node": "Append User Instruction", + "type": "main", + "index": 0 + }, + { + "node": "Ai Request", + "type": "main", + "index": 0 + }, + { + "node": "Append Tool Results", + "type": "main", + "index": 0 + } + ] + } + }, + "Reduce Python": { + "main": { + "0": [ + { + "node": "Append Repo Summary", + "type": "main", + "index": 0 + } + ] + } + }, + "Ai Request": { + "main": { + "0": [ + { + "node": "Run Tool Calls", + "type": "main", + "index": 0 + } + ] + } + }, + "Run Tool Calls": { + "main": { + "0": [ + { + "node": "Append Tool Results", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "list_files", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered meta.workflow_packages.repo_scan_context.label workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/repo_scan_context/workflow.json b/workflow/examples/python/repo_scan_context/workflow.json index 65efcb2ae..f947840be 100644 --- a/workflow/examples/python/repo_scan_context/workflow.json +++ b/workflow/examples/python/repo_scan_context/workflow.json @@ -8,11 +8,19 @@ "type": "tools.list_files", "typeVersion": 1, "position": [ - 0, - 50 + 100, + 100 ], "parameters": { - "path": "." + "name": "List Files", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": { + "path": "." + } } }, { @@ -21,13 +29,21 @@ "type": "utils.filter_list", "typeVersion": 1, "position": [ - 300, - 50 + 400, + 100 ], "parameters": { - "items": "$repo_files", - "mode": "regex", - "pattern": "\\.py$" + "name": "Filter Python", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": { + "items": "$repo_files", + "mode": "regex", + "pattern": "\\.py$" + } } }, { @@ -36,12 +52,20 @@ "type": "utils.reduce_list", "typeVersion": 1, "position": [ - 600, - 50 + 700, + 100 ], "parameters": { - "items": "$python_files", - "separator": "\\n" + "name": "Reduce Python", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "items": "$python_files", + "separator": "\\n" + } } }, { @@ -50,10 +74,18 @@ "type": "core.seed_messages", "typeVersion": 1, "position": [ - 900, - 50 + 100, + 300 ], - "parameters": {} + "parameters": { + "name": "Seed Messages", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": {} + } }, { "id": "append_repo_summary", @@ -61,12 +93,20 @@ "type": "core.append_context_message", "typeVersion": 1, "position": [ - 1200, - 50 + 400, + 300 ], "parameters": { - "messages": "$messages", - "context": "$python_summary" + "name": "Append Repo Summary", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": { + "messages": "$messages", + "context": "$python_summary" + } } }, { @@ -75,11 +115,19 @@ "type": "core.append_user_instruction", "typeVersion": 1, "position": [ - 1500, - 50 + 700, + 300 ], "parameters": { - "messages": "$messages" + "name": "Append User Instruction", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": { + "messages": "$messages" + } } }, { @@ -88,11 +136,19 @@ "type": "core.ai_request", "typeVersion": 1, "position": [ - 1800, - 50 + 100, + 500 ], "parameters": { - "messages": "$messages" + "name": "Ai Request", + "typeVersion": 1, + "position": [ + 1800, + 50 + ], + "parameters": { + "messages": "$messages" + } } }, { @@ -101,11 +157,19 @@ "type": "core.run_tool_calls", "typeVersion": 1, "position": [ - 2100, - 50 + 400, + 500 ], "parameters": { - "response": "$llm_response" + "name": "Run Tool Calls", + "typeVersion": 1, + "position": [ + 2100, + 50 + ], + "parameters": { + "response": "$llm_response" + } } }, { @@ -114,12 +178,20 @@ "type": "core.append_tool_results", "typeVersion": 1, "position": [ - 2400, - 50 + 700, + 500 ], "parameters": { - "messages": "$messages", - "tool_results": "$tool_results" + "name": "Append Tool Results", + "typeVersion": 1, + "position": [ + 2400, + 50 + ], + "parameters": { + "messages": "$messages", + "tool_results": "$tool_results" + } } } ], @@ -128,7 +200,7 @@ "main": { "0": [ { - "node": "Filter Python", + "node": "[object Object]", "type": "main", "index": 0 } @@ -139,7 +211,7 @@ "main": { "0": [ { - "node": "Reduce Python", + "node": "[object Object]", "type": "main", "index": 0 } @@ -150,22 +222,7 @@ "main": { "0": [ { - "node": "Append Repo Summary", - "type": "main", - "index": 0 - }, - { - "node": "Append User Instruction", - "type": "main", - "index": 0 - }, - { - "node": "Ai Request", - "type": "main", - "index": 0 - }, - { - "node": "Append Tool Results", + "node": "[object Object]", "type": "main", "index": 0 } @@ -176,7 +233,7 @@ "main": { "0": [ { - "node": "Append Repo Summary", + "node": "[object Object]", "type": "main", "index": 0 } @@ -187,7 +244,7 @@ "main": { "0": [ { - "node": "Run Tool Calls", + "node": "[object Object]", "type": "main", "index": 0 } @@ -198,7 +255,7 @@ "main": { "0": [ { - "node": "Append Tool Results", + "node": "[object Object]", "type": "main", "index": 0 } @@ -206,14 +263,13 @@ } } }, - "triggers": [ - { - "nodeId": "list_files", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered meta.workflow_packages.repo_scan_context.label workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/single_pass/workflow.backup.json b/workflow/examples/python/single_pass/workflow.backup.json new file mode 100644 index 000000000..1459d6d9d --- /dev/null +++ b/workflow/examples/python/single_pass/workflow.backup.json @@ -0,0 +1,161 @@ +{ + "name": "Single Pass", + "active": false, + "nodes": [ + { + "id": "load_context", + "name": "Load Context", + "type": "core.load_context", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": {} + }, + { + "id": "seed_messages", + "name": "Seed Messages", + "type": "core.seed_messages", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": {} + }, + { + "id": "append_context", + "name": "Append Context", + "type": "core.append_context_message", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": {} + }, + { + "id": "append_user_instruction", + "name": "Append User Instruction", + "type": "core.append_user_instruction", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": {} + }, + { + "id": "ai_request", + "name": "AI Request", + "type": "core.ai_request", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": {} + }, + { + "id": "run_tool_calls", + "name": "Run Tool Calls", + "type": "core.run_tool_calls", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": {} + }, + { + "id": "append_tool_results", + "name": "Append Tool Results", + "type": "core.append_tool_results", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": {} + } + ], + "connections": { + "Load Context": { + "main": { + "0": [ + { + "node": "Append Context", + "type": "main", + "index": 0 + } + ] + } + }, + "Seed Messages": { + "main": { + "0": [ + { + "node": "Append Context", + "type": "main", + "index": 0 + } + ] + } + }, + "Append Context": { + "main": { + "0": [ + { + "node": "Append User Instruction", + "type": "main", + "index": 0 + } + ] + } + }, + "Append User Instruction": { + "main": { + "0": [ + { + "node": "AI Request", + "type": "main", + "index": 0 + } + ] + } + }, + "AI Request": { + "main": { + "0": [ + { + "node": "Run Tool Calls", + "type": "main", + "index": 0 + } + ] + } + }, + "Run Tool Calls": { + "main": { + "0": [ + { + "node": "Append Tool Results", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "load_context", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered single-pass workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/single_pass/workflow.json b/workflow/examples/python/single_pass/workflow.json index 1459d6d9d..52a65f172 100644 --- a/workflow/examples/python/single_pass/workflow.json +++ b/workflow/examples/python/single_pass/workflow.json @@ -8,10 +8,18 @@ "type": "core.load_context", "typeVersion": 1, "position": [ - 0, - 0 + 100, + 100 ], - "parameters": {} + "parameters": { + "name": "Load Context", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": {} + } }, { "id": "seed_messages", @@ -19,10 +27,18 @@ "type": "core.seed_messages", "typeVersion": 1, "position": [ - 0, + 400, 100 ], - "parameters": {} + "parameters": { + "name": "Seed Messages", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": {} + } }, { "id": "append_context", @@ -30,10 +46,18 @@ "type": "core.append_context_message", "typeVersion": 1, "position": [ - 300, - 50 + 700, + 100 ], - "parameters": {} + "parameters": { + "name": "Append Context", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": {} + } }, { "id": "append_user_instruction", @@ -41,21 +65,37 @@ "type": "core.append_user_instruction", "typeVersion": 1, "position": [ - 600, - 50 + 100, + 300 ], - "parameters": {} + "parameters": { + "name": "Append User Instruction", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": {} + } }, { "id": "ai_request", - "name": "AI Request", + "name": "Ai Request", "type": "core.ai_request", "typeVersion": 1, "position": [ - 900, - 50 + 400, + 300 ], - "parameters": {} + "parameters": { + "name": "AI Request", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": {} + } }, { "id": "run_tool_calls", @@ -63,10 +103,18 @@ "type": "core.run_tool_calls", "typeVersion": 1, "position": [ - 1200, - 50 + 700, + 300 ], - "parameters": {} + "parameters": { + "name": "Run Tool Calls", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": {} + } }, { "id": "append_tool_results", @@ -74,10 +122,18 @@ "type": "core.append_tool_results", "typeVersion": 1, "position": [ - 1500, - 50 + 100, + 500 ], - "parameters": {} + "parameters": { + "name": "Append Tool Results", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": {} + } } ], "connections": { @@ -85,7 +141,7 @@ "main": { "0": [ { - "node": "Append Context", + "node": "[object Object]", "type": "main", "index": 0 } @@ -96,7 +152,7 @@ "main": { "0": [ { - "node": "Append Context", + "node": "[object Object]", "type": "main", "index": 0 } @@ -107,7 +163,7 @@ "main": { "0": [ { - "node": "Append User Instruction", + "node": "[object Object]", "type": "main", "index": 0 } @@ -118,18 +174,18 @@ "main": { "0": [ { - "node": "AI Request", + "node": "[object Object]", "type": "main", "index": 0 } ] } }, - "AI Request": { + "Ai Request": { "main": { "0": [ { - "node": "Run Tool Calls", + "node": "[object Object]", "type": "main", "index": 0 } @@ -140,7 +196,7 @@ "main": { "0": [ { - "node": "Append Tool Results", + "node": "[object Object]", "type": "main", "index": 0 } @@ -148,14 +204,13 @@ } } }, - "triggers": [ - { - "nodeId": "load_context", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered single-pass workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/string_plugins_test/workflow.backup.json b/workflow/examples/python/string_plugins_test/workflow.backup.json new file mode 100644 index 000000000..f05070387 --- /dev/null +++ b/workflow/examples/python/string_plugins_test/workflow.backup.json @@ -0,0 +1,242 @@ +{ + "name": "String Plugins Test Suite", + "active": false, + "nodes": [ + { + "id": "test_concat", + "name": "Test Concat", + "type": "string.concat", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": { + "strings": [ + "Hello", + "World" + ], + "separator": " " + } + }, + { + "id": "assert_concat", + "name": "Assert Concat", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": { + "actual": "$test_concat.result", + "expected": "Hello World", + "message": "string.concat should join strings" + } + }, + { + "id": "test_upper", + "name": "Test Upper", + "type": "string.upper", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "text": "hello" + } + }, + { + "id": "assert_upper", + "name": "Assert Upper", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 100 + ], + "parameters": { + "actual": "$test_upper.result", + "expected": "HELLO", + "message": "string.upper should uppercase text" + } + }, + { + "id": "test_lower", + "name": "Test Lower", + "type": "string.lower", + "typeVersion": 1, + "position": [ + 0, + 200 + ], + "parameters": { + "text": "WORLD" + } + }, + { + "id": "assert_lower", + "name": "Assert Lower", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 200 + ], + "parameters": { + "actual": "$test_lower.result", + "expected": "world", + "message": "string.lower should lowercase text" + } + }, + { + "id": "test_split", + "name": "Test Split", + "type": "string.split", + "typeVersion": 1, + "position": [ + 0, + 300 + ], + "parameters": { + "text": "a,b,c", + "separator": "," + } + }, + { + "id": "assert_split_length", + "name": "Assert Split Length", + "type": "list.length", + "typeVersion": 1, + "position": [ + 300, + 300 + ], + "parameters": { + "items": "$test_split.result" + } + }, + { + "id": "assert_split", + "name": "Assert Split Count", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 600, + 300 + ], + "parameters": { + "actual": "$assert_split_length.result", + "expected": 3, + "message": "string.split should split into array" + } + }, + { + "id": "test_length", + "name": "Test Length", + "type": "string.length", + "typeVersion": 1, + "position": [ + 0, + 400 + ], + "parameters": { + "text": "Hello" + } + }, + { + "id": "assert_length", + "name": "Assert Length", + "type": "test.assert_equals", + "typeVersion": 1, + "position": [ + 300, + 400 + ], + "parameters": { + "actual": "$test_length.result", + "expected": 5, + "message": "string.length should return character count" + } + } + ], + "connections": { + "Test Concat": { + "main": { + "0": [ + { + "node": "Assert Concat", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Upper": { + "main": { + "0": [ + { + "node": "Assert Upper", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Lower": { + "main": { + "0": [ + { + "node": "Assert Lower", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Split": { + "main": { + "0": [ + { + "node": "Assert Split Length", + "type": "main", + "index": 0 + } + ] + } + }, + "Assert Split Length": { + "main": { + "0": [ + { + "node": "Assert Split Count", + "type": "main", + "index": 0 + } + ] + } + }, + "Test Length": { + "main": { + "0": [ + { + "node": "Assert Length", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "test_concat", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered String Plugins Test Suite workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/string_plugins_test/workflow.json b/workflow/examples/python/string_plugins_test/workflow.json index f05070387..f6042da9e 100644 --- a/workflow/examples/python/string_plugins_test/workflow.json +++ b/workflow/examples/python/string_plugins_test/workflow.json @@ -8,15 +8,23 @@ "type": "string.concat", "typeVersion": 1, "position": [ - 0, - 0 + 100, + 100 ], "parameters": { - "strings": [ - "Hello", - "World" + "name": "Test Concat", + "typeVersion": 1, + "position": [ + 0, + 0 ], - "separator": " " + "parameters": { + "strings": [ + "Hello", + "World" + ], + "separator": " " + } } }, { @@ -25,13 +33,21 @@ "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 0 + 400, + 100 ], "parameters": { - "actual": "$test_concat.result", - "expected": "Hello World", - "message": "string.concat should join strings" + "name": "Assert Concat", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": { + "actual": "$test_concat.result", + "expected": "Hello World", + "message": "string.concat should join strings" + } } }, { @@ -40,11 +56,19 @@ "type": "string.upper", "typeVersion": 1, "position": [ - 0, + 700, 100 ], "parameters": { - "text": "hello" + "name": "Test Upper", + "typeVersion": 1, + "position": [ + 0, + 100 + ], + "parameters": { + "text": "hello" + } } }, { @@ -53,13 +77,21 @@ "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 100 + 100, + 300 ], "parameters": { - "actual": "$test_upper.result", - "expected": "HELLO", - "message": "string.upper should uppercase text" + "name": "Assert Upper", + "typeVersion": 1, + "position": [ + 300, + 100 + ], + "parameters": { + "actual": "$test_upper.result", + "expected": "HELLO", + "message": "string.upper should uppercase text" + } } }, { @@ -68,11 +100,19 @@ "type": "string.lower", "typeVersion": 1, "position": [ - 0, - 200 + 400, + 300 ], "parameters": { - "text": "WORLD" + "name": "Test Lower", + "typeVersion": 1, + "position": [ + 0, + 200 + ], + "parameters": { + "text": "WORLD" + } } }, { @@ -81,13 +121,21 @@ "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 200 + 700, + 300 ], "parameters": { - "actual": "$test_lower.result", - "expected": "world", - "message": "string.lower should lowercase text" + "name": "Assert Lower", + "typeVersion": 1, + "position": [ + 300, + 200 + ], + "parameters": { + "actual": "$test_lower.result", + "expected": "world", + "message": "string.lower should lowercase text" + } } }, { @@ -96,12 +144,20 @@ "type": "string.split", "typeVersion": 1, "position": [ - 0, - 300 + 100, + 500 ], "parameters": { - "text": "a,b,c", - "separator": "," + "name": "Test Split", + "typeVersion": 1, + "position": [ + 0, + 300 + ], + "parameters": { + "text": "a,b,c", + "separator": "," + } } }, { @@ -110,26 +166,42 @@ "type": "list.length", "typeVersion": 1, "position": [ - 300, - 300 + 400, + 500 ], "parameters": { - "items": "$test_split.result" + "name": "Assert Split Length", + "typeVersion": 1, + "position": [ + 300, + 300 + ], + "parameters": { + "items": "$test_split.result" + } } }, { "id": "assert_split", - "name": "Assert Split Count", + "name": "Assert Split", "type": "test.assert_equals", "typeVersion": 1, "position": [ - 600, - 300 + 700, + 500 ], "parameters": { - "actual": "$assert_split_length.result", - "expected": 3, - "message": "string.split should split into array" + "name": "Assert Split Count", + "typeVersion": 1, + "position": [ + 600, + 300 + ], + "parameters": { + "actual": "$assert_split_length.result", + "expected": 3, + "message": "string.split should split into array" + } } }, { @@ -138,11 +210,19 @@ "type": "string.length", "typeVersion": 1, "position": [ - 0, - 400 + 100, + 700 ], "parameters": { - "text": "Hello" + "name": "Test Length", + "typeVersion": 1, + "position": [ + 0, + 400 + ], + "parameters": { + "text": "Hello" + } } }, { @@ -151,13 +231,21 @@ "type": "test.assert_equals", "typeVersion": 1, "position": [ - 300, - 400 + 400, + 700 ], "parameters": { - "actual": "$test_length.result", - "expected": 5, - "message": "string.length should return character count" + "name": "Assert Length", + "typeVersion": 1, + "position": [ + 300, + 400 + ], + "parameters": { + "actual": "$test_length.result", + "expected": 5, + "message": "string.length should return character count" + } } } ], @@ -166,7 +254,7 @@ "main": { "0": [ { - "node": "Assert Concat", + "node": "[object Object]", "type": "main", "index": 0 } @@ -177,7 +265,7 @@ "main": { "0": [ { - "node": "Assert Upper", + "node": "[object Object]", "type": "main", "index": 0 } @@ -188,7 +276,7 @@ "main": { "0": [ { - "node": "Assert Lower", + "node": "[object Object]", "type": "main", "index": 0 } @@ -199,7 +287,7 @@ "main": { "0": [ { - "node": "Assert Split Length", + "node": "[object Object]", "type": "main", "index": 0 } @@ -210,7 +298,7 @@ "main": { "0": [ { - "node": "Assert Split Count", + "node": "[object Object]", "type": "main", "index": 0 } @@ -221,7 +309,7 @@ "main": { "0": [ { - "node": "Assert Length", + "node": "[object Object]", "type": "main", "index": 0 } @@ -229,14 +317,13 @@ } } }, - "triggers": [ - { - "nodeId": "test_concat", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered String Plugins Test Suite workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/testing_triangle/workflow.backup.json b/workflow/examples/python/testing_triangle/workflow.backup.json new file mode 100644 index 000000000..3d1b651ad --- /dev/null +++ b/workflow/examples/python/testing_triangle/workflow.backup.json @@ -0,0 +1,157 @@ +{ + "name": "meta.workflow_packages.testing_triangle.label", + "active": false, + "nodes": [ + { + "id": "lint", + "name": "Lint", + "type": "tools.run_lint", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": { + "path": "src" + } + }, + { + "id": "lint_failed", + "name": "Lint Failed", + "type": "utils.branch_condition", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": { + "value": "$lint_results", + "mode": "regex", + "compare": "(FAILED|ERROR)" + } + }, + { + "id": "lint_ok", + "name": "Lint Ok", + "type": "utils.not", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "value": "$lint_failed" + } + }, + { + "id": "unit_tests", + "name": "Unit Tests", + "type": "tools.run_tests", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "path": "tests" + } + }, + { + "id": "unit_failed", + "name": "Unit Failed", + "type": "utils.branch_condition", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": { + "value": "$unit_results", + "mode": "regex", + "compare": "(FAILED|ERROR)" + } + }, + { + "id": "unit_ok", + "name": "Unit Ok", + "type": "utils.not", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": { + "value": "$unit_failed" + } + }, + { + "id": "ui_tests", + "name": "Ui Tests", + "type": "tools.run_tests", + "typeVersion": 1, + "position": [ + 1800, + 50 + ], + "parameters": { + "path": "tests/ui" + } + } + ], + "connections": { + "Lint": { + "main": { + "0": [ + { + "node": "Lint Failed", + "type": "main", + "index": 0 + } + ] + } + }, + "Lint Failed": { + "main": { + "0": [ + { + "node": "Lint Ok", + "type": "main", + "index": 0 + } + ] + } + }, + "Unit Tests": { + "main": { + "0": [ + { + "node": "Unit Failed", + "type": "main", + "index": 0 + } + ] + } + }, + "Unit Failed": { + "main": { + "0": [ + { + "node": "Unit Ok", + "type": "main", + "index": 0 + } + ] + } + } + }, + "triggers": [ + { + "nodeId": "lint", + "kind": "manual", + "enabled": true, + "meta": { + "description": "Manually triggered meta.workflow_packages.testing_triangle.label workflow execution" + } + } + ] +} diff --git a/workflow/examples/python/testing_triangle/workflow.json b/workflow/examples/python/testing_triangle/workflow.json index 3d1b651ad..1cbbd19de 100644 --- a/workflow/examples/python/testing_triangle/workflow.json +++ b/workflow/examples/python/testing_triangle/workflow.json @@ -8,11 +8,19 @@ "type": "tools.run_lint", "typeVersion": 1, "position": [ - 0, - 50 + 100, + 100 ], "parameters": { - "path": "src" + "name": "Lint", + "typeVersion": 1, + "position": [ + 0, + 50 + ], + "parameters": { + "path": "src" + } } }, { @@ -21,13 +29,21 @@ "type": "utils.branch_condition", "typeVersion": 1, "position": [ - 300, - 50 + 400, + 100 ], "parameters": { - "value": "$lint_results", - "mode": "regex", - "compare": "(FAILED|ERROR)" + "name": "Lint Failed", + "typeVersion": 1, + "position": [ + 300, + 50 + ], + "parameters": { + "value": "$lint_results", + "mode": "regex", + "compare": "(FAILED|ERROR)" + } } }, { @@ -36,11 +52,19 @@ "type": "utils.not", "typeVersion": 1, "position": [ - 600, - 50 + 700, + 100 ], "parameters": { - "value": "$lint_failed" + "name": "Lint Ok", + "typeVersion": 1, + "position": [ + 600, + 50 + ], + "parameters": { + "value": "$lint_failed" + } } }, { @@ -49,11 +73,19 @@ "type": "tools.run_tests", "typeVersion": 1, "position": [ - 900, - 50 + 100, + 300 ], "parameters": { - "path": "tests" + "name": "Unit Tests", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": { + "path": "tests" + } } }, { @@ -62,13 +94,21 @@ "type": "utils.branch_condition", "typeVersion": 1, "position": [ - 1200, - 50 + 400, + 300 ], "parameters": { - "value": "$unit_results", - "mode": "regex", - "compare": "(FAILED|ERROR)" + "name": "Unit Failed", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": { + "value": "$unit_results", + "mode": "regex", + "compare": "(FAILED|ERROR)" + } } }, { @@ -77,11 +117,19 @@ "type": "utils.not", "typeVersion": 1, "position": [ - 1500, - 50 + 700, + 300 ], "parameters": { - "value": "$unit_failed" + "name": "Unit Ok", + "typeVersion": 1, + "position": [ + 1500, + 50 + ], + "parameters": { + "value": "$unit_failed" + } } }, { @@ -90,11 +138,19 @@ "type": "tools.run_tests", "typeVersion": 1, "position": [ - 1800, - 50 + 100, + 500 ], "parameters": { - "path": "tests/ui" + "name": "Ui Tests", + "typeVersion": 1, + "position": [ + 1800, + 50 + ], + "parameters": { + "path": "tests/ui" + } } } ], @@ -103,7 +159,7 @@ "main": { "0": [ { - "node": "Lint Failed", + "node": "[object Object]", "type": "main", "index": 0 } @@ -114,7 +170,7 @@ "main": { "0": [ { - "node": "Lint Ok", + "node": "[object Object]", "type": "main", "index": 0 } @@ -125,7 +181,7 @@ "main": { "0": [ { - "node": "Unit Failed", + "node": "[object Object]", "type": "main", "index": 0 } @@ -136,7 +192,7 @@ "main": { "0": [ { - "node": "Unit Ok", + "node": "[object Object]", "type": "main", "index": 0 } @@ -144,14 +200,13 @@ } } }, - "triggers": [ - { - "nodeId": "lint", - "kind": "manual", - "enabled": true, - "meta": { - "description": "Manually triggered meta.workflow_packages.testing_triangle.label workflow execution" - } - } - ] + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" + } } diff --git a/workflow/examples/python/web_server_bootstrap/workflow.backup.json b/workflow/examples/python/web_server_bootstrap/workflow.backup.json new file mode 100644 index 000000000..56de65304 --- /dev/null +++ b/workflow/examples/python/web_server_bootstrap/workflow.backup.json @@ -0,0 +1,347 @@ +{ + "name": "Web Server Bootstrap", + "active": true, + "nodes": [ + { + "id": "configure_logging", + "name": "Configure Logging", + "type": "backend.configure_logging", + "typeVersion": 1, + "position": [0, 0], + "parameters": {} + }, + { + "id": "load_env", + "name": "Load Environment", + "type": "backend.load_env", + "typeVersion": 1, + "position": [300, 0], + "parameters": {} + }, + { + "id": "create_app", + "name": "Create Flask App", + "type": "web.create_flask_app", + "typeVersion": 1, + "position": [600, 0], + "parameters": { + "name": "autometabuilder", + "config": { + "JSON_SORT_KEYS": false + } + } + }, + { + "id": "create_context_routes", + "name": "Create Context Routes", + "type": "web.route_context", + "typeVersion": 1, + "position": [900, -150], + "parameters": {} + }, + { + "id": "create_run_routes", + "name": "Create Run Routes", + "type": "web.route_run", + "typeVersion": 1, + "position": [900, -50], + "parameters": {} + }, + { + "id": "create_prompt_routes", + "name": "Create Prompt Routes", + "type": "web.route_prompt", + "typeVersion": 1, + "position": [900, 50], + "parameters": {} + }, + { + "id": "create_settings_routes", + "name": "Create Settings Routes", + "type": "web.route_settings", + "typeVersion": 1, + "position": [900, 150], + "parameters": {} + }, + { + "id": "create_translations_routes", + "name": "Create Translation Routes", + "type": "web.route_translations", + "typeVersion": 1, + "position": [900, 250], + "parameters": {} + }, + { + "id": "create_navigation_routes", + "name": "Create Navigation Routes", + "type": "web.route_navigation", + "typeVersion": 1, + "position": [900, 350], + "parameters": {} + }, + { + "id": "register_context", + "name": "Register Context Blueprint", + "type": "web.register_blueprint", + "typeVersion": 1, + "position": [1200, -150], + "parameters": { + "blueprint": "={{$node.create_context_routes.json.result}}" + } + }, + { + "id": "register_run", + "name": "Register Run Blueprint", + "type": "web.register_blueprint", + "typeVersion": 1, + "position": [1200, -50], + "parameters": { + "blueprint": "={{$node.create_run_routes.json.result}}" + } + }, + { + "id": "register_prompt", + "name": "Register Prompt Blueprint", + "type": "web.register_blueprint", + "typeVersion": 1, + "position": [1200, 50], + "parameters": { + "blueprint": "={{$node.create_prompt_routes.json.result}}" + } + }, + { + "id": "register_settings", + "name": "Register Settings Blueprint", + "type": "web.register_blueprint", + "typeVersion": 1, + "position": [1200, 150], + "parameters": { + "blueprint": "={{$node.create_settings_routes.json.result}}" + } + }, + { + "id": "register_translations", + "name": "Register Translations Blueprint", + "type": "web.register_blueprint", + "typeVersion": 1, + "position": [1200, 250], + "parameters": { + "blueprint": "={{$node.create_translations_routes.json.result}}" + } + }, + { + "id": "register_navigation", + "name": "Register Navigation Blueprint", + "type": "web.register_blueprint", + "typeVersion": 1, + "position": [1200, 350], + "parameters": { + "blueprint": "={{$node.create_navigation_routes.json.result}}" + } + }, + { + "id": "start_server", + "name": "Start Web Server", + "type": "web.start_server", + "typeVersion": 1, + "position": [1500, 100], + "parameters": { + "host": "0.0.0.0", + "port": 8000, + "debug": false + } + } + ], + "connections": { + "Configure Logging": { + "main": { + "0": [ + { + "node": "Load Environment", + "type": "main", + "index": 0 + } + ] + } + }, + "Load Environment": { + "main": { + "0": [ + { + "node": "Create Flask App", + "type": "main", + "index": 0 + } + ] + } + }, + "Create Flask App": { + "main": { + "0": [ + { + "node": "Create Context Routes", + "type": "main", + "index": 0 + }, + { + "node": "Create Run Routes", + "type": "main", + "index": 0 + }, + { + "node": "Create Prompt Routes", + "type": "main", + "index": 0 + }, + { + "node": "Create Settings Routes", + "type": "main", + "index": 0 + }, + { + "node": "Create Translation Routes", + "type": "main", + "index": 0 + }, + { + "node": "Create Navigation Routes", + "type": "main", + "index": 0 + } + ] + } + }, + "Create Context Routes": { + "main": { + "0": [ + { + "node": "Register Context Blueprint", + "type": "main", + "index": 0 + } + ] + } + }, + "Create Run Routes": { + "main": { + "0": [ + { + "node": "Register Run Blueprint", + "type": "main", + "index": 0 + } + ] + } + }, + "Create Prompt Routes": { + "main": { + "0": [ + { + "node": "Register Prompt Blueprint", + "type": "main", + "index": 0 + } + ] + } + }, + "Create Settings Routes": { + "main": { + "0": [ + { + "node": "Register Settings Blueprint", + "type": "main", + "index": 0 + } + ] + } + }, + "Create Translation Routes": { + "main": { + "0": [ + { + "node": "Register Translations Blueprint", + "type": "main", + "index": 0 + } + ] + } + }, + "Create Navigation Routes": { + "main": { + "0": [ + { + "node": "Register Navigation Blueprint", + "type": "main", + "index": 0 + } + ] + } + }, + "Register Context Blueprint": { + "main": { + "0": [ + { + "node": "Start Web Server", + "type": "main", + "index": 0 + } + ] + } + }, + "Register Run Blueprint": { + "main": { + "0": [ + { + "node": "Start Web Server", + "type": "main", + "index": 0 + } + ] + } + }, + "Register Prompt Blueprint": { + "main": { + "0": [ + { + "node": "Start Web Server", + "type": "main", + "index": 0 + } + ] + } + }, + "Register Settings Blueprint": { + "main": { + "0": [ + { + "node": "Start Web Server", + "type": "main", + "index": 0 + } + ] + } + }, + "Register Translations Blueprint": { + "main": { + "0": [ + { + "node": "Start Web Server", + "type": "main", + "index": 0 + } + ] + } + }, + "Register Navigation Blueprint": { + "main": { + "0": [ + { + "node": "Start Web Server", + "type": "main", + "index": 0 + } + ] + } + } + } +} diff --git a/workflow/examples/python/web_server_bootstrap/workflow.json b/workflow/examples/python/web_server_bootstrap/workflow.json index 56de65304..2dea8751b 100644 --- a/workflow/examples/python/web_server_bootstrap/workflow.json +++ b/workflow/examples/python/web_server_bootstrap/workflow.json @@ -1,33 +1,66 @@ { "name": "Web Server Bootstrap", - "active": true, + "active": false, "nodes": [ { "id": "configure_logging", "name": "Configure Logging", "type": "backend.configure_logging", "typeVersion": 1, - "position": [0, 0], - "parameters": {} + "position": [ + 100, + 100 + ], + "parameters": { + "name": "Configure Logging", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": {} + } }, { "id": "load_env", - "name": "Load Environment", + "name": "Load Env", "type": "backend.load_env", "typeVersion": 1, - "position": [300, 0], - "parameters": {} + "position": [ + 400, + 100 + ], + "parameters": { + "name": "Load Environment", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": {} + } }, { "id": "create_app", - "name": "Create Flask App", + "name": "Create App", "type": "web.create_flask_app", "typeVersion": 1, - "position": [600, 0], + "position": [ + 700, + 100 + ], "parameters": { - "name": "autometabuilder", - "config": { - "JSON_SORT_KEYS": false + "name": "Create Flask App", + "typeVersion": 1, + "position": [ + 600, + 0 + ], + "parameters": { + "name": "autometabuilder", + "config": { + "JSON_SORT_KEYS": false + } } } }, @@ -36,119 +69,262 @@ "name": "Create Context Routes", "type": "web.route_context", "typeVersion": 1, - "position": [900, -150], - "parameters": {} + "position": [ + 100, + 300 + ], + "parameters": { + "name": "Create Context Routes", + "typeVersion": 1, + "position": [ + 900, + -150 + ], + "parameters": {} + } }, { "id": "create_run_routes", "name": "Create Run Routes", "type": "web.route_run", "typeVersion": 1, - "position": [900, -50], - "parameters": {} + "position": [ + 400, + 300 + ], + "parameters": { + "name": "Create Run Routes", + "typeVersion": 1, + "position": [ + 900, + -50 + ], + "parameters": {} + } }, { "id": "create_prompt_routes", "name": "Create Prompt Routes", "type": "web.route_prompt", "typeVersion": 1, - "position": [900, 50], - "parameters": {} + "position": [ + 700, + 300 + ], + "parameters": { + "name": "Create Prompt Routes", + "typeVersion": 1, + "position": [ + 900, + 50 + ], + "parameters": {} + } }, { "id": "create_settings_routes", "name": "Create Settings Routes", "type": "web.route_settings", "typeVersion": 1, - "position": [900, 150], - "parameters": {} + "position": [ + 100, + 500 + ], + "parameters": { + "name": "Create Settings Routes", + "typeVersion": 1, + "position": [ + 900, + 150 + ], + "parameters": {} + } }, { "id": "create_translations_routes", - "name": "Create Translation Routes", + "name": "Create Translations Routes", "type": "web.route_translations", "typeVersion": 1, - "position": [900, 250], - "parameters": {} + "position": [ + 400, + 500 + ], + "parameters": { + "name": "Create Translation Routes", + "typeVersion": 1, + "position": [ + 900, + 250 + ], + "parameters": {} + } }, { "id": "create_navigation_routes", "name": "Create Navigation Routes", "type": "web.route_navigation", "typeVersion": 1, - "position": [900, 350], - "parameters": {} + "position": [ + 700, + 500 + ], + "parameters": { + "name": "Create Navigation Routes", + "typeVersion": 1, + "position": [ + 900, + 350 + ], + "parameters": {} + } }, { "id": "register_context", - "name": "Register Context Blueprint", + "name": "Register Context", "type": "web.register_blueprint", "typeVersion": 1, - "position": [1200, -150], + "position": [ + 100, + 700 + ], "parameters": { - "blueprint": "={{$node.create_context_routes.json.result}}" + "name": "Register Context Blueprint", + "typeVersion": 1, + "position": [ + 1200, + -150 + ], + "parameters": { + "blueprint": "={{$node.create_context_routes.json.result}}" + } } }, { "id": "register_run", - "name": "Register Run Blueprint", + "name": "Register Run", "type": "web.register_blueprint", "typeVersion": 1, - "position": [1200, -50], + "position": [ + 400, + 700 + ], "parameters": { - "blueprint": "={{$node.create_run_routes.json.result}}" + "name": "Register Run Blueprint", + "typeVersion": 1, + "position": [ + 1200, + -50 + ], + "parameters": { + "blueprint": "={{$node.create_run_routes.json.result}}" + } } }, { "id": "register_prompt", - "name": "Register Prompt Blueprint", + "name": "Register Prompt", "type": "web.register_blueprint", "typeVersion": 1, - "position": [1200, 50], + "position": [ + 700, + 700 + ], "parameters": { - "blueprint": "={{$node.create_prompt_routes.json.result}}" + "name": "Register Prompt Blueprint", + "typeVersion": 1, + "position": [ + 1200, + 50 + ], + "parameters": { + "blueprint": "={{$node.create_prompt_routes.json.result}}" + } } }, { "id": "register_settings", - "name": "Register Settings Blueprint", + "name": "Register Settings", "type": "web.register_blueprint", "typeVersion": 1, - "position": [1200, 150], + "position": [ + 100, + 900 + ], "parameters": { - "blueprint": "={{$node.create_settings_routes.json.result}}" + "name": "Register Settings Blueprint", + "typeVersion": 1, + "position": [ + 1200, + 150 + ], + "parameters": { + "blueprint": "={{$node.create_settings_routes.json.result}}" + } } }, { "id": "register_translations", - "name": "Register Translations Blueprint", + "name": "Register Translations", "type": "web.register_blueprint", "typeVersion": 1, - "position": [1200, 250], + "position": [ + 400, + 900 + ], "parameters": { - "blueprint": "={{$node.create_translations_routes.json.result}}" + "name": "Register Translations Blueprint", + "typeVersion": 1, + "position": [ + 1200, + 250 + ], + "parameters": { + "blueprint": "={{$node.create_translations_routes.json.result}}" + } } }, { "id": "register_navigation", - "name": "Register Navigation Blueprint", + "name": "Register Navigation", "type": "web.register_blueprint", "typeVersion": 1, - "position": [1200, 350], + "position": [ + 700, + 900 + ], "parameters": { - "blueprint": "={{$node.create_navigation_routes.json.result}}" + "name": "Register Navigation Blueprint", + "typeVersion": 1, + "position": [ + 1200, + 350 + ], + "parameters": { + "blueprint": "={{$node.create_navigation_routes.json.result}}" + } } }, { "id": "start_server", - "name": "Start Web Server", + "name": "Start Server", "type": "web.start_server", "typeVersion": 1, - "position": [1500, 100], + "position": [ + 100, + 1100 + ], "parameters": { - "host": "0.0.0.0", - "port": 8000, - "debug": false + "name": "Start Web Server", + "typeVersion": 1, + "position": [ + 1500, + 100 + ], + "parameters": { + "host": "0.0.0.0", + "port": 8000, + "debug": false + } } } ], @@ -157,7 +333,7 @@ "main": { "0": [ { - "node": "Load Environment", + "node": "[object Object]", "type": "main", "index": 0 } @@ -168,7 +344,7 @@ "main": { "0": [ { - "node": "Create Flask App", + "node": "[object Object]", "type": "main", "index": 0 } @@ -179,32 +355,7 @@ "main": { "0": [ { - "node": "Create Context Routes", - "type": "main", - "index": 0 - }, - { - "node": "Create Run Routes", - "type": "main", - "index": 0 - }, - { - "node": "Create Prompt Routes", - "type": "main", - "index": 0 - }, - { - "node": "Create Settings Routes", - "type": "main", - "index": 0 - }, - { - "node": "Create Translation Routes", - "type": "main", - "index": 0 - }, - { - "node": "Create Navigation Routes", + "node": "[object Object]", "type": "main", "index": 0 } @@ -215,7 +366,7 @@ "main": { "0": [ { - "node": "Register Context Blueprint", + "node": "[object Object]", "type": "main", "index": 0 } @@ -226,7 +377,7 @@ "main": { "0": [ { - "node": "Register Run Blueprint", + "node": "[object Object]", "type": "main", "index": 0 } @@ -237,7 +388,7 @@ "main": { "0": [ { - "node": "Register Prompt Blueprint", + "node": "[object Object]", "type": "main", "index": 0 } @@ -248,7 +399,7 @@ "main": { "0": [ { - "node": "Register Settings Blueprint", + "node": "[object Object]", "type": "main", "index": 0 } @@ -259,7 +410,7 @@ "main": { "0": [ { - "node": "Register Translations Blueprint", + "node": "[object Object]", "type": "main", "index": 0 } @@ -270,7 +421,7 @@ "main": { "0": [ { - "node": "Register Navigation Blueprint", + "node": "[object Object]", "type": "main", "index": 0 } @@ -281,7 +432,7 @@ "main": { "0": [ { - "node": "Start Web Server", + "node": "[object Object]", "type": "main", "index": 0 } @@ -292,7 +443,7 @@ "main": { "0": [ { - "node": "Start Web Server", + "node": "[object Object]", "type": "main", "index": 0 } @@ -303,7 +454,7 @@ "main": { "0": [ { - "node": "Start Web Server", + "node": "[object Object]", "type": "main", "index": 0 } @@ -314,7 +465,7 @@ "main": { "0": [ { - "node": "Start Web Server", + "node": "[object Object]", "type": "main", "index": 0 } @@ -325,7 +476,7 @@ "main": { "0": [ { - "node": "Start Web Server", + "node": "[object Object]", "type": "main", "index": 0 } @@ -336,12 +487,21 @@ "main": { "0": [ { - "node": "Start Web Server", + "node": "[object Object]", "type": "main", "index": 0 } ] } } + }, + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" } } diff --git a/workflow/examples/python/web_server_json_routes/workflow.backup.json b/workflow/examples/python/web_server_json_routes/workflow.backup.json new file mode 100644 index 000000000..aca7fcd66 --- /dev/null +++ b/workflow/examples/python/web_server_json_routes/workflow.backup.json @@ -0,0 +1,135 @@ +{ + "name": "Web Server with JSON Routes", + "active": true, + "nodes": [ + { + "id": "configure_logging", + "name": "Configure Logging", + "type": "backend.configure_logging", + "typeVersion": 1, + "position": [0, 0], + "parameters": {} + }, + { + "id": "load_env", + "name": "Load Environment", + "type": "backend.load_env", + "typeVersion": 1, + "position": [300, 0], + "parameters": {} + }, + { + "id": "create_app", + "name": "Create Flask App", + "type": "web.create_flask_app", + "typeVersion": 1, + "position": [600, 0], + "parameters": { + "name": "autometabuilder", + "config": { + "JSON_SORT_KEYS": false + } + } + }, + { + "id": "register_api_routes", + "name": "Register API Routes", + "type": "web.register_routes", + "typeVersion": 1, + "position": [900, 0], + "parameters": { + "blueprint_name": "api", + "routes": [ + { + "path": "/api/navigation", + "methods": ["GET"], + "handler": "web.api_navigation", + "handler_type": "plugin" + }, + { + "path": "/api/workflow/packages", + "methods": ["GET"], + "handler": "web.api_workflow_packages", + "handler_type": "plugin" + }, + { + "path": "/api/workflow/plugins", + "methods": ["GET"], + "handler": "web.api_workflow_plugins", + "handler_type": "plugin" + }, + { + "path": "/api/workflow/graph", + "methods": ["GET"], + "handler": "web.api_workflow_graph", + "handler_type": "plugin" + }, + { + "path": "/api/translation-options", + "methods": ["GET"], + "handler": "web.api_translation_options", + "handler_type": "plugin" + } + ] + } + }, + { + "id": "start_server", + "name": "Start Web Server", + "type": "web.start_server", + "typeVersion": 1, + "position": [1200, 0], + "parameters": { + "host": "0.0.0.0", + "port": 8000, + "debug": false + } + } + ], + "connections": { + "Configure Logging": { + "main": { + "0": [ + { + "node": "Load Environment", + "type": "main", + "index": 0 + } + ] + } + }, + "Load Environment": { + "main": { + "0": [ + { + "node": "Create Flask App", + "type": "main", + "index": 0 + } + ] + } + }, + "Create Flask App": { + "main": { + "0": [ + { + "node": "Register API Routes", + "type": "main", + "index": 0 + } + ] + } + }, + "Register API Routes": { + "main": { + "0": [ + { + "node": "Start Web Server", + "type": "main", + "index": 0 + } + ] + } + } + } +} diff --git a/workflow/examples/python/web_server_json_routes/workflow.json b/workflow/examples/python/web_server_json_routes/workflow.json index aca7fcd66..61702f288 100644 --- a/workflow/examples/python/web_server_json_routes/workflow.json +++ b/workflow/examples/python/web_server_json_routes/workflow.json @@ -1,88 +1,153 @@ { "name": "Web Server with JSON Routes", - "active": true, + "active": false, "nodes": [ { "id": "configure_logging", "name": "Configure Logging", "type": "backend.configure_logging", "typeVersion": 1, - "position": [0, 0], - "parameters": {} + "position": [ + 100, + 100 + ], + "parameters": { + "name": "Configure Logging", + "typeVersion": 1, + "position": [ + 0, + 0 + ], + "parameters": {} + } }, { "id": "load_env", - "name": "Load Environment", + "name": "Load Env", "type": "backend.load_env", "typeVersion": 1, - "position": [300, 0], - "parameters": {} + "position": [ + 400, + 100 + ], + "parameters": { + "name": "Load Environment", + "typeVersion": 1, + "position": [ + 300, + 0 + ], + "parameters": {} + } }, { "id": "create_app", - "name": "Create Flask App", + "name": "Create App", "type": "web.create_flask_app", "typeVersion": 1, - "position": [600, 0], + "position": [ + 700, + 100 + ], "parameters": { - "name": "autometabuilder", - "config": { - "JSON_SORT_KEYS": false + "name": "Create Flask App", + "typeVersion": 1, + "position": [ + 600, + 0 + ], + "parameters": { + "name": "autometabuilder", + "config": { + "JSON_SORT_KEYS": false + } } } }, { "id": "register_api_routes", - "name": "Register API Routes", + "name": "Register Api Routes", "type": "web.register_routes", "typeVersion": 1, - "position": [900, 0], + "position": [ + 100, + 300 + ], "parameters": { - "blueprint_name": "api", - "routes": [ - { - "path": "/api/navigation", - "methods": ["GET"], - "handler": "web.api_navigation", - "handler_type": "plugin" - }, - { - "path": "/api/workflow/packages", - "methods": ["GET"], - "handler": "web.api_workflow_packages", - "handler_type": "plugin" - }, - { - "path": "/api/workflow/plugins", - "methods": ["GET"], - "handler": "web.api_workflow_plugins", - "handler_type": "plugin" - }, - { - "path": "/api/workflow/graph", - "methods": ["GET"], - "handler": "web.api_workflow_graph", - "handler_type": "plugin" - }, - { - "path": "/api/translation-options", - "methods": ["GET"], - "handler": "web.api_translation_options", - "handler_type": "plugin" - } - ] + "name": "Register API Routes", + "typeVersion": 1, + "position": [ + 900, + 0 + ], + "parameters": { + "blueprint_name": "api", + "routes": [ + { + "path": "/api/navigation", + "methods": [ + "GET" + ], + "handler": "web.api_navigation", + "handler_type": "plugin" + }, + { + "path": "/api/workflow/packages", + "methods": [ + "GET" + ], + "handler": "web.api_workflow_packages", + "handler_type": "plugin" + }, + { + "path": "/api/workflow/plugins", + "methods": [ + "GET" + ], + "handler": "web.api_workflow_plugins", + "handler_type": "plugin" + }, + { + "path": "/api/workflow/graph", + "methods": [ + "GET" + ], + "handler": "web.api_workflow_graph", + "handler_type": "plugin" + }, + { + "path": "/api/translation-options", + "methods": [ + "GET" + ], + "handler": "web.api_translation_options", + "handler_type": "plugin" + } + ] + } } }, { "id": "start_server", - "name": "Start Web Server", + "name": "Start Server", "type": "web.start_server", "typeVersion": 1, - "position": [1200, 0], + "position": [ + 400, + 300 + ], "parameters": { - "host": "0.0.0.0", - "port": 8000, - "debug": false + "name": "Start Web Server", + "typeVersion": 1, + "position": [ + 1200, + 0 + ], + "parameters": { + "host": "0.0.0.0", + "port": 8000, + "debug": false + } } } ], @@ -91,7 +156,7 @@ "main": { "0": [ { - "node": "Load Environment", + "node": "[object Object]", "type": "main", "index": 0 } @@ -102,7 +167,7 @@ "main": { "0": [ { - "node": "Create Flask App", + "node": "[object Object]", "type": "main", "index": 0 } @@ -113,23 +178,32 @@ "main": { "0": [ { - "node": "Register API Routes", + "node": "[object Object]", "type": "main", "index": 0 } ] } }, - "Register API Routes": { + "Register Api Routes": { "main": { "0": [ { - "node": "Start Web Server", + "node": "[object Object]", "type": "main", "index": 0 } ] } } + }, + "staticData": {}, + "meta": {}, + "settings": { + "timezone": "UTC", + "executionTimeout": 3600, + "saveExecutionProgress": true, + "saveDataErrorExecution": "all", + "saveDataSuccessExecution": "all" } }