diff --git a/workflow/plugins/cpp/convert/convert_to_boolean/convert_to_boolean.hpp b/workflow/plugins/cpp/convert/convert_to_boolean/convert_to_boolean.hpp new file mode 100644 index 000000000..b4e9b9501 --- /dev/null +++ b/workflow/plugins/cpp/convert/convert_to_boolean/convert_to_boolean.hpp @@ -0,0 +1,44 @@ +#pragma once +/** + * Workflow plugin: convert value to boolean + */ + +#include "../../plugin.hpp" +#include + +namespace metabuilder::workflow::convert { + +inline PluginResult to_boolean(Runtime&, const json& inputs) { + json value = inputs.value("value", json{}); + + if (value.is_boolean()) { + return {{"result", value.get()}}; + } + + if (value.is_string()) { + std::string str = value.get(); + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + bool falsy = (str == "false" || str == "0" || str.empty() || str == "none" || str == "null"); + return {{"result", !falsy}}; + } + + if (value.is_number()) { + return {{"result", value.get() != 0.0}}; + } + + if (value.is_null()) { + return {{"result", false}}; + } + + if (value.is_array()) { + return {{"result", !value.empty()}}; + } + + if (value.is_object()) { + return {{"result", !value.empty()}}; + } + + return {{"result", false}}; +} + +} // namespace metabuilder::workflow::convert diff --git a/workflow/plugins/cpp/convert/convert_to_boolean/package.json b/workflow/plugins/cpp/convert/convert_to_boolean/package.json new file mode 100644 index 000000000..84371d6f2 --- /dev/null +++ b/workflow/plugins/cpp/convert/convert_to_boolean/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/convert_to_boolean", + "version": "1.0.0", + "description": "Convert value to boolean", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin"], + "main": "convert_to_boolean.hpp", + "metadata": { + "plugin_type": "convert.to_boolean", + "category": "convert" + } +} diff --git a/workflow/plugins/cpp/convert/convert_to_json/convert_to_json.hpp b/workflow/plugins/cpp/convert/convert_to_json/convert_to_json.hpp new file mode 100644 index 000000000..f13c7e83f --- /dev/null +++ b/workflow/plugins/cpp/convert/convert_to_json/convert_to_json.hpp @@ -0,0 +1,27 @@ +#pragma once +/** + * Workflow plugin: convert value to JSON string + */ + +#include "../../plugin.hpp" + +namespace metabuilder::workflow::convert { + +inline PluginResult to_json(Runtime&, const json& inputs) { + json value = inputs.value("value", json{}); + int indent = inputs.contains("indent") ? inputs["indent"].get() : -1; + + try { + std::string result; + if (indent >= 0) { + result = value.dump(indent); + } else { + result = value.dump(); + } + return {{"result", result}}; + } catch (const std::exception& e) { + return {{"result", nullptr}, {"error", e.what()}}; + } +} + +} // namespace metabuilder::workflow::convert diff --git a/workflow/plugins/cpp/convert/convert_to_json/package.json b/workflow/plugins/cpp/convert/convert_to_json/package.json new file mode 100644 index 000000000..a1659ee39 --- /dev/null +++ b/workflow/plugins/cpp/convert/convert_to_json/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/convert_to_json", + "version": "1.0.0", + "description": "Convert value to JSON string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin"], + "main": "convert_to_json.hpp", + "metadata": { + "plugin_type": "convert.to_json", + "category": "convert" + } +} diff --git a/workflow/plugins/cpp/convert/package.json b/workflow/plugins/cpp/convert/package.json index 7d61a1aea..1f3d7b763 100644 --- a/workflow/plugins/cpp/convert/package.json +++ b/workflow/plugins/cpp/convert/package.json @@ -7,11 +7,13 @@ "keywords": ["convert", "workflow", "plugins", "cpp"], "metadata": { "category": "convert", - "plugin_count": 3 + "plugin_count": 5 }, "plugins": [ - "convert_to_string", + "convert_parse_json", + "convert_to_boolean", + "convert_to_json", "convert_to_number", - "convert_parse_json" + "convert_to_string" ] } diff --git a/workflow/plugins/cpp/logic/logic_gt/logic_gt.hpp b/workflow/plugins/cpp/logic/logic_gt/logic_gt.hpp new file mode 100644 index 000000000..7f3b8d765 --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_gt/logic_gt.hpp @@ -0,0 +1,25 @@ +#pragma once +/** + * Workflow plugin: greater than comparison + */ + +#include "../../plugin.hpp" + +namespace metabuilder::workflow::logic { + +inline PluginResult gt(Runtime&, const json& inputs) { + auto a = inputs.value("a", json{}); + auto b = inputs.value("b", json{}); + + if (a.is_number() && b.is_number()) { + return {{"result", a.get() > b.get()}}; + } + + if (a.is_string() && b.is_string()) { + return {{"result", a.get() > b.get()}}; + } + + return {{"result", false}}; +} + +} // namespace metabuilder::workflow::logic diff --git a/workflow/plugins/cpp/logic/logic_gt/package.json b/workflow/plugins/cpp/logic/logic_gt/package.json new file mode 100644 index 000000000..90ef318f9 --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_gt/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_gt", + "version": "1.0.0", + "description": "Greater than comparison", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_gt.hpp", + "metadata": { + "plugin_type": "logic.gt", + "category": "logic" + } +} diff --git a/workflow/plugins/cpp/logic/logic_gte/logic_gte.hpp b/workflow/plugins/cpp/logic/logic_gte/logic_gte.hpp new file mode 100644 index 000000000..9b742092d --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_gte/logic_gte.hpp @@ -0,0 +1,25 @@ +#pragma once +/** + * Workflow plugin: greater than or equal comparison + */ + +#include "../../plugin.hpp" + +namespace metabuilder::workflow::logic { + +inline PluginResult gte(Runtime&, const json& inputs) { + auto a = inputs.value("a", json{}); + auto b = inputs.value("b", json{}); + + if (a.is_number() && b.is_number()) { + return {{"result", a.get() >= b.get()}}; + } + + if (a.is_string() && b.is_string()) { + return {{"result", a.get() >= b.get()}}; + } + + return {{"result", false}}; +} + +} // namespace metabuilder::workflow::logic diff --git a/workflow/plugins/cpp/logic/logic_gte/package.json b/workflow/plugins/cpp/logic/logic_gte/package.json new file mode 100644 index 000000000..f992cb54c --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_gte/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_gte", + "version": "1.0.0", + "description": "Greater than or equal comparison", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_gte.hpp", + "metadata": { + "plugin_type": "logic.gte", + "category": "logic" + } +} diff --git a/workflow/plugins/cpp/logic/logic_in/logic_in.hpp b/workflow/plugins/cpp/logic/logic_in/logic_in.hpp new file mode 100644 index 000000000..fb5c99eca --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_in/logic_in.hpp @@ -0,0 +1,28 @@ +#pragma once +/** + * Workflow plugin: membership test + */ + +#include "../../plugin.hpp" +#include + +namespace metabuilder::workflow::logic { + +inline PluginResult in(Runtime&, const json& inputs) { + auto value = inputs.value("value", json{}); + auto collection = inputs.value("collection", json::array()); + + if (!collection.is_array()) { + return {{"result", false}}; + } + + for (const auto& item : collection) { + if (item == value) { + return {{"result", true}}; + } + } + + return {{"result", false}}; +} + +} // namespace metabuilder::workflow::logic diff --git a/workflow/plugins/cpp/logic/logic_in/package.json b/workflow/plugins/cpp/logic/logic_in/package.json new file mode 100644 index 000000000..f47782900 --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_in/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_in", + "version": "1.0.0", + "description": "Membership test", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_in.hpp", + "metadata": { + "plugin_type": "logic.in", + "category": "logic" + } +} diff --git a/workflow/plugins/cpp/logic/logic_lt/logic_lt.hpp b/workflow/plugins/cpp/logic/logic_lt/logic_lt.hpp new file mode 100644 index 000000000..0136515cb --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_lt/logic_lt.hpp @@ -0,0 +1,25 @@ +#pragma once +/** + * Workflow plugin: less than comparison + */ + +#include "../../plugin.hpp" + +namespace metabuilder::workflow::logic { + +inline PluginResult lt(Runtime&, const json& inputs) { + auto a = inputs.value("a", json{}); + auto b = inputs.value("b", json{}); + + if (a.is_number() && b.is_number()) { + return {{"result", a.get() < b.get()}}; + } + + if (a.is_string() && b.is_string()) { + return {{"result", a.get() < b.get()}}; + } + + return {{"result", false}}; +} + +} // namespace metabuilder::workflow::logic diff --git a/workflow/plugins/cpp/logic/logic_lt/package.json b/workflow/plugins/cpp/logic/logic_lt/package.json new file mode 100644 index 000000000..2c4a5c649 --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_lt/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_lt", + "version": "1.0.0", + "description": "Less than comparison", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_lt.hpp", + "metadata": { + "plugin_type": "logic.lt", + "category": "logic" + } +} diff --git a/workflow/plugins/cpp/logic/logic_lte/logic_lte.hpp b/workflow/plugins/cpp/logic/logic_lte/logic_lte.hpp new file mode 100644 index 000000000..26d4fe5c8 --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_lte/logic_lte.hpp @@ -0,0 +1,25 @@ +#pragma once +/** + * Workflow plugin: less than or equal comparison + */ + +#include "../../plugin.hpp" + +namespace metabuilder::workflow::logic { + +inline PluginResult lte(Runtime&, const json& inputs) { + auto a = inputs.value("a", json{}); + auto b = inputs.value("b", json{}); + + if (a.is_number() && b.is_number()) { + return {{"result", a.get() <= b.get()}}; + } + + if (a.is_string() && b.is_string()) { + return {{"result", a.get() <= b.get()}}; + } + + return {{"result", false}}; +} + +} // namespace metabuilder::workflow::logic diff --git a/workflow/plugins/cpp/logic/logic_lte/package.json b/workflow/plugins/cpp/logic/logic_lte/package.json new file mode 100644 index 000000000..ecac82d73 --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_lte/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_lte", + "version": "1.0.0", + "description": "Less than or equal comparison", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_lte.hpp", + "metadata": { + "plugin_type": "logic.lte", + "category": "logic" + } +} diff --git a/workflow/plugins/cpp/logic/logic_xor/logic_xor.hpp b/workflow/plugins/cpp/logic/logic_xor/logic_xor.hpp new file mode 100644 index 000000000..343cdc0e8 --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_xor/logic_xor.hpp @@ -0,0 +1,16 @@ +#pragma once +/** + * Workflow plugin: logical XOR + */ + +#include "../../plugin.hpp" + +namespace metabuilder::workflow::logic { + +inline PluginResult xor_op(Runtime&, const json& inputs) { + bool a = inputs.value("a", false); + bool b = inputs.value("b", false); + return {{"result", a != b}}; +} + +} // namespace metabuilder::workflow::logic diff --git a/workflow/plugins/cpp/logic/logic_xor/package.json b/workflow/plugins/cpp/logic/logic_xor/package.json new file mode 100644 index 000000000..919fd3be8 --- /dev/null +++ b/workflow/plugins/cpp/logic/logic_xor/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_xor", + "version": "1.0.0", + "description": "Logical XOR operation", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_xor.hpp", + "metadata": { + "plugin_type": "logic.xor", + "category": "logic" + } +} diff --git a/workflow/plugins/cpp/logic/package.json b/workflow/plugins/cpp/logic/package.json index d426c9b9e..dfa0cfbd2 100644 --- a/workflow/plugins/cpp/logic/package.json +++ b/workflow/plugins/cpp/logic/package.json @@ -7,12 +7,18 @@ "keywords": ["logic", "workflow", "plugins", "cpp"], "metadata": { "category": "logic", - "plugin_count": 4 + "plugin_count": 10 }, "plugins": [ "logic_and", - "logic_or", + "logic_equals", + "logic_gt", + "logic_gte", + "logic_in", + "logic_lt", + "logic_lte", "logic_not", - "logic_equals" + "logic_or", + "logic_xor" ] } diff --git a/workflow/plugins/cpp/string/string_replace/package.json b/workflow/plugins/cpp/string/string_replace/package.json new file mode 100644 index 000000000..02d13470d --- /dev/null +++ b/workflow/plugins/cpp/string/string_replace/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_replace", + "version": "1.0.0", + "description": "Replace occurrences in string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_replace.hpp", + "metadata": { + "plugin_type": "string.replace", + "category": "string" + } +} diff --git a/workflow/plugins/cpp/string/string_replace/string_replace.hpp b/workflow/plugins/cpp/string/string_replace/string_replace.hpp new file mode 100644 index 000000000..def0b2e39 --- /dev/null +++ b/workflow/plugins/cpp/string/string_replace/string_replace.hpp @@ -0,0 +1,34 @@ +#pragma once +/** + * Workflow plugin: replace occurrences in string + */ + +#include "../../plugin.hpp" + +namespace metabuilder::workflow::string { + +inline PluginResult replace(Runtime&, const json& inputs) { + auto text = inputs.value("text", std::string{}); + auto old_str = inputs.value("old", std::string{}); + auto new_str = inputs.value("new", std::string{}); + auto count = inputs.contains("count") ? inputs["count"].get() : -1; + + if (old_str.empty()) { + return {{"result", text}}; + } + + std::string result = text; + size_t pos = 0; + int replaced = 0; + + while ((pos = result.find(old_str, pos)) != std::string::npos) { + if (count >= 0 && replaced >= count) break; + result.replace(pos, old_str.length(), new_str); + pos += new_str.length(); + ++replaced; + } + + return {{"result", result}}; +} + +} // namespace metabuilder::workflow::string diff --git a/workflow/plugins/cpp/string/string_split/package.json b/workflow/plugins/cpp/string/string_split/package.json new file mode 100644 index 000000000..ecc04036f --- /dev/null +++ b/workflow/plugins/cpp/string/string_split/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_split", + "version": "1.0.0", + "description": "Split string by separator", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_split.hpp", + "metadata": { + "plugin_type": "string.split", + "category": "string" + } +} diff --git a/workflow/plugins/cpp/string/string_split/string_split.hpp b/workflow/plugins/cpp/string/string_split/string_split.hpp new file mode 100644 index 000000000..10299b792 --- /dev/null +++ b/workflow/plugins/cpp/string/string_split/string_split.hpp @@ -0,0 +1,39 @@ +#pragma once +/** + * Workflow plugin: split string by separator + */ + +#include "../../plugin.hpp" +#include +#include + +namespace metabuilder::workflow::string { + +inline PluginResult split(Runtime&, const json& inputs) { + auto text = inputs.value("text", std::string{}); + auto separator = inputs.value("separator", std::string{" "}); + auto max_splits = inputs.contains("max_splits") ? inputs["max_splits"].get() : -1; + + std::vector result; + + if (separator.empty()) { + result.push_back(text); + return {{"result", result}}; + } + + size_t pos = 0; + size_t prev = 0; + int count = 0; + + while ((pos = text.find(separator, prev)) != std::string::npos) { + if (max_splits >= 0 && count >= max_splits) break; + result.push_back(text.substr(prev, pos - prev)); + prev = pos + separator.length(); + ++count; + } + result.push_back(text.substr(prev)); + + return {{"result", result}}; +} + +} // namespace metabuilder::workflow::string diff --git a/workflow/plugins/cpp/string/string_trim/package.json b/workflow/plugins/cpp/string/string_trim/package.json new file mode 100644 index 000000000..d8c607e1b --- /dev/null +++ b/workflow/plugins/cpp/string/string_trim/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_trim", + "version": "1.0.0", + "description": "Trim whitespace from string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_trim.hpp", + "metadata": { + "plugin_type": "string.trim", + "category": "string" + } +} diff --git a/workflow/plugins/cpp/string/string_trim/string_trim.hpp b/workflow/plugins/cpp/string/string_trim/string_trim.hpp new file mode 100644 index 000000000..b0d7cb0c4 --- /dev/null +++ b/workflow/plugins/cpp/string/string_trim/string_trim.hpp @@ -0,0 +1,42 @@ +#pragma once +/** + * Workflow plugin: trim whitespace from string + */ + +#include "../../plugin.hpp" +#include +#include + +namespace metabuilder::workflow::string { + +inline PluginResult trim(Runtime&, const json& inputs) { + auto text = inputs.value("text", std::string{}); + auto mode = inputs.value("mode", std::string{"both"}); + + auto ltrim = [](std::string& s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { + return !std::isspace(ch); + })); + }; + + auto rtrim = [](std::string& s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { + return !std::isspace(ch); + }).base(), s.end()); + }; + + std::string result = text; + + if (mode == "start") { + ltrim(result); + } else if (mode == "end") { + rtrim(result); + } else { + ltrim(result); + rtrim(result); + } + + return {{"result", result}}; +} + +} // namespace metabuilder::workflow::string diff --git a/workflow/plugins/cpp/var/package.json b/workflow/plugins/cpp/var/package.json index c0c783448..dd15ad89c 100644 --- a/workflow/plugins/cpp/var/package.json +++ b/workflow/plugins/cpp/var/package.json @@ -7,11 +7,12 @@ "keywords": ["var", "workflow", "plugins", "cpp"], "metadata": { "category": "var", - "plugin_count": 3 + "plugin_count": 4 }, "plugins": [ + "var_delete", + "var_exists", "var_get", - "var_set", - "var_delete" + "var_set" ] } diff --git a/workflow/plugins/cpp/var/var_exists/package.json b/workflow/plugins/cpp/var/var_exists/package.json new file mode 100644 index 000000000..7c0a83a00 --- /dev/null +++ b/workflow/plugins/cpp/var/var_exists/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/var_exists", + "version": "1.0.0", + "description": "Check if variable exists in store", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "workflow", "plugin"], + "main": "var_exists.hpp", + "metadata": { + "plugin_type": "var.exists", + "category": "var" + } +} diff --git a/workflow/plugins/cpp/var/var_exists/var_exists.hpp b/workflow/plugins/cpp/var/var_exists/var_exists.hpp new file mode 100644 index 000000000..39dbab399 --- /dev/null +++ b/workflow/plugins/cpp/var/var_exists/var_exists.hpp @@ -0,0 +1,21 @@ +#pragma once +/** + * Workflow plugin: check if variable exists in store + */ + +#include "../../plugin.hpp" + +namespace metabuilder::workflow::var { + +inline PluginResult exists(Runtime& runtime, const json& inputs) { + std::string key = inputs.value("key", ""); + + if (key.empty()) { + return {{"result", false}, {"error", "key is required"}}; + } + + bool found = runtime.store.find(key) != runtime.store.end(); + return {{"result", found}}; +} + +} // namespace metabuilder::workflow::var diff --git a/workflow/plugins/go/convert/convert_parse_json.go b/workflow/plugins/go/convert/convert_parse_json/convert_parse_json.go similarity index 65% rename from workflow/plugins/go/convert/convert_parse_json.go rename to workflow/plugins/go/convert/convert_parse_json/convert_parse_json.go index 201b4656d..e580febfd 100644 --- a/workflow/plugins/go/convert/convert_parse_json.go +++ b/workflow/plugins/go/convert/convert_parse_json/convert_parse_json.go @@ -1,5 +1,5 @@ -// Package convert provides type conversion workflow plugins. -package convert +// Package convert_parse_json provides the parse JSON plugin. +package convert_parse_json import ( "encoding/json" @@ -7,8 +7,8 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// ParseJSON parses a JSON string to object. -func ParseJSON(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run parses a JSON string to object. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { str, ok := inputs["string"].(string) if !ok { return map[string]interface{}{"result": nil, "error": "string is required"}, nil diff --git a/workflow/plugins/go/convert/convert_parse_json/package.json b/workflow/plugins/go/convert/convert_parse_json/package.json new file mode 100644 index 000000000..1c84b411a --- /dev/null +++ b/workflow/plugins/go/convert/convert_parse_json/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/convert_parse_json", + "version": "1.0.0", + "description": "Parse a JSON string to object", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin"], + "main": "convert_parse_json.go", + "metadata": { + "plugin_type": "convert.parse_json", + "category": "convert" + } +} diff --git a/workflow/plugins/go/convert/convert_to_boolean.go b/workflow/plugins/go/convert/convert_to_boolean/convert_to_boolean.go similarity index 69% rename from workflow/plugins/go/convert/convert_to_boolean.go rename to workflow/plugins/go/convert/convert_to_boolean/convert_to_boolean.go index 418c97da3..658a71a8a 100644 --- a/workflow/plugins/go/convert/convert_to_boolean.go +++ b/workflow/plugins/go/convert/convert_to_boolean/convert_to_boolean.go @@ -1,5 +1,5 @@ -// Package convert provides type conversion workflow plugins. -package convert +// Package convert_to_boolean provides the convert to boolean plugin. +package convert_to_boolean import ( "strings" @@ -7,8 +7,8 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// ToBoolean converts a value to boolean. -func ToBoolean(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run converts a value to boolean. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { value := inputs["value"] var result bool diff --git a/workflow/plugins/go/convert/convert_to_boolean/package.json b/workflow/plugins/go/convert/convert_to_boolean/package.json new file mode 100644 index 000000000..5bbe99ecb --- /dev/null +++ b/workflow/plugins/go/convert/convert_to_boolean/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/convert_to_boolean", + "version": "1.0.0", + "description": "Convert a value to boolean", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin"], + "main": "convert_to_boolean.go", + "metadata": { + "plugin_type": "convert.to_boolean", + "category": "convert" + } +} diff --git a/workflow/plugins/go/convert/convert_to_json.go b/workflow/plugins/go/convert/convert_to_json/convert_to_json.go similarity index 67% rename from workflow/plugins/go/convert/convert_to_json.go rename to workflow/plugins/go/convert/convert_to_json/convert_to_json.go index abe9344c0..544595e9f 100644 --- a/workflow/plugins/go/convert/convert_to_json.go +++ b/workflow/plugins/go/convert/convert_to_json/convert_to_json.go @@ -1,5 +1,5 @@ -// Package convert provides type conversion workflow plugins. -package convert +// Package convert_to_json provides the convert to JSON plugin. +package convert_to_json import ( "encoding/json" @@ -7,8 +7,8 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// ToJSON converts a value to JSON string. -func ToJSON(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run converts a value to JSON string. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { value := inputs["value"] pretty := false if p, ok := inputs["pretty"].(bool); ok { diff --git a/workflow/plugins/go/convert/convert_to_json/package.json b/workflow/plugins/go/convert/convert_to_json/package.json new file mode 100644 index 000000000..238a59659 --- /dev/null +++ b/workflow/plugins/go/convert/convert_to_json/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/convert_to_json", + "version": "1.0.0", + "description": "Convert a value to JSON string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin"], + "main": "convert_to_json.go", + "metadata": { + "plugin_type": "convert.to_json", + "category": "convert" + } +} diff --git a/workflow/plugins/go/convert/convert_to_number.go b/workflow/plugins/go/convert/convert_to_number/convert_to_number.go similarity index 73% rename from workflow/plugins/go/convert/convert_to_number.go rename to workflow/plugins/go/convert/convert_to_number/convert_to_number.go index 50c0fb1a4..54069179c 100644 --- a/workflow/plugins/go/convert/convert_to_number.go +++ b/workflow/plugins/go/convert/convert_to_number/convert_to_number.go @@ -1,5 +1,5 @@ -// Package convert provides type conversion workflow plugins. -package convert +// Package convert_to_number provides the convert to number plugin. +package convert_to_number import ( "strconv" @@ -7,8 +7,8 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// ToNumber converts a value to number. -func ToNumber(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run converts a value to number. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { value := inputs["value"] var result float64 diff --git a/workflow/plugins/go/convert/convert_to_number/package.json b/workflow/plugins/go/convert/convert_to_number/package.json new file mode 100644 index 000000000..62512df79 --- /dev/null +++ b/workflow/plugins/go/convert/convert_to_number/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/convert_to_number", + "version": "1.0.0", + "description": "Convert a value to number", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin"], + "main": "convert_to_number.go", + "metadata": { + "plugin_type": "convert.to_number", + "category": "convert" + } +} diff --git a/workflow/plugins/go/convert/convert_to_string.go b/workflow/plugins/go/convert/convert_to_string/convert_to_string.go similarity index 67% rename from workflow/plugins/go/convert/convert_to_string.go rename to workflow/plugins/go/convert/convert_to_string/convert_to_string.go index ed5a17c50..8faf85b4d 100644 --- a/workflow/plugins/go/convert/convert_to_string.go +++ b/workflow/plugins/go/convert/convert_to_string/convert_to_string.go @@ -1,5 +1,5 @@ -// Package convert provides type conversion workflow plugins. -package convert +// Package convert_to_string provides the convert to string plugin. +package convert_to_string import ( "encoding/json" @@ -8,8 +8,8 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// ToString converts a value to string. -func ToString(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run converts a value to string. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { value := inputs["value"] var result string diff --git a/workflow/plugins/go/convert/convert_to_string/package.json b/workflow/plugins/go/convert/convert_to_string/package.json new file mode 100644 index 000000000..c09d0f54e --- /dev/null +++ b/workflow/plugins/go/convert/convert_to_string/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/convert_to_string", + "version": "1.0.0", + "description": "Convert a value to string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin"], + "main": "convert_to_string.go", + "metadata": { + "plugin_type": "convert.to_string", + "category": "convert" + } +} diff --git a/workflow/plugins/go/convert/package.json b/workflow/plugins/go/convert/package.json new file mode 100644 index 000000000..a34aff5a4 --- /dev/null +++ b/workflow/plugins/go/convert/package.json @@ -0,0 +1,19 @@ +{ + "name": "@metabuilder/workflow-plugins-convert", + "version": "1.0.0", + "description": "Type conversion plugins", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugins"], + "metadata": { + "category": "convert", + "plugin_count": 5 + }, + "plugins": [ + "convert_parse_json", + "convert_to_boolean", + "convert_to_json", + "convert_to_number", + "convert_to_string" + ] +} diff --git a/workflow/plugins/go/dict/dict_delete.go b/workflow/plugins/go/dict/dict_delete/dict_delete.go similarity index 79% rename from workflow/plugins/go/dict/dict_delete.go rename to workflow/plugins/go/dict/dict_delete/dict_delete.go index 9dc415749..26653caa1 100644 --- a/workflow/plugins/go/dict/dict_delete.go +++ b/workflow/plugins/go/dict/dict_delete/dict_delete.go @@ -1,5 +1,5 @@ -// Package dict provides dictionary/map manipulation workflow plugins. -package dict +// Package dict_delete provides the dictionary delete plugin. +package dict_delete import ( "strings" @@ -7,22 +7,23 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Delete removes a key from a dictionary. +// Run removes a key from a dictionary. // Supports dot notation for nested keys (e.g., "user.name"). // Inputs: // - dict: the dictionary to modify // - key: the key to delete (supports dot notation) +// // Returns: // - result: the modified dictionary // - deleted: whether the key was found and deleted -func Delete(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { dict, ok := inputs["dict"].(map[string]interface{}) if !ok { return map[string]interface{}{"result": map[string]interface{}{}, "deleted": false}, nil } // Make a shallow copy to avoid mutating the original - dict = copyDictForDelete(dict) + dict = copyDict(dict) key, ok := inputs["key"].(string) if !ok { @@ -48,15 +49,15 @@ func Delete(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string] if val, exists := current[part]; exists { if nested, ok := val.(map[string]interface{}); ok { // Copy nested dict to avoid mutation - copied := copyDictForDelete(nested) + copied := copyDict(nested) current[part] = copied current = copied } else { - // Can't descend further + // Cannot descend further return map[string]interface{}{"result": dict, "deleted": false}, nil } } else { - // Path doesn't exist + // Path does not exist return map[string]interface{}{"result": dict, "deleted": false}, nil } } @@ -71,8 +72,8 @@ func Delete(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string] return map[string]interface{}{"result": dict, "deleted": false}, nil } -// copyDictForDelete creates a shallow copy of a dictionary. -func copyDictForDelete(d map[string]interface{}) map[string]interface{} { +// copyDict creates a shallow copy of a dictionary. +func copyDict(d map[string]interface{}) map[string]interface{} { result := make(map[string]interface{}, len(d)) for k, v := range d { result[k] = v diff --git a/workflow/plugins/go/dict/dict_delete/package.json b/workflow/plugins/go/dict/dict_delete/package.json new file mode 100644 index 000000000..f662db07f --- /dev/null +++ b/workflow/plugins/go/dict/dict_delete/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/dict_delete", + "version": "1.0.0", + "description": "Delete a key from a dictionary", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["dict", "workflow", "plugin"], + "main": "dict_delete.go", + "metadata": { + "plugin_type": "dict.delete", + "category": "dict" + } +} diff --git a/workflow/plugins/go/dict/dict_get.go b/workflow/plugins/go/dict/dict_get/dict_get.go similarity index 87% rename from workflow/plugins/go/dict/dict_get.go rename to workflow/plugins/go/dict/dict_get/dict_get.go index 4ddd268d1..1e3173ab9 100644 --- a/workflow/plugins/go/dict/dict_get.go +++ b/workflow/plugins/go/dict/dict_get/dict_get.go @@ -1,5 +1,5 @@ -// Package dict provides dictionary/map manipulation workflow plugins. -package dict +// Package dict_get provides the dictionary get plugin. +package dict_get import ( "strings" @@ -7,16 +7,17 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Get retrieves a value from a dictionary by key. +// Run retrieves a value from a dictionary by key. // Supports dot notation for nested keys (e.g., "user.name"). // Inputs: // - dict: the dictionary to read from // - key: the key to retrieve (supports dot notation) // - default: (optional) default value if key not found +// // Returns: // - result: the value at the key or default // - found: whether the key was found -func Get(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { dict, ok := inputs["dict"].(map[string]interface{}) if !ok { defaultVal := inputs["default"] @@ -43,7 +44,7 @@ func Get(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]int if nested, ok := val.(map[string]interface{}); ok { current = nested } else { - // Can't descend further + // Cannot descend further defaultVal := inputs["default"] return map[string]interface{}{"result": defaultVal, "found": false}, nil } diff --git a/workflow/plugins/go/dict/dict_get/package.json b/workflow/plugins/go/dict/dict_get/package.json new file mode 100644 index 000000000..c8761925e --- /dev/null +++ b/workflow/plugins/go/dict/dict_get/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/dict_get", + "version": "1.0.0", + "description": "Get a value from a dictionary by key", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["dict", "workflow", "plugin"], + "main": "dict_get.go", + "metadata": { + "plugin_type": "dict.get", + "category": "dict" + } +} diff --git a/workflow/plugins/go/dict/dict_keys.go b/workflow/plugins/go/dict/dict_keys/dict_keys.go similarity index 76% rename from workflow/plugins/go/dict/dict_keys.go rename to workflow/plugins/go/dict/dict_keys/dict_keys.go index 84d50640a..39863b5e1 100644 --- a/workflow/plugins/go/dict/dict_keys.go +++ b/workflow/plugins/go/dict/dict_keys/dict_keys.go @@ -1,5 +1,5 @@ -// Package dict provides dictionary/map manipulation workflow plugins. -package dict +// Package dict_keys provides the dictionary keys plugin. +package dict_keys import ( "sort" @@ -7,13 +7,14 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Keys returns all keys from a dictionary. +// Run returns all keys from a dictionary. // Inputs: // - dict: the dictionary to get keys from // - sorted: (optional) whether to sort keys alphabetically (default: false) +// // Returns: // - result: list of keys -func Keys(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { dict, ok := inputs["dict"].(map[string]interface{}) if !ok { return map[string]interface{}{"result": []interface{}{}}, nil diff --git a/workflow/plugins/go/dict/dict_keys/package.json b/workflow/plugins/go/dict/dict_keys/package.json new file mode 100644 index 000000000..867999f72 --- /dev/null +++ b/workflow/plugins/go/dict/dict_keys/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/dict_keys", + "version": "1.0.0", + "description": "Get all keys from a dictionary", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["dict", "workflow", "plugin"], + "main": "dict_keys.go", + "metadata": { + "plugin_type": "dict.keys", + "category": "dict" + } +} diff --git a/workflow/plugins/go/dict/dict_merge.go b/workflow/plugins/go/dict/dict_merge/dict_merge.go similarity index 86% rename from workflow/plugins/go/dict/dict_merge.go rename to workflow/plugins/go/dict/dict_merge/dict_merge.go index 44a0f1509..d2c6ce041 100644 --- a/workflow/plugins/go/dict/dict_merge.go +++ b/workflow/plugins/go/dict/dict_merge/dict_merge.go @@ -1,18 +1,19 @@ -// Package dict provides dictionary/map manipulation workflow plugins. -package dict +// Package dict_merge provides the dictionary merge plugin. +package dict_merge import ( plugin "metabuilder/workflow/plugins/go" ) -// Merge combines multiple dictionaries into one. +// Run combines multiple dictionaries into one. // Later dictionaries override earlier ones for duplicate keys. // Inputs: // - dicts: list of dictionaries to merge // - deep: (optional) perform deep merge for nested objects (default: false) +// // Returns: // - result: the merged dictionary -func Merge(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { dicts, ok := inputs["dicts"].([]interface{}) if !ok { return map[string]interface{}{"result": map[string]interface{}{}}, nil @@ -62,7 +63,7 @@ func deepMerge(dst, src map[string]interface{}) { continue } } - // Either key doesn't exist in dst, or types don't match - just copy + // Either key does not exist in dst, or types do not match - just copy dst[k] = deepCopyValue(srcVal) } } diff --git a/workflow/plugins/go/dict/dict_merge/package.json b/workflow/plugins/go/dict/dict_merge/package.json new file mode 100644 index 000000000..97fe5a5a8 --- /dev/null +++ b/workflow/plugins/go/dict/dict_merge/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/dict_merge", + "version": "1.0.0", + "description": "Merge multiple dictionaries into one", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["dict", "workflow", "plugin"], + "main": "dict_merge.go", + "metadata": { + "plugin_type": "dict.merge", + "category": "dict" + } +} diff --git a/workflow/plugins/go/dict/dict_set.go b/workflow/plugins/go/dict/dict_set/dict_set.go similarity index 90% rename from workflow/plugins/go/dict/dict_set.go rename to workflow/plugins/go/dict/dict_set/dict_set.go index 81d434cc3..ae37aefb2 100644 --- a/workflow/plugins/go/dict/dict_set.go +++ b/workflow/plugins/go/dict/dict_set/dict_set.go @@ -1,5 +1,5 @@ -// Package dict provides dictionary/map manipulation workflow plugins. -package dict +// Package dict_set provides the dictionary set plugin. +package dict_set import ( "strings" @@ -7,16 +7,17 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Set sets a value in a dictionary by key. +// Run sets a value in a dictionary by key. // Supports dot notation for nested keys (e.g., "user.name"). // Creates intermediate objects as needed. // Inputs: // - dict: the dictionary to modify (or nil to create new) // - key: the key to set (supports dot notation) // - value: the value to set +// // Returns: // - result: the modified dictionary -func Set(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { dict, ok := inputs["dict"].(map[string]interface{}) if !ok { dict = make(map[string]interface{}) diff --git a/workflow/plugins/go/dict/dict_set/package.json b/workflow/plugins/go/dict/dict_set/package.json new file mode 100644 index 000000000..bbf558153 --- /dev/null +++ b/workflow/plugins/go/dict/dict_set/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/dict_set", + "version": "1.0.0", + "description": "Set a value in a dictionary by key", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["dict", "workflow", "plugin"], + "main": "dict_set.go", + "metadata": { + "plugin_type": "dict.set", + "category": "dict" + } +} diff --git a/workflow/plugins/go/dict/dict_values.go b/workflow/plugins/go/dict/dict_values/dict_values.go similarity index 81% rename from workflow/plugins/go/dict/dict_values.go rename to workflow/plugins/go/dict/dict_values/dict_values.go index 6c8569e1e..6353a1214 100644 --- a/workflow/plugins/go/dict/dict_values.go +++ b/workflow/plugins/go/dict/dict_values/dict_values.go @@ -1,5 +1,5 @@ -// Package dict provides dictionary/map manipulation workflow plugins. -package dict +// Package dict_values provides the dictionary values plugin. +package dict_values import ( "sort" @@ -7,13 +7,14 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Values returns all values from a dictionary. +// Run returns all values from a dictionary. // Inputs: // - dict: the dictionary to get values from // - sorted_by_key: (optional) return values sorted by their keys (default: false) +// // Returns: // - result: list of values -func Values(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { dict, ok := inputs["dict"].(map[string]interface{}) if !ok { return map[string]interface{}{"result": []interface{}{}}, nil diff --git a/workflow/plugins/go/dict/dict_values/package.json b/workflow/plugins/go/dict/dict_values/package.json new file mode 100644 index 000000000..39a59b4ce --- /dev/null +++ b/workflow/plugins/go/dict/dict_values/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/dict_values", + "version": "1.0.0", + "description": "Get all values from a dictionary", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["dict", "workflow", "plugin"], + "main": "dict_values.go", + "metadata": { + "plugin_type": "dict.values", + "category": "dict" + } +} diff --git a/workflow/plugins/go/dict/package.json b/workflow/plugins/go/dict/package.json new file mode 100644 index 000000000..170036723 --- /dev/null +++ b/workflow/plugins/go/dict/package.json @@ -0,0 +1,20 @@ +{ + "name": "@metabuilder/workflow-plugins-dict", + "version": "1.0.0", + "description": "Dictionary manipulation plugins", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["dict", "workflow", "plugins"], + "metadata": { + "category": "dict", + "plugin_count": 6 + }, + "plugins": [ + "dict_delete", + "dict_get", + "dict_keys", + "dict_merge", + "dict_set", + "dict_values" + ] +} diff --git a/workflow/plugins/go/list/list_concat.go b/workflow/plugins/go/list/list_concat/list_concat.go similarity index 63% rename from workflow/plugins/go/list/list_concat.go rename to workflow/plugins/go/list/list_concat/list_concat.go index f6b1abbbf..0c2881325 100644 --- a/workflow/plugins/go/list/list_concat.go +++ b/workflow/plugins/go/list/list_concat/list_concat.go @@ -1,12 +1,12 @@ -// Package list provides list manipulation workflow plugins. -package list +// Package list_concat provides the concatenate lists plugin. +package list_concat import ( plugin "metabuilder/workflow/plugins/go" ) -// Concat concatenates multiple lists. -func Concat(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run concatenates multiple lists. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { lists, ok := inputs["lists"].([]interface{}) if !ok { return map[string]interface{}{"result": []interface{}{}}, nil diff --git a/workflow/plugins/go/list/list_concat/package.json b/workflow/plugins/go/list/list_concat/package.json new file mode 100644 index 000000000..7a0ce61c8 --- /dev/null +++ b/workflow/plugins/go/list/list_concat/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/list_concat", + "version": "1.0.0", + "description": "Concatenate multiple lists", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin"], + "main": "list_concat.go", + "metadata": { + "plugin_type": "list.concat", + "category": "list" + } +} diff --git a/workflow/plugins/go/list/list_find.go b/workflow/plugins/go/list/list_find/list_find.go similarity index 79% rename from workflow/plugins/go/list/list_find.go rename to workflow/plugins/go/list/list_find/list_find.go index 8cd1a61e2..20133a861 100644 --- a/workflow/plugins/go/list/list_find.go +++ b/workflow/plugins/go/list/list_find/list_find.go @@ -1,19 +1,20 @@ -// Package list provides list manipulation workflow plugins. -package list +// Package list_find provides the list find plugin. +package list_find import ( plugin "metabuilder/workflow/plugins/go" ) -// Find returns the first element matching a condition or key/value pair. +// Run returns the first element matching a condition or key/value pair. // Inputs: // - list: the list to search // - key: (optional) the key to match in objects // - value: the value to match (or condition value) +// // Returns: // - result: the first matching element or nil // - index: the index of the match or -1 -func Find(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { list, ok := inputs["list"].([]interface{}) if !ok { return map[string]interface{}{"result": nil, "index": -1}, nil diff --git a/workflow/plugins/go/list/list_find/package.json b/workflow/plugins/go/list/list_find/package.json new file mode 100644 index 000000000..ae3c23cbe --- /dev/null +++ b/workflow/plugins/go/list/list_find/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/list_find", + "version": "1.0.0", + "description": "Find first element matching a condition", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin"], + "main": "list_find.go", + "metadata": { + "plugin_type": "list.find", + "category": "list" + } +} diff --git a/workflow/plugins/go/list/list_length.go b/workflow/plugins/go/list/list_length/list_length.go similarity index 50% rename from workflow/plugins/go/list/list_length.go rename to workflow/plugins/go/list/list_length/list_length.go index 70efd64b8..2985bd332 100644 --- a/workflow/plugins/go/list/list_length.go +++ b/workflow/plugins/go/list/list_length/list_length.go @@ -1,12 +1,12 @@ -// Package list provides list manipulation workflow plugins. -package list +// Package list_length provides the list length plugin. +package list_length import ( plugin "metabuilder/workflow/plugins/go" ) -// Length returns the length of a list. -func Length(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run returns the length of a list. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { list, ok := inputs["list"].([]interface{}) if !ok { return map[string]interface{}{"result": 0}, nil diff --git a/workflow/plugins/go/list/list_length/package.json b/workflow/plugins/go/list/list_length/package.json new file mode 100644 index 000000000..1108ad759 --- /dev/null +++ b/workflow/plugins/go/list/list_length/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/list_length", + "version": "1.0.0", + "description": "Get the length of a list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin"], + "main": "list_length.go", + "metadata": { + "plugin_type": "list.length", + "category": "list" + } +} diff --git a/workflow/plugins/go/list/list_reverse.go b/workflow/plugins/go/list/list_reverse/list_reverse.go similarity index 61% rename from workflow/plugins/go/list/list_reverse.go rename to workflow/plugins/go/list/list_reverse/list_reverse.go index be33d8445..744399cf3 100644 --- a/workflow/plugins/go/list/list_reverse.go +++ b/workflow/plugins/go/list/list_reverse/list_reverse.go @@ -1,12 +1,12 @@ -// Package list provides list manipulation workflow plugins. -package list +// Package list_reverse provides the list reverse plugin. +package list_reverse import ( plugin "metabuilder/workflow/plugins/go" ) -// Reverse reverses a list. -func Reverse(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run reverses a list. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { list, ok := inputs["list"].([]interface{}) if !ok { return map[string]interface{}{"result": []interface{}{}}, nil diff --git a/workflow/plugins/go/list/list_reverse/package.json b/workflow/plugins/go/list/list_reverse/package.json new file mode 100644 index 000000000..622ac1cf3 --- /dev/null +++ b/workflow/plugins/go/list/list_reverse/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/list_reverse", + "version": "1.0.0", + "description": "Reverse a list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin"], + "main": "list_reverse.go", + "metadata": { + "plugin_type": "list.reverse", + "category": "list" + } +} diff --git a/workflow/plugins/go/list/list_slice.go b/workflow/plugins/go/list/list_slice/list_slice.go similarity index 74% rename from workflow/plugins/go/list/list_slice.go rename to workflow/plugins/go/list/list_slice/list_slice.go index 70481122b..721192a2b 100644 --- a/workflow/plugins/go/list/list_slice.go +++ b/workflow/plugins/go/list/list_slice/list_slice.go @@ -1,12 +1,12 @@ -// Package list provides list manipulation workflow plugins. -package list +// Package list_slice provides the list slice plugin. +package list_slice import ( plugin "metabuilder/workflow/plugins/go" ) -// Slice extracts a portion of a list. -func Slice(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run extracts a portion of a list. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { list, ok := inputs["list"].([]interface{}) if !ok { return map[string]interface{}{"result": []interface{}{}}, nil diff --git a/workflow/plugins/go/list/list_slice/package.json b/workflow/plugins/go/list/list_slice/package.json new file mode 100644 index 000000000..98729c4c6 --- /dev/null +++ b/workflow/plugins/go/list/list_slice/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/list_slice", + "version": "1.0.0", + "description": "Extract a portion of a list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin"], + "main": "list_slice.go", + "metadata": { + "plugin_type": "list.slice", + "category": "list" + } +} diff --git a/workflow/plugins/go/list/list_sort.go b/workflow/plugins/go/list/list_sort/list_sort.go similarity index 90% rename from workflow/plugins/go/list/list_sort.go rename to workflow/plugins/go/list/list_sort/list_sort.go index 8fb06f33f..e5344c958 100644 --- a/workflow/plugins/go/list/list_sort.go +++ b/workflow/plugins/go/list/list_sort/list_sort.go @@ -1,5 +1,5 @@ -// Package list provides list manipulation workflow plugins. -package list +// Package list_sort provides the list sort plugin. +package list_sort import ( "sort" @@ -7,14 +7,15 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Sort sorts a list of values. +// Run sorts a list of values. // Inputs: // - list: the list to sort // - key: (optional) the key to sort by for objects // - descending: (optional) sort in descending order (default: false) +// // Returns: // - result: the sorted list -func Sort(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { list, ok := inputs["list"].([]interface{}) if !ok { return map[string]interface{}{"result": []interface{}{}}, nil diff --git a/workflow/plugins/go/list/list_sort/package.json b/workflow/plugins/go/list/list_sort/package.json new file mode 100644 index 000000000..94a4651e2 --- /dev/null +++ b/workflow/plugins/go/list/list_sort/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/list_sort", + "version": "1.0.0", + "description": "Sort a list of values", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin"], + "main": "list_sort.go", + "metadata": { + "plugin_type": "list.sort", + "category": "list" + } +} diff --git a/workflow/plugins/go/list/list_unique.go b/workflow/plugins/go/list/list_unique/list_unique.go similarity index 87% rename from workflow/plugins/go/list/list_unique.go rename to workflow/plugins/go/list/list_unique/list_unique.go index 98cd155d9..15b2e3b04 100644 --- a/workflow/plugins/go/list/list_unique.go +++ b/workflow/plugins/go/list/list_unique/list_unique.go @@ -1,5 +1,5 @@ -// Package list provides list manipulation workflow plugins. -package list +// Package list_unique provides the list unique plugin. +package list_unique import ( "encoding/json" @@ -7,13 +7,14 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Unique removes duplicate elements from a list. +// Run removes duplicate elements from a list. // Inputs: // - list: the list to deduplicate // - key: (optional) the key to use for uniqueness in objects +// // Returns: // - result: the list with duplicates removed -func Unique(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { list, ok := inputs["list"].([]interface{}) if !ok { return map[string]interface{}{"result": []interface{}{}}, nil diff --git a/workflow/plugins/go/list/list_unique/package.json b/workflow/plugins/go/list/list_unique/package.json new file mode 100644 index 000000000..a2077fed0 --- /dev/null +++ b/workflow/plugins/go/list/list_unique/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/list_unique", + "version": "1.0.0", + "description": "Remove duplicate elements from a list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin"], + "main": "list_unique.go", + "metadata": { + "plugin_type": "list.unique", + "category": "list" + } +} diff --git a/workflow/plugins/go/list/package.json b/workflow/plugins/go/list/package.json new file mode 100644 index 000000000..ce47d8e79 --- /dev/null +++ b/workflow/plugins/go/list/package.json @@ -0,0 +1,21 @@ +{ + "name": "@metabuilder/workflow-plugins-list", + "version": "1.0.0", + "description": "List manipulation plugins", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugins"], + "metadata": { + "category": "list", + "plugin_count": 7 + }, + "plugins": [ + "list_concat", + "list_find", + "list_length", + "list_reverse", + "list_slice", + "list_sort", + "list_unique" + ] +} diff --git a/workflow/plugins/go/logic/logic_and.go b/workflow/plugins/go/logic/logic_and/logic_and.go similarity index 76% rename from workflow/plugins/go/logic/logic_and.go rename to workflow/plugins/go/logic/logic_and/logic_and.go index 2416f6213..3fd488440 100644 --- a/workflow/plugins/go/logic/logic_and.go +++ b/workflow/plugins/go/logic/logic_and/logic_and.go @@ -1,12 +1,12 @@ -// Package logic provides boolean logic workflow plugins. -package logic +// Package logic_and provides the logical AND plugin. +package logic_and import ( plugin "metabuilder/workflow/plugins/go" ) -// And performs logical AND on boolean values. -func And(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run performs logical AND on boolean values. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { values, ok := inputs["values"].([]interface{}) if !ok || len(values) == 0 { return map[string]interface{}{"result": false}, nil diff --git a/workflow/plugins/go/logic/logic_and/package.json b/workflow/plugins/go/logic/logic_and/package.json new file mode 100644 index 000000000..9620443a0 --- /dev/null +++ b/workflow/plugins/go/logic/logic_and/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_and", + "version": "1.0.0", + "description": "Perform logical AND on boolean values", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_and.go", + "metadata": { + "plugin_type": "logic.and", + "category": "logic" + } +} diff --git a/workflow/plugins/go/logic/logic_equals.go b/workflow/plugins/go/logic/logic_equals.go deleted file mode 100644 index a63d09e0a..000000000 --- a/workflow/plugins/go/logic/logic_equals.go +++ /dev/null @@ -1,17 +0,0 @@ -// Package logic provides boolean logic workflow plugins. -package logic - -import ( - "reflect" - - plugin "metabuilder/workflow/plugins/go" -) - -// Equals checks if two values are equal. -func Equals(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { - a := inputs["a"] - b := inputs["b"] - - result := reflect.DeepEqual(a, b) - return map[string]interface{}{"result": result}, nil -} diff --git a/workflow/plugins/go/logic/logic_equals/logic_equals.go b/workflow/plugins/go/logic/logic_equals/logic_equals.go new file mode 100644 index 000000000..63783ecf4 --- /dev/null +++ b/workflow/plugins/go/logic/logic_equals/logic_equals.go @@ -0,0 +1,17 @@ +// Package logic_equals provides the equality check plugin. +package logic_equals + +import ( + "reflect" + + plugin "metabuilder/workflow/plugins/go" +) + +// Run checks if two values are equal. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { + a := inputs["a"] + b := inputs["b"] + + result := reflect.DeepEqual(a, b) + return map[string]interface{}{"result": result}, nil +} diff --git a/workflow/plugins/go/logic/logic_equals/package.json b/workflow/plugins/go/logic/logic_equals/package.json new file mode 100644 index 000000000..e716af215 --- /dev/null +++ b/workflow/plugins/go/logic/logic_equals/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_equals", + "version": "1.0.0", + "description": "Check if two values are equal", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_equals.go", + "metadata": { + "plugin_type": "logic.equals", + "category": "logic" + } +} diff --git a/workflow/plugins/go/logic/logic_gt.go b/workflow/plugins/go/logic/logic_gt/logic_gt.go similarity index 61% rename from workflow/plugins/go/logic/logic_gt.go rename to workflow/plugins/go/logic/logic_gt/logic_gt.go index dec076e72..58699654b 100644 --- a/workflow/plugins/go/logic/logic_gt.go +++ b/workflow/plugins/go/logic/logic_gt/logic_gt.go @@ -1,12 +1,12 @@ -// Package logic provides boolean logic workflow plugins. -package logic +// Package logic_gt provides the greater than comparison plugin. +package logic_gt import ( plugin "metabuilder/workflow/plugins/go" ) -// GreaterThan checks if a > b. -func GreaterThan(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run checks if a > b. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { a := toFloat(inputs["a"]) b := toFloat(inputs["b"]) diff --git a/workflow/plugins/go/logic/logic_gt/package.json b/workflow/plugins/go/logic/logic_gt/package.json new file mode 100644 index 000000000..f535930ca --- /dev/null +++ b/workflow/plugins/go/logic/logic_gt/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_gt", + "version": "1.0.0", + "description": "Check if a is greater than b", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_gt.go", + "metadata": { + "plugin_type": "logic.gt", + "category": "logic" + } +} diff --git a/workflow/plugins/go/logic/logic_lt.go b/workflow/plugins/go/logic/logic_lt.go deleted file mode 100644 index 7159def1a..000000000 --- a/workflow/plugins/go/logic/logic_lt.go +++ /dev/null @@ -1,14 +0,0 @@ -// Package logic provides boolean logic workflow plugins. -package logic - -import ( - plugin "metabuilder/workflow/plugins/go" -) - -// LessThan checks if a < b. -func LessThan(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { - a := toFloat(inputs["a"]) - b := toFloat(inputs["b"]) - - return map[string]interface{}{"result": a < b}, nil -} diff --git a/workflow/plugins/go/logic/logic_lt/logic_lt.go b/workflow/plugins/go/logic/logic_lt/logic_lt.go new file mode 100644 index 000000000..f5d0d73d0 --- /dev/null +++ b/workflow/plugins/go/logic/logic_lt/logic_lt.go @@ -0,0 +1,27 @@ +// Package logic_lt provides the less than comparison plugin. +package logic_lt + +import ( + plugin "metabuilder/workflow/plugins/go" +) + +// Run checks if a < b. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { + a := toFloat(inputs["a"]) + b := toFloat(inputs["b"]) + + return map[string]interface{}{"result": a < b}, nil +} + +func toFloat(v interface{}) float64 { + switch n := v.(type) { + case float64: + return n + case int: + return float64(n) + case int64: + return float64(n) + default: + return 0 + } +} diff --git a/workflow/plugins/go/logic/logic_lt/package.json b/workflow/plugins/go/logic/logic_lt/package.json new file mode 100644 index 000000000..82667f2f5 --- /dev/null +++ b/workflow/plugins/go/logic/logic_lt/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_lt", + "version": "1.0.0", + "description": "Check if a is less than b", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_lt.go", + "metadata": { + "plugin_type": "logic.lt", + "category": "logic" + } +} diff --git a/workflow/plugins/go/logic/logic_not.go b/workflow/plugins/go/logic/logic_not.go deleted file mode 100644 index dcf9d3b0d..000000000 --- a/workflow/plugins/go/logic/logic_not.go +++ /dev/null @@ -1,12 +0,0 @@ -// Package logic provides boolean logic workflow plugins. -package logic - -import ( - plugin "metabuilder/workflow/plugins/go" -) - -// Not performs logical NOT on a boolean value. -func Not(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { - value := inputs["value"] - return map[string]interface{}{"result": !toBool(value)}, nil -} diff --git a/workflow/plugins/go/logic/logic_not/logic_not.go b/workflow/plugins/go/logic/logic_not/logic_not.go new file mode 100644 index 000000000..2a6c9591d --- /dev/null +++ b/workflow/plugins/go/logic/logic_not/logic_not.go @@ -0,0 +1,27 @@ +// Package logic_not provides the logical NOT plugin. +package logic_not + +import ( + plugin "metabuilder/workflow/plugins/go" +) + +// Run performs logical NOT on a boolean value. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { + value := inputs["value"] + return map[string]interface{}{"result": !toBool(value)}, nil +} + +func toBool(v interface{}) bool { + switch b := v.(type) { + case bool: + return b + case int: + return b != 0 + case float64: + return b != 0 + case string: + return b != "" + default: + return v != nil + } +} diff --git a/workflow/plugins/go/logic/logic_not/package.json b/workflow/plugins/go/logic/logic_not/package.json new file mode 100644 index 000000000..ad540d566 --- /dev/null +++ b/workflow/plugins/go/logic/logic_not/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_not", + "version": "1.0.0", + "description": "Perform logical NOT on a boolean value", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_not.go", + "metadata": { + "plugin_type": "logic.not", + "category": "logic" + } +} diff --git a/workflow/plugins/go/logic/logic_or.go b/workflow/plugins/go/logic/logic_or.go deleted file mode 100644 index 43e99ae9f..000000000 --- a/workflow/plugins/go/logic/logic_or.go +++ /dev/null @@ -1,22 +0,0 @@ -// Package logic provides boolean logic workflow plugins. -package logic - -import ( - plugin "metabuilder/workflow/plugins/go" -) - -// Or performs logical OR on boolean values. -func Or(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { - values, ok := inputs["values"].([]interface{}) - if !ok || len(values) == 0 { - return map[string]interface{}{"result": false}, nil - } - - for _, v := range values { - if toBool(v) { - return map[string]interface{}{"result": true}, nil - } - } - - return map[string]interface{}{"result": false}, nil -} diff --git a/workflow/plugins/go/logic/logic_or/logic_or.go b/workflow/plugins/go/logic/logic_or/logic_or.go new file mode 100644 index 000000000..07b006a77 --- /dev/null +++ b/workflow/plugins/go/logic/logic_or/logic_or.go @@ -0,0 +1,37 @@ +// Package logic_or provides the logical OR plugin. +package logic_or + +import ( + plugin "metabuilder/workflow/plugins/go" +) + +// Run performs logical OR on boolean values. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { + values, ok := inputs["values"].([]interface{}) + if !ok || len(values) == 0 { + return map[string]interface{}{"result": false}, nil + } + + for _, v := range values { + if toBool(v) { + return map[string]interface{}{"result": true}, nil + } + } + + return map[string]interface{}{"result": false}, nil +} + +func toBool(v interface{}) bool { + switch b := v.(type) { + case bool: + return b + case int: + return b != 0 + case float64: + return b != 0 + case string: + return b != "" + default: + return v != nil + } +} diff --git a/workflow/plugins/go/logic/logic_or/package.json b/workflow/plugins/go/logic/logic_or/package.json new file mode 100644 index 000000000..03b577216 --- /dev/null +++ b/workflow/plugins/go/logic/logic_or/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/logic_or", + "version": "1.0.0", + "description": "Perform logical OR on boolean values", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin"], + "main": "logic_or.go", + "metadata": { + "plugin_type": "logic.or", + "category": "logic" + } +} diff --git a/workflow/plugins/go/logic/package.json b/workflow/plugins/go/logic/package.json new file mode 100644 index 000000000..64db8934b --- /dev/null +++ b/workflow/plugins/go/logic/package.json @@ -0,0 +1,20 @@ +{ + "name": "@metabuilder/workflow-plugins-logic", + "version": "1.0.0", + "description": "Boolean logic plugins", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugins"], + "metadata": { + "category": "logic", + "plugin_count": 6 + }, + "plugins": [ + "logic_and", + "logic_equals", + "logic_gt", + "logic_lt", + "logic_not", + "logic_or" + ] +} diff --git a/workflow/plugins/go/math/math_add.go b/workflow/plugins/go/math/math_add/math_add.go similarity index 73% rename from workflow/plugins/go/math/math_add.go rename to workflow/plugins/go/math/math_add/math_add.go index c341c27d8..cfdad2a7e 100644 --- a/workflow/plugins/go/math/math_add.go +++ b/workflow/plugins/go/math/math_add/math_add.go @@ -1,12 +1,12 @@ -// Package math provides mathematical workflow plugins. -package math +// Package math_add provides the add numbers plugin. +package math_add import ( plugin "metabuilder/workflow/plugins/go" ) -// Add adds two or more numbers. -func Add(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run adds two or more numbers. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { numbers, ok := inputs["numbers"].([]interface{}) if !ok { return map[string]interface{}{"result": 0, "error": "numbers must be an array"}, nil diff --git a/workflow/plugins/go/math/math_add/package.json b/workflow/plugins/go/math/math_add/package.json new file mode 100644 index 000000000..dd311f655 --- /dev/null +++ b/workflow/plugins/go/math/math_add/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/math_add", + "version": "1.0.0", + "description": "Add two or more numbers", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin"], + "main": "math_add.go", + "metadata": { + "plugin_type": "math.add", + "category": "math" + } +} diff --git a/workflow/plugins/go/math/math_divide.go b/workflow/plugins/go/math/math_divide/math_divide.go similarity index 54% rename from workflow/plugins/go/math/math_divide.go rename to workflow/plugins/go/math/math_divide/math_divide.go index 45d6a0bf1..03b3d7028 100644 --- a/workflow/plugins/go/math/math_divide.go +++ b/workflow/plugins/go/math/math_divide/math_divide.go @@ -1,5 +1,5 @@ -// Package math provides mathematical workflow plugins. -package math +// Package math_divide provides the divide numbers plugin. +package math_divide import ( "errors" @@ -7,8 +7,8 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Divide divides the first number by subsequent numbers. -func Divide(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run divides the first number by subsequent numbers. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { numbers, ok := inputs["numbers"].([]interface{}) if !ok || len(numbers) < 2 { return map[string]interface{}{"result": 0, "error": "numbers must have at least 2 elements"}, nil @@ -25,3 +25,16 @@ func Divide(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string] return map[string]interface{}{"result": result}, nil } + +func toFloat64(v interface{}) float64 { + switch n := v.(type) { + case float64: + return n + case int: + return float64(n) + case int64: + return float64(n) + default: + return 0 + } +} diff --git a/workflow/plugins/go/math/math_divide/package.json b/workflow/plugins/go/math/math_divide/package.json new file mode 100644 index 000000000..c4b5a4545 --- /dev/null +++ b/workflow/plugins/go/math/math_divide/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/math_divide", + "version": "1.0.0", + "description": "Divide the first number by subsequent numbers", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin"], + "main": "math_divide.go", + "metadata": { + "plugin_type": "math.divide", + "category": "math" + } +} diff --git a/workflow/plugins/go/math/math_multiply.go b/workflow/plugins/go/math/math_multiply.go deleted file mode 100644 index 9488fa252..000000000 --- a/workflow/plugins/go/math/math_multiply.go +++ /dev/null @@ -1,21 +0,0 @@ -// Package math provides mathematical workflow plugins. -package math - -import ( - plugin "metabuilder/workflow/plugins/go" -) - -// Multiply multiplies two or more numbers. -func Multiply(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { - numbers, ok := inputs["numbers"].([]interface{}) - if !ok || len(numbers) == 0 { - return map[string]interface{}{"result": 0, "error": "numbers must be a non-empty array"}, nil - } - - result := 1.0 - for _, n := range numbers { - result *= toFloat64(n) - } - - return map[string]interface{}{"result": result}, nil -} diff --git a/workflow/plugins/go/math/math_multiply/math_multiply.go b/workflow/plugins/go/math/math_multiply/math_multiply.go new file mode 100644 index 000000000..935512f2b --- /dev/null +++ b/workflow/plugins/go/math/math_multiply/math_multiply.go @@ -0,0 +1,34 @@ +// Package math_multiply provides the multiply numbers plugin. +package math_multiply + +import ( + plugin "metabuilder/workflow/plugins/go" +) + +// Run multiplies two or more numbers. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { + numbers, ok := inputs["numbers"].([]interface{}) + if !ok || len(numbers) == 0 { + return map[string]interface{}{"result": 0, "error": "numbers must be a non-empty array"}, nil + } + + result := 1.0 + for _, n := range numbers { + result *= toFloat64(n) + } + + return map[string]interface{}{"result": result}, nil +} + +func toFloat64(v interface{}) float64 { + switch n := v.(type) { + case float64: + return n + case int: + return float64(n) + case int64: + return float64(n) + default: + return 0 + } +} diff --git a/workflow/plugins/go/math/math_multiply/package.json b/workflow/plugins/go/math/math_multiply/package.json new file mode 100644 index 000000000..bcb47dfed --- /dev/null +++ b/workflow/plugins/go/math/math_multiply/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/math_multiply", + "version": "1.0.0", + "description": "Multiply two or more numbers", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin"], + "main": "math_multiply.go", + "metadata": { + "plugin_type": "math.multiply", + "category": "math" + } +} diff --git a/workflow/plugins/go/math/math_subtract.go b/workflow/plugins/go/math/math_subtract/math_subtract.go similarity index 71% rename from workflow/plugins/go/math/math_subtract.go rename to workflow/plugins/go/math/math_subtract/math_subtract.go index 3882e499c..9fb0f58d0 100644 --- a/workflow/plugins/go/math/math_subtract.go +++ b/workflow/plugins/go/math/math_subtract/math_subtract.go @@ -1,12 +1,12 @@ -// Package math provides mathematical workflow plugins. -package math +// Package math_subtract provides the subtract numbers plugin. +package math_subtract import ( plugin "metabuilder/workflow/plugins/go" ) -// Subtract subtracts numbers from the first number. -func Subtract(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run subtracts numbers from the first number. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { numbers, ok := inputs["numbers"].([]interface{}) if !ok || len(numbers) == 0 { return map[string]interface{}{"result": 0, "error": "numbers must be a non-empty array"}, nil diff --git a/workflow/plugins/go/math/math_subtract/package.json b/workflow/plugins/go/math/math_subtract/package.json new file mode 100644 index 000000000..37f561e3f --- /dev/null +++ b/workflow/plugins/go/math/math_subtract/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/math_subtract", + "version": "1.0.0", + "description": "Subtract numbers from the first number", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin"], + "main": "math_subtract.go", + "metadata": { + "plugin_type": "math.subtract", + "category": "math" + } +} diff --git a/workflow/plugins/go/math/package.json b/workflow/plugins/go/math/package.json new file mode 100644 index 000000000..57e731cdd --- /dev/null +++ b/workflow/plugins/go/math/package.json @@ -0,0 +1,18 @@ +{ + "name": "@metabuilder/workflow-plugins-math", + "version": "1.0.0", + "description": "Mathematical operation plugins", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugins"], + "metadata": { + "category": "math", + "plugin_count": 4 + }, + "plugins": [ + "math_add", + "math_divide", + "math_multiply", + "math_subtract" + ] +} diff --git a/workflow/plugins/go/string/package.json b/workflow/plugins/go/string/package.json new file mode 100644 index 000000000..d5032209d --- /dev/null +++ b/workflow/plugins/go/string/package.json @@ -0,0 +1,19 @@ +{ + "name": "@metabuilder/workflow-plugins-string", + "version": "1.0.0", + "description": "String manipulation plugins", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugins"], + "metadata": { + "category": "string", + "plugin_count": 5 + }, + "plugins": [ + "string_concat", + "string_lower", + "string_replace", + "string_split", + "string_upper" + ] +} diff --git a/workflow/plugins/go/string/string_concat/package.json b/workflow/plugins/go/string/string_concat/package.json new file mode 100644 index 000000000..e9d1afb0e --- /dev/null +++ b/workflow/plugins/go/string/string_concat/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_concat", + "version": "1.0.0", + "description": "Concatenate multiple strings with optional separator", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_concat.go", + "metadata": { + "plugin_type": "string.concat", + "category": "string" + } +} diff --git a/workflow/plugins/go/string/string_concat.go b/workflow/plugins/go/string/string_concat/string_concat.go similarity index 66% rename from workflow/plugins/go/string/string_concat.go rename to workflow/plugins/go/string/string_concat/string_concat.go index 7ffcf99e5..1f95b5436 100644 --- a/workflow/plugins/go/string/string_concat.go +++ b/workflow/plugins/go/string/string_concat/string_concat.go @@ -1,5 +1,5 @@ -// Package string provides string manipulation workflow plugins. -package string +// Package string_concat provides the concatenate strings plugin. +package string_concat import ( "fmt" @@ -8,8 +8,8 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Concat concatenates multiple strings with optional separator. -func Concat(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run concatenates multiple strings with optional separator. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { strs, ok := inputs["strings"].([]interface{}) if !ok { return map[string]interface{}{"result": "", "error": "strings must be an array"}, nil diff --git a/workflow/plugins/go/string/string_lower/package.json b/workflow/plugins/go/string/string_lower/package.json new file mode 100644 index 000000000..9328f82c5 --- /dev/null +++ b/workflow/plugins/go/string/string_lower/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_lower", + "version": "1.0.0", + "description": "Convert string to lowercase", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_lower.go", + "metadata": { + "plugin_type": "string.lower", + "category": "string" + } +} diff --git a/workflow/plugins/go/string/string_lower.go b/workflow/plugins/go/string/string_lower/string_lower.go similarity index 55% rename from workflow/plugins/go/string/string_lower.go rename to workflow/plugins/go/string/string_lower/string_lower.go index 44913c4bb..edddad22c 100644 --- a/workflow/plugins/go/string/string_lower.go +++ b/workflow/plugins/go/string/string_lower/string_lower.go @@ -1,5 +1,5 @@ -// Package string provides string manipulation workflow plugins. -package string +// Package string_lower provides the lowercase string plugin. +package string_lower import ( "strings" @@ -7,8 +7,8 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Lower converts string to lowercase. -func Lower(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run converts string to lowercase. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { str, ok := inputs["string"].(string) if !ok { return map[string]interface{}{"result": "", "error": "string is required"}, nil diff --git a/workflow/plugins/go/string/string_replace/package.json b/workflow/plugins/go/string/string_replace/package.json new file mode 100644 index 000000000..6e0b296ea --- /dev/null +++ b/workflow/plugins/go/string/string_replace/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_replace", + "version": "1.0.0", + "description": "Replace occurrences in a string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_replace.go", + "metadata": { + "plugin_type": "string.replace", + "category": "string" + } +} diff --git a/workflow/plugins/go/string/string_replace.go b/workflow/plugins/go/string/string_replace/string_replace.go similarity index 67% rename from workflow/plugins/go/string/string_replace.go rename to workflow/plugins/go/string/string_replace/string_replace.go index 900b94618..143e9200f 100644 --- a/workflow/plugins/go/string/string_replace.go +++ b/workflow/plugins/go/string/string_replace/string_replace.go @@ -1,5 +1,5 @@ -// Package string provides string manipulation workflow plugins. -package string +// Package string_replace provides the replace string plugin. +package string_replace import ( "strings" @@ -7,8 +7,8 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Replace replaces occurrences in a string. -func Replace(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run replaces occurrences in a string. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { str, ok := inputs["string"].(string) if !ok { return map[string]interface{}{"result": "", "error": "string is required"}, nil diff --git a/workflow/plugins/go/string/string_split/package.json b/workflow/plugins/go/string/string_split/package.json new file mode 100644 index 000000000..dfe34cff5 --- /dev/null +++ b/workflow/plugins/go/string/string_split/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_split", + "version": "1.0.0", + "description": "Split a string by separator", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_split.go", + "metadata": { + "plugin_type": "string.split", + "category": "string" + } +} diff --git a/workflow/plugins/go/string/string_split.go b/workflow/plugins/go/string/string_split/string_split.go similarity index 71% rename from workflow/plugins/go/string/string_split.go rename to workflow/plugins/go/string/string_split/string_split.go index babbbb479..b4f56e11c 100644 --- a/workflow/plugins/go/string/string_split.go +++ b/workflow/plugins/go/string/string_split/string_split.go @@ -1,5 +1,5 @@ -// Package string provides string manipulation workflow plugins. -package string +// Package string_split provides the split string plugin. +package string_split import ( "strings" @@ -7,8 +7,8 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Split splits a string by separator. -func Split(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run splits a string by separator. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { str, ok := inputs["string"].(string) if !ok { return map[string]interface{}{"result": []string{}, "error": "string is required"}, nil diff --git a/workflow/plugins/go/string/string_upper/package.json b/workflow/plugins/go/string/string_upper/package.json new file mode 100644 index 000000000..3eb959e26 --- /dev/null +++ b/workflow/plugins/go/string/string_upper/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_upper", + "version": "1.0.0", + "description": "Convert string to uppercase", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_upper.go", + "metadata": { + "plugin_type": "string.upper", + "category": "string" + } +} diff --git a/workflow/plugins/go/string/string_upper.go b/workflow/plugins/go/string/string_upper/string_upper.go similarity index 55% rename from workflow/plugins/go/string/string_upper.go rename to workflow/plugins/go/string/string_upper/string_upper.go index 086a6aea5..8193021a2 100644 --- a/workflow/plugins/go/string/string_upper.go +++ b/workflow/plugins/go/string/string_upper/string_upper.go @@ -1,5 +1,5 @@ -// Package string provides string manipulation workflow plugins. -package string +// Package string_upper provides the uppercase string plugin. +package string_upper import ( "strings" @@ -7,8 +7,8 @@ import ( plugin "metabuilder/workflow/plugins/go" ) -// Upper converts string to uppercase. -func Upper(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run converts string to uppercase. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { str, ok := inputs["string"].(string) if !ok { return map[string]interface{}{"result": "", "error": "string is required"}, nil diff --git a/workflow/plugins/go/var/package.json b/workflow/plugins/go/var/package.json new file mode 100644 index 000000000..1b3cf05d3 --- /dev/null +++ b/workflow/plugins/go/var/package.json @@ -0,0 +1,17 @@ +{ + "name": "@metabuilder/workflow-plugins-var", + "version": "1.0.0", + "description": "Variable management plugins", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "workflow", "plugins"], + "metadata": { + "category": "var", + "plugin_count": 3 + }, + "plugins": [ + "var_delete", + "var_get", + "var_set" + ] +} diff --git a/workflow/plugins/go/var/var_delete/package.json b/workflow/plugins/go/var/var_delete/package.json new file mode 100644 index 000000000..81f963798 --- /dev/null +++ b/workflow/plugins/go/var/var_delete/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/var_delete", + "version": "1.0.0", + "description": "Delete a variable from the workflow store", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "workflow", "plugin"], + "main": "var_delete.go", + "metadata": { + "plugin_type": "var.delete", + "category": "var" + } +} diff --git a/workflow/plugins/go/var/var_delete.go b/workflow/plugins/go/var/var_delete/var_delete.go similarity index 57% rename from workflow/plugins/go/var/var_delete.go rename to workflow/plugins/go/var/var_delete/var_delete.go index 6b98208ff..ea4f5b029 100644 --- a/workflow/plugins/go/var/var_delete.go +++ b/workflow/plugins/go/var/var_delete/var_delete.go @@ -1,12 +1,12 @@ -// Package variable provides variable management workflow plugins. -package variable +// Package var_delete provides the variable delete plugin. +package var_delete import ( plugin "metabuilder/workflow/plugins/go" ) -// Delete removes a variable from the workflow store. -func Delete(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run removes a variable from the workflow store. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { key, ok := inputs["key"].(string) if !ok { return map[string]interface{}{"success": false, "error": "key is required"}, nil diff --git a/workflow/plugins/go/var/var_get/package.json b/workflow/plugins/go/var/var_get/package.json new file mode 100644 index 000000000..6fd279a61 --- /dev/null +++ b/workflow/plugins/go/var/var_get/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/var_get", + "version": "1.0.0", + "description": "Get a variable from the workflow store", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "workflow", "plugin"], + "main": "var_get.go", + "metadata": { + "plugin_type": "var.get", + "category": "var" + } +} diff --git a/workflow/plugins/go/var/var_get.go b/workflow/plugins/go/var/var_get/var_get.go similarity index 68% rename from workflow/plugins/go/var/var_get.go rename to workflow/plugins/go/var/var_get/var_get.go index 19d3bf4f2..1d63f0fd3 100644 --- a/workflow/plugins/go/var/var_get.go +++ b/workflow/plugins/go/var/var_get/var_get.go @@ -1,12 +1,12 @@ -// Package variable provides variable management workflow plugins. -package variable +// Package var_get provides the variable get plugin. +package var_get import ( plugin "metabuilder/workflow/plugins/go" ) -// Get retrieves a variable from the workflow store. -func Get(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run retrieves a variable from the workflow store. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { key, ok := inputs["key"].(string) if !ok { return map[string]interface{}{ diff --git a/workflow/plugins/go/var/var_set/package.json b/workflow/plugins/go/var/var_set/package.json new file mode 100644 index 000000000..debe2bfc1 --- /dev/null +++ b/workflow/plugins/go/var/var_set/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/var_set", + "version": "1.0.0", + "description": "Set a variable in the workflow store", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "workflow", "plugin"], + "main": "var_set.go", + "metadata": { + "plugin_type": "var.set", + "category": "var" + } +} diff --git a/workflow/plugins/go/var/var_set.go b/workflow/plugins/go/var/var_set/var_set.go similarity index 63% rename from workflow/plugins/go/var/var_set.go rename to workflow/plugins/go/var/var_set/var_set.go index f8909450b..d892f4ba6 100644 --- a/workflow/plugins/go/var/var_set.go +++ b/workflow/plugins/go/var/var_set/var_set.go @@ -1,12 +1,12 @@ -// Package variable provides variable management workflow plugins. -package variable +// Package var_set provides the variable set plugin. +package var_set import ( plugin "metabuilder/workflow/plugins/go" ) -// Set stores a variable in the workflow store. -func Set(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { +// Run stores a variable in the workflow store. +func Run(runtime *plugin.Runtime, inputs map[string]interface{}) (map[string]interface{}, error) { key, ok := inputs["key"].(string) if !ok { return map[string]interface{}{"success": false, "error": "key is required"}, nil diff --git a/workflow/plugins/mojo/list/list_concat.mojo b/workflow/plugins/mojo/list/list_concat/list_concat.mojo similarity index 100% rename from workflow/plugins/mojo/list/list_concat.mojo rename to workflow/plugins/mojo/list/list_concat/list_concat.mojo diff --git a/workflow/plugins/mojo/list/list_concat/package.json b/workflow/plugins/mojo/list/list_concat/package.json new file mode 100644 index 000000000..04eed0fd2 --- /dev/null +++ b/workflow/plugins/mojo/list/list_concat/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/list_concat", + "version": "1.0.0", + "description": "Concatenate multiple lists into one", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin"], + "main": "list_concat.mojo", + "metadata": { + "plugin_type": "list.concat", + "category": "list" + } +} diff --git a/workflow/plugins/mojo/list/list_length.mojo b/workflow/plugins/mojo/list/list_length/list_length.mojo similarity index 100% rename from workflow/plugins/mojo/list/list_length.mojo rename to workflow/plugins/mojo/list/list_length/list_length.mojo diff --git a/workflow/plugins/mojo/list/list_length/package.json b/workflow/plugins/mojo/list/list_length/package.json new file mode 100644 index 000000000..11edfb61e --- /dev/null +++ b/workflow/plugins/mojo/list/list_length/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/list_length", + "version": "1.0.0", + "description": "Get the number of items in a list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin"], + "main": "list_length.mojo", + "metadata": { + "plugin_type": "list.length", + "category": "list" + } +} diff --git a/workflow/plugins/mojo/list/list_reverse.mojo b/workflow/plugins/mojo/list/list_reverse/list_reverse.mojo similarity index 100% rename from workflow/plugins/mojo/list/list_reverse.mojo rename to workflow/plugins/mojo/list/list_reverse/list_reverse.mojo diff --git a/workflow/plugins/mojo/list/list_reverse/package.json b/workflow/plugins/mojo/list/list_reverse/package.json new file mode 100644 index 000000000..857aab109 --- /dev/null +++ b/workflow/plugins/mojo/list/list_reverse/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/list_reverse", + "version": "1.0.0", + "description": "Reverse the order of items in a list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin"], + "main": "list_reverse.mojo", + "metadata": { + "plugin_type": "list.reverse", + "category": "list" + } +} diff --git a/workflow/plugins/mojo/list/package.json b/workflow/plugins/mojo/list/package.json index 9bb038fd6..8ec5073f4 100644 --- a/workflow/plugins/mojo/list/package.json +++ b/workflow/plugins/mojo/list/package.json @@ -1,67 +1,17 @@ { - "name": "list", + "name": "@metabuilder/workflow-plugins-list", "version": "1.0.0", - "description": "List operation plugins for workflow processing", + "description": "List operation plugins", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugins"], "metadata": { - "plugin_type": "list", - "language": "mojo", - "category": "list" + "category": "list", + "plugin_count": 3 }, "plugins": [ - { - "name": "list_concat", - "file": "list_concat.mojo", - "type": "list.concat", - "description": "Concatenate multiple lists into one", - "inputs": { - "lists": { - "type": "array", - "items": "array", - "description": "List of lists to concatenate" - } - }, - "outputs": { - "result": { - "type": "array", - "description": "Concatenated list" - } - } - }, - { - "name": "list_length", - "file": "list_length.mojo", - "type": "list.length", - "description": "Get the number of items in a list", - "inputs": { - "list": { - "type": "array", - "description": "List to measure" - } - }, - "outputs": { - "result": { - "type": "integer", - "description": "Number of items in the list" - } - } - }, - { - "name": "list_reverse", - "file": "list_reverse.mojo", - "type": "list.reverse", - "description": "Reverse the order of items in a list", - "inputs": { - "list": { - "type": "array", - "description": "List to reverse" - } - }, - "outputs": { - "result": { - "type": "array", - "description": "Reversed list" - } - } - } + "list_concat", + "list_length", + "list_reverse" ] } diff --git a/workflow/plugins/mojo/math/math_add.mojo b/workflow/plugins/mojo/math/math_add/math_add.mojo similarity index 100% rename from workflow/plugins/mojo/math/math_add.mojo rename to workflow/plugins/mojo/math/math_add/math_add.mojo diff --git a/workflow/plugins/mojo/math/math_add/package.json b/workflow/plugins/mojo/math/math_add/package.json new file mode 100644 index 000000000..4e2b26ab5 --- /dev/null +++ b/workflow/plugins/mojo/math/math_add/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/math_add", + "version": "1.0.0", + "description": "Add two or more numbers together", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin"], + "main": "math_add.mojo", + "metadata": { + "plugin_type": "math.add", + "category": "math" + } +} diff --git a/workflow/plugins/mojo/math/math_divide.mojo b/workflow/plugins/mojo/math/math_divide/math_divide.mojo similarity index 100% rename from workflow/plugins/mojo/math/math_divide.mojo rename to workflow/plugins/mojo/math/math_divide/math_divide.mojo diff --git a/workflow/plugins/mojo/math/math_divide/package.json b/workflow/plugins/mojo/math/math_divide/package.json new file mode 100644 index 000000000..8ff766361 --- /dev/null +++ b/workflow/plugins/mojo/math/math_divide/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/math_divide", + "version": "1.0.0", + "description": "Divide numbers sequentially from the first number", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin"], + "main": "math_divide.mojo", + "metadata": { + "plugin_type": "math.divide", + "category": "math" + } +} diff --git a/workflow/plugins/mojo/math/math_multiply.mojo b/workflow/plugins/mojo/math/math_multiply/math_multiply.mojo similarity index 100% rename from workflow/plugins/mojo/math/math_multiply.mojo rename to workflow/plugins/mojo/math/math_multiply/math_multiply.mojo diff --git a/workflow/plugins/mojo/math/math_multiply/package.json b/workflow/plugins/mojo/math/math_multiply/package.json new file mode 100644 index 000000000..3ab54aa73 --- /dev/null +++ b/workflow/plugins/mojo/math/math_multiply/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/math_multiply", + "version": "1.0.0", + "description": "Multiply two or more numbers together", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin"], + "main": "math_multiply.mojo", + "metadata": { + "plugin_type": "math.multiply", + "category": "math" + } +} diff --git a/workflow/plugins/mojo/math/math_subtract.mojo b/workflow/plugins/mojo/math/math_subtract/math_subtract.mojo similarity index 100% rename from workflow/plugins/mojo/math/math_subtract.mojo rename to workflow/plugins/mojo/math/math_subtract/math_subtract.mojo diff --git a/workflow/plugins/mojo/math/math_subtract/package.json b/workflow/plugins/mojo/math/math_subtract/package.json new file mode 100644 index 000000000..4c9eadd5e --- /dev/null +++ b/workflow/plugins/mojo/math/math_subtract/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/math_subtract", + "version": "1.0.0", + "description": "Subtract numbers sequentially from the first number", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin"], + "main": "math_subtract.mojo", + "metadata": { + "plugin_type": "math.subtract", + "category": "math" + } +} diff --git a/workflow/plugins/mojo/math/package.json b/workflow/plugins/mojo/math/package.json index 0dbd624c6..57e731cdd 100644 --- a/workflow/plugins/mojo/math/package.json +++ b/workflow/plugins/mojo/math/package.json @@ -1,92 +1,18 @@ { - "name": "math", + "name": "@metabuilder/workflow-plugins-math", "version": "1.0.0", - "description": "Mathematical operation plugins for workflow processing", + "description": "Mathematical operation plugins", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugins"], "metadata": { - "plugin_type": "math", - "language": "mojo", - "category": "math" + "category": "math", + "plugin_count": 4 }, "plugins": [ - { - "name": "math_add", - "file": "math_add.mojo", - "type": "math.add", - "description": "Add two or more numbers together", - "inputs": { - "numbers": { - "type": "array", - "items": "number", - "description": "List of numbers to add" - } - }, - "outputs": { - "result": { - "type": "number", - "description": "Sum of all input numbers" - } - } - }, - { - "name": "math_subtract", - "file": "math_subtract.mojo", - "type": "math.subtract", - "description": "Subtract numbers sequentially from the first number", - "inputs": { - "numbers": { - "type": "array", - "items": "number", - "description": "List of numbers (first is minuend, rest are subtrahends)" - } - }, - "outputs": { - "result": { - "type": "number", - "description": "Result of sequential subtraction" - } - } - }, - { - "name": "math_multiply", - "file": "math_multiply.mojo", - "type": "math.multiply", - "description": "Multiply two or more numbers together", - "inputs": { - "numbers": { - "type": "array", - "items": "number", - "description": "List of numbers to multiply" - } - }, - "outputs": { - "result": { - "type": "number", - "description": "Product of all input numbers" - } - } - }, - { - "name": "math_divide", - "file": "math_divide.mojo", - "type": "math.divide", - "description": "Divide numbers sequentially from the first number", - "inputs": { - "numbers": { - "type": "array", - "items": "number", - "description": "List of numbers (first is dividend, rest are divisors)" - } - }, - "outputs": { - "result": { - "type": "number", - "description": "Result of sequential division" - }, - "error": { - "type": "string", - "description": "Error message if division by zero" - } - } - } + "math_add", + "math_divide", + "math_multiply", + "math_subtract" ] } diff --git a/workflow/plugins/mojo/string/package.json b/workflow/plugins/mojo/string/package.json index 9b874fa01..ab1f39caf 100644 --- a/workflow/plugins/mojo/string/package.json +++ b/workflow/plugins/mojo/string/package.json @@ -1,90 +1,18 @@ { - "name": "string", + "name": "@metabuilder/workflow-plugins-string", "version": "1.0.0", - "description": "String manipulation plugins for workflow processing", + "description": "String manipulation plugins", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugins"], "metadata": { - "plugin_type": "string", - "language": "mojo", - "category": "string" + "category": "string", + "plugin_count": 4 }, "plugins": [ - { - "name": "string_concat", - "file": "string_concat.mojo", - "type": "string.concat", - "description": "Concatenate multiple strings with optional separator", - "inputs": { - "strings": { - "type": "array", - "items": "string", - "description": "List of strings to concatenate" - }, - "separator": { - "type": "string", - "description": "Optional separator between strings", - "default": "" - } - }, - "outputs": { - "result": { - "type": "string", - "description": "Concatenated string" - } - } - }, - { - "name": "string_upper", - "file": "string_upper.mojo", - "type": "string.upper", - "description": "Convert a string to uppercase", - "inputs": { - "text": { - "type": "string", - "description": "String to convert to uppercase" - } - }, - "outputs": { - "result": { - "type": "string", - "description": "Uppercase string" - } - } - }, - { - "name": "string_lower", - "file": "string_lower.mojo", - "type": "string.lower", - "description": "Convert a string to lowercase", - "inputs": { - "text": { - "type": "string", - "description": "String to convert to lowercase" - } - }, - "outputs": { - "result": { - "type": "string", - "description": "Lowercase string" - } - } - }, - { - "name": "string_length", - "file": "string_length.mojo", - "type": "string.length", - "description": "Get the length of a string", - "inputs": { - "text": { - "type": "string", - "description": "String to measure" - } - }, - "outputs": { - "result": { - "type": "integer", - "description": "Length of the string" - } - } - } + "string_concat", + "string_length", + "string_lower", + "string_upper" ] } diff --git a/workflow/plugins/mojo/string/string_concat/package.json b/workflow/plugins/mojo/string/string_concat/package.json new file mode 100644 index 000000000..ed97295e3 --- /dev/null +++ b/workflow/plugins/mojo/string/string_concat/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_concat", + "version": "1.0.0", + "description": "Concatenate multiple strings with optional separator", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_concat.mojo", + "metadata": { + "plugin_type": "string.concat", + "category": "string" + } +} diff --git a/workflow/plugins/mojo/string/string_concat.mojo b/workflow/plugins/mojo/string/string_concat/string_concat.mojo similarity index 100% rename from workflow/plugins/mojo/string/string_concat.mojo rename to workflow/plugins/mojo/string/string_concat/string_concat.mojo diff --git a/workflow/plugins/mojo/string/string_length/package.json b/workflow/plugins/mojo/string/string_length/package.json new file mode 100644 index 000000000..5065ea54b --- /dev/null +++ b/workflow/plugins/mojo/string/string_length/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_length", + "version": "1.0.0", + "description": "Get the length of a string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_length.mojo", + "metadata": { + "plugin_type": "string.length", + "category": "string" + } +} diff --git a/workflow/plugins/mojo/string/string_length.mojo b/workflow/plugins/mojo/string/string_length/string_length.mojo similarity index 100% rename from workflow/plugins/mojo/string/string_length.mojo rename to workflow/plugins/mojo/string/string_length/string_length.mojo diff --git a/workflow/plugins/mojo/string/string_lower/package.json b/workflow/plugins/mojo/string/string_lower/package.json new file mode 100644 index 000000000..96e52de7b --- /dev/null +++ b/workflow/plugins/mojo/string/string_lower/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_lower", + "version": "1.0.0", + "description": "Convert a string to lowercase", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_lower.mojo", + "metadata": { + "plugin_type": "string.lower", + "category": "string" + } +} diff --git a/workflow/plugins/mojo/string/string_lower.mojo b/workflow/plugins/mojo/string/string_lower/string_lower.mojo similarity index 100% rename from workflow/plugins/mojo/string/string_lower.mojo rename to workflow/plugins/mojo/string/string_lower/string_lower.mojo diff --git a/workflow/plugins/mojo/string/string_upper/package.json b/workflow/plugins/mojo/string/string_upper/package.json new file mode 100644 index 000000000..26b67403a --- /dev/null +++ b/workflow/plugins/mojo/string/string_upper/package.json @@ -0,0 +1,13 @@ +{ + "name": "@metabuilder/string_upper", + "version": "1.0.0", + "description": "Convert a string to uppercase", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin"], + "main": "string_upper.mojo", + "metadata": { + "plugin_type": "string.upper", + "category": "string" + } +} diff --git a/workflow/plugins/mojo/string/string_upper.mojo b/workflow/plugins/mojo/string/string_upper/string_upper.mojo similarity index 100% rename from workflow/plugins/mojo/string/string_upper.mojo rename to workflow/plugins/mojo/string/string_upper/string_upper.mojo diff --git a/workflow/plugins/rust/Cargo.toml b/workflow/plugins/rust/Cargo.toml index b427234b9..b85291c10 100644 --- a/workflow/plugins/rust/Cargo.toml +++ b/workflow/plugins/rust/Cargo.toml @@ -1,17 +1,75 @@ -[package] -name = "metabuilder-workflow-plugins" +[workspace] +resolver = "2" +members = [ + # Math plugins + "math/math_add", + "math/math_subtract", + "math/math_multiply", + "math/math_divide", + "math/math_modulo", + "math/math_power", + "math/math_abs", + "math/math_round", + "math/math_floor", + "math/math_ceil", + # String plugins + "string/string_concat", + "string/string_split", + "string/string_replace", + "string/string_upper", + "string/string_lower", + "string/string_trim", + "string/string_length", + "string/string_contains", + "string/string_starts_with", + "string/string_ends_with", + "string/string_substring", + # Logic plugins + "logic/logic_and", + "logic/logic_or", + "logic/logic_not", + "logic/logic_xor", + "logic/logic_equals", + "logic/logic_gt", + "logic/logic_gte", + "logic/logic_lt", + "logic/logic_lte", + "logic/logic_in", + # List plugins + "list/list_concat", + "list/list_length", + "list/list_slice", + "list/list_reverse", + "list/list_first", + "list/list_last", + "list/list_at", + "list/list_contains", + "list/list_index_of", + "list/list_unique", + "list/list_sort", + # Convert plugins + "convert/convert_to_string", + "convert/convert_to_number", + "convert/convert_to_boolean", + "convert/convert_to_json", + "convert/convert_parse_json", + "convert/convert_to_list", + "convert/convert_to_object", + # Var plugins + "var/var_get", + "var/var_set", + "var/var_delete", + "var/var_exists", + "var/var_keys", + "var/var_clear", +] + +[workspace.package] version = "0.1.0" edition = "2021" -description = "Rust workflow plugins for MetaBuilder" +license = "MIT" +authors = ["MetaBuilder"] -[lib] -name = "workflow_plugins" -crate-type = ["cdylib", "rlib"] - -[dependencies] +[workspace.dependencies] serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -thiserror = "1.0" - -[dev-dependencies] -tokio = { version = "1.0", features = ["full"] } diff --git a/workflow/plugins/rust/convert/convert_parse_json/Cargo.toml b/workflow/plugins/rust/convert/convert_parse_json/Cargo.toml new file mode 100644 index 000000000..30f589839 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_parse_json/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "convert_parse_json" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Parse JSON string to value" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/convert/convert_parse_json/package.json b/workflow/plugins/rust/convert/convert_parse_json/package.json new file mode 100644 index 000000000..f6f2d2415 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_parse_json/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/convert_parse_json", + "version": "0.1.0", + "description": "Parse JSON string to value", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "convert.parse_json", + "category": "convert", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/convert/convert_parse_json/src/lib.rs b/workflow/plugins/rust/convert/convert_parse_json/src/lib.rs new file mode 100644 index 000000000..a5d2e281a --- /dev/null +++ b/workflow/plugins/rust/convert/convert_parse_json/src/lib.rs @@ -0,0 +1,41 @@ +//! Workflow plugin: parse JSON string. + +use serde_json::Value; +use std::collections::HashMap; + +/// Parse JSON string to value. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let string: String = inputs + .get("string") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + + match serde_json::from_str::(&string) { + Ok(value) => { + output.insert("result".to_string(), value); + } + Err(e) => { + output.insert("result".to_string(), Value::Null); + output.insert("error".to_string(), serde_json::json!(e.to_string())); + } + } + + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_json() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("string".to_string(), serde_json::json!("{\"a\":1}")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!({"a": 1}))); + } +} diff --git a/workflow/plugins/rust/convert/convert_to_boolean/Cargo.toml b/workflow/plugins/rust/convert/convert_to_boolean/Cargo.toml new file mode 100644 index 000000000..7dc92836b --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_boolean/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "convert_to_boolean" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Convert value to boolean" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/convert/convert_to_boolean/package.json b/workflow/plugins/rust/convert/convert_to_boolean/package.json new file mode 100644 index 000000000..3942fad7b --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_boolean/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/convert_to_boolean", + "version": "0.1.0", + "description": "Convert value to boolean", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "convert.to_boolean", + "category": "convert", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/convert/convert_to_boolean/src/lib.rs b/workflow/plugins/rust/convert/convert_to_boolean/src/lib.rs new file mode 100644 index 000000000..ea80a9e35 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_boolean/src/lib.rs @@ -0,0 +1,40 @@ +//! Workflow plugin: convert to boolean. + +use serde_json::Value; +use std::collections::HashMap; + +/// Convert value to boolean. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value = inputs.get("value").unwrap_or(&Value::Null); + + let result = match value { + Value::Bool(b) => *b, + Value::Number(n) => n.as_f64().map(|f| f != 0.0).unwrap_or(false), + Value::String(s) => { + let lower = s.to_lowercase(); + lower == "true" || lower == "1" || lower == "yes" + } + Value::Null => false, + Value::Array(a) => !a.is_empty(), + Value::Object(o) => !o.is_empty(), + }; + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_boolean() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!("true")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/convert/convert_to_json/Cargo.toml b/workflow/plugins/rust/convert/convert_to_json/Cargo.toml new file mode 100644 index 000000000..3ca1fe42f --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_json/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "convert_to_json" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Convert value to JSON string" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/convert/convert_to_json/package.json b/workflow/plugins/rust/convert/convert_to_json/package.json new file mode 100644 index 000000000..5e197f867 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_json/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/convert_to_json", + "version": "0.1.0", + "description": "Convert value to JSON string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "convert.to_json", + "category": "convert", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/convert/convert_to_json/src/lib.rs b/workflow/plugins/rust/convert/convert_to_json/src/lib.rs new file mode 100644 index 000000000..6292267d4 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_json/src/lib.rs @@ -0,0 +1,38 @@ +//! Workflow plugin: convert to JSON string. + +use serde_json::Value; +use std::collections::HashMap; + +/// Convert value to JSON string. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value = inputs.get("value").unwrap_or(&Value::Null); + let pretty: bool = inputs + .get("pretty") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(false); + + let result = if pretty { + serde_json::to_string_pretty(value).unwrap_or_default() + } else { + serde_json::to_string(value).unwrap_or_default() + }; + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_json() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!({"a": 1})); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!("{\"a\":1}"))); + } +} diff --git a/workflow/plugins/rust/convert/convert_to_list/Cargo.toml b/workflow/plugins/rust/convert/convert_to_list/Cargo.toml new file mode 100644 index 000000000..4d5c8bc85 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_list/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "convert_to_list" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Convert value to list" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/convert/convert_to_list/package.json b/workflow/plugins/rust/convert/convert_to_list/package.json new file mode 100644 index 000000000..5b5139539 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_list/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/convert_to_list", + "version": "0.1.0", + "description": "Convert value to list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "convert.to_list", + "category": "convert", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/convert/convert_to_list/src/lib.rs b/workflow/plugins/rust/convert/convert_to_list/src/lib.rs new file mode 100644 index 000000000..406548650 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_list/src/lib.rs @@ -0,0 +1,35 @@ +//! Workflow plugin: convert to list. + +use serde_json::Value; +use std::collections::HashMap; + +/// Convert value to list. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value = inputs.get("value").unwrap_or(&Value::Null); + + let result = match value { + Value::Array(a) => a.clone(), + Value::String(s) => s.chars().map(|c| Value::String(c.to_string())).collect(), + Value::Null => vec![], + _ => vec![value.clone()], + }; + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_list() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!("abc")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(["a", "b", "c"]))); + } +} diff --git a/workflow/plugins/rust/convert/convert_to_number/Cargo.toml b/workflow/plugins/rust/convert/convert_to_number/Cargo.toml new file mode 100644 index 000000000..9e7e76037 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_number/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "convert_to_number" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Convert value to number" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/convert/convert_to_number/package.json b/workflow/plugins/rust/convert/convert_to_number/package.json new file mode 100644 index 000000000..33eb1c0a5 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_number/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/convert_to_number", + "version": "0.1.0", + "description": "Convert value to number", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "convert.to_number", + "category": "convert", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/convert/convert_to_number/src/lib.rs b/workflow/plugins/rust/convert/convert_to_number/src/lib.rs new file mode 100644 index 000000000..cda9b17b5 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_number/src/lib.rs @@ -0,0 +1,35 @@ +//! Workflow plugin: convert to number. + +use serde_json::Value; +use std::collections::HashMap; + +/// Convert value to number. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value = inputs.get("value").unwrap_or(&Value::Null); + + let result = match value { + Value::Number(n) => n.as_f64().unwrap_or(0.0), + Value::String(s) => s.parse::().unwrap_or(0.0), + Value::Bool(b) => if *b { 1.0 } else { 0.0 }, + _ => 0.0, + }; + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_number() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!("42.5")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(42.5))); + } +} diff --git a/workflow/plugins/rust/convert/convert_to_object/Cargo.toml b/workflow/plugins/rust/convert/convert_to_object/Cargo.toml new file mode 100644 index 000000000..b6fa15e69 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_object/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "convert_to_object" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Convert value to object/dict" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/convert/convert_to_object/package.json b/workflow/plugins/rust/convert/convert_to_object/package.json new file mode 100644 index 000000000..36e9bc1f6 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_object/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/convert_to_object", + "version": "0.1.0", + "description": "Convert value to object/dict", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "convert.to_object", + "category": "convert", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/convert/convert_to_object/src/lib.rs b/workflow/plugins/rust/convert/convert_to_object/src/lib.rs new file mode 100644 index 000000000..b25c35133 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_object/src/lib.rs @@ -0,0 +1,47 @@ +//! Workflow plugin: convert to object. + +use serde_json::Value; +use std::collections::HashMap; + +/// Convert value to object/dict. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value = inputs.get("value").unwrap_or(&Value::Null); + + let result = match value { + Value::Object(o) => Value::Object(o.clone()), + Value::Array(a) => { + // Convert array of [key, value] pairs to object + let mut obj = serde_json::Map::new(); + for item in a { + if let Value::Array(pair) = item { + if pair.len() >= 2 { + if let Value::String(key) = &pair[0] { + obj.insert(key.clone(), pair[1].clone()); + } + } + } + } + Value::Object(obj) + } + _ => Value::Object(serde_json::Map::new()), + }; + + let mut output = HashMap::new(); + output.insert("result".to_string(), result); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_object() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!([["a", 1], ["b", 2]])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!({"a": 1, "b": 2}))); + } +} diff --git a/workflow/plugins/rust/convert/convert_to_string/Cargo.toml b/workflow/plugins/rust/convert/convert_to_string/Cargo.toml new file mode 100644 index 000000000..e89c5458a --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_string/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "convert_to_string" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Convert value to string" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/convert/convert_to_string/package.json b/workflow/plugins/rust/convert/convert_to_string/package.json new file mode 100644 index 000000000..ea5b29829 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_string/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/convert_to_string", + "version": "0.1.0", + "description": "Convert value to string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "convert.to_string", + "category": "convert", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/convert/convert_to_string/src/lib.rs b/workflow/plugins/rust/convert/convert_to_string/src/lib.rs new file mode 100644 index 000000000..2d2171e70 --- /dev/null +++ b/workflow/plugins/rust/convert/convert_to_string/src/lib.rs @@ -0,0 +1,34 @@ +//! Workflow plugin: convert to string. + +use serde_json::Value; +use std::collections::HashMap; + +/// Convert value to string. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value = inputs.get("value").unwrap_or(&Value::Null); + + let result = match value { + Value::String(s) => s.clone(), + Value::Null => String::new(), + _ => serde_json::to_string(value).unwrap_or_default(), + }; + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_string() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!(42)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!("42"))); + } +} diff --git a/workflow/plugins/rust/convert/package.json b/workflow/plugins/rust/convert/package.json new file mode 100644 index 000000000..f75fdd5ab --- /dev/null +++ b/workflow/plugins/rust/convert/package.json @@ -0,0 +1,22 @@ +{ + "name": "@metabuilder/workflow-plugins-convert-rust", + "version": "0.1.0", + "description": "Type conversion plugins (Rust)", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["convert", "type", "workflow", "plugins", "rust"], + "metadata": { + "category": "convert", + "runtime": "rust", + "plugin_count": 7 + }, + "plugins": [ + "convert_to_string", + "convert_to_number", + "convert_to_boolean", + "convert_to_json", + "convert_parse_json", + "convert_to_list", + "convert_to_object" + ] +} diff --git a/workflow/plugins/rust/list/list_at/Cargo.toml b/workflow/plugins/rust/list/list_at/Cargo.toml new file mode 100644 index 000000000..24dbac626 --- /dev/null +++ b/workflow/plugins/rust/list/list_at/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "list_at" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Get element at index" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/list/list_at/package.json b/workflow/plugins/rust/list/list_at/package.json new file mode 100644 index 000000000..93400d1e6 --- /dev/null +++ b/workflow/plugins/rust/list/list_at/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/list_at", + "version": "0.1.0", + "description": "Get element at index", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "list.at", + "category": "list", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/list/list_at/src/lib.rs b/workflow/plugins/rust/list/list_at/src/lib.rs new file mode 100644 index 000000000..9c5621974 --- /dev/null +++ b/workflow/plugins/rust/list/list_at/src/lib.rs @@ -0,0 +1,45 @@ +//! Workflow plugin: get element at index. + +use serde_json::Value; +use std::collections::HashMap; + +/// Get element at index. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let list: Vec = inputs + .get("list") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let index: i64 = inputs + .get("index") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0); + + let len = list.len() as i64; + let idx = if index < 0 { len + index } else { index }; + + let result = if idx >= 0 && (idx as usize) < list.len() { + list[idx as usize].clone() + } else { + Value::Null + }; + + let mut output = HashMap::new(); + output.insert("result".to_string(), result); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_at() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("list".to_string(), serde_json::json!([1, 2, 3])); + inputs.insert("index".to_string(), serde_json::json!(1)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(2))); + } +} diff --git a/workflow/plugins/rust/list/list_concat/Cargo.toml b/workflow/plugins/rust/list/list_concat/Cargo.toml new file mode 100644 index 000000000..933907bfa --- /dev/null +++ b/workflow/plugins/rust/list/list_concat/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "list_concat" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Concatenate multiple lists" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/list/list_concat/package.json b/workflow/plugins/rust/list/list_concat/package.json new file mode 100644 index 000000000..8fb4e0bbf --- /dev/null +++ b/workflow/plugins/rust/list/list_concat/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/list_concat", + "version": "0.1.0", + "description": "Concatenate multiple lists", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "list.concat", + "category": "list", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/list/list_concat/src/lib.rs b/workflow/plugins/rust/list/list_concat/src/lib.rs new file mode 100644 index 000000000..6150ebb1b --- /dev/null +++ b/workflow/plugins/rust/list/list_concat/src/lib.rs @@ -0,0 +1,33 @@ +//! Workflow plugin: concatenate lists. + +use serde_json::Value; +use std::collections::HashMap; + +/// Concatenate multiple lists. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let lists: Vec> = inputs + .get("lists") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let result: Vec = lists.into_iter().flatten().collect(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_concat() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("lists".to_string(), serde_json::json!([[1, 2], [3, 4]])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!([1, 2, 3, 4]))); + } +} diff --git a/workflow/plugins/rust/list/list_contains/Cargo.toml b/workflow/plugins/rust/list/list_contains/Cargo.toml new file mode 100644 index 000000000..ee9806a84 --- /dev/null +++ b/workflow/plugins/rust/list/list_contains/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "list_contains" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Check if list contains value" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/list/list_contains/package.json b/workflow/plugins/rust/list/list_contains/package.json new file mode 100644 index 000000000..77b765f76 --- /dev/null +++ b/workflow/plugins/rust/list/list_contains/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/list_contains", + "version": "0.1.0", + "description": "Check if list contains value", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "list.contains", + "category": "list", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/list/list_contains/src/lib.rs b/workflow/plugins/rust/list/list_contains/src/lib.rs new file mode 100644 index 000000000..15002bee4 --- /dev/null +++ b/workflow/plugins/rust/list/list_contains/src/lib.rs @@ -0,0 +1,33 @@ +//! Workflow plugin: check if list contains value. + +use serde_json::Value; +use std::collections::HashMap; + +/// Check if list contains value. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let list: Vec = inputs + .get("list") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let value = inputs.get("value").unwrap_or(&Value::Null); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(list.contains(value))); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_contains() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("list".to_string(), serde_json::json!([1, 2, 3])); + inputs.insert("value".to_string(), serde_json::json!(2)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/list/list_first/Cargo.toml b/workflow/plugins/rust/list/list_first/Cargo.toml new file mode 100644 index 000000000..8feebdb8e --- /dev/null +++ b/workflow/plugins/rust/list/list_first/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "list_first" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Get first element of list" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/list/list_first/package.json b/workflow/plugins/rust/list/list_first/package.json new file mode 100644 index 000000000..0db48a824 --- /dev/null +++ b/workflow/plugins/rust/list/list_first/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/list_first", + "version": "0.1.0", + "description": "Get first element of list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "list.first", + "category": "list", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/list/list_first/src/lib.rs b/workflow/plugins/rust/list/list_first/src/lib.rs new file mode 100644 index 000000000..cbe371fb5 --- /dev/null +++ b/workflow/plugins/rust/list/list_first/src/lib.rs @@ -0,0 +1,33 @@ +//! Workflow plugin: get first element. + +use serde_json::Value; +use std::collections::HashMap; + +/// Get first element of list. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let list: Vec = inputs + .get("list") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let result = list.first().cloned().unwrap_or(Value::Null); + + let mut output = HashMap::new(); + output.insert("result".to_string(), result); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_first() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("list".to_string(), serde_json::json!([1, 2, 3])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(1))); + } +} diff --git a/workflow/plugins/rust/list/list_index_of/Cargo.toml b/workflow/plugins/rust/list/list_index_of/Cargo.toml new file mode 100644 index 000000000..8918cfd99 --- /dev/null +++ b/workflow/plugins/rust/list/list_index_of/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "list_index_of" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Find index of value in list" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/list/list_index_of/package.json b/workflow/plugins/rust/list/list_index_of/package.json new file mode 100644 index 000000000..eacf5c865 --- /dev/null +++ b/workflow/plugins/rust/list/list_index_of/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/list_index_of", + "version": "0.1.0", + "description": "Find index of value in list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "list.index_of", + "category": "list", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/list/list_index_of/src/lib.rs b/workflow/plugins/rust/list/list_index_of/src/lib.rs new file mode 100644 index 000000000..3b4fec0f1 --- /dev/null +++ b/workflow/plugins/rust/list/list_index_of/src/lib.rs @@ -0,0 +1,35 @@ +//! Workflow plugin: find index of value in list. + +use serde_json::Value; +use std::collections::HashMap; + +/// Find index of value in list. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let list: Vec = inputs + .get("list") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let value = inputs.get("value").unwrap_or(&Value::Null); + + let result = list.iter().position(|v| v == value).map(|i| i as i64).unwrap_or(-1); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_index_of() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("list".to_string(), serde_json::json!([1, 2, 3])); + inputs.insert("value".to_string(), serde_json::json!(2)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(1))); + } +} diff --git a/workflow/plugins/rust/list/list_last/Cargo.toml b/workflow/plugins/rust/list/list_last/Cargo.toml new file mode 100644 index 000000000..62d93723a --- /dev/null +++ b/workflow/plugins/rust/list/list_last/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "list_last" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Get last element of list" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/list/list_last/package.json b/workflow/plugins/rust/list/list_last/package.json new file mode 100644 index 000000000..27f1bc6c1 --- /dev/null +++ b/workflow/plugins/rust/list/list_last/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/list_last", + "version": "0.1.0", + "description": "Get last element of list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "list.last", + "category": "list", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/list/list_last/src/lib.rs b/workflow/plugins/rust/list/list_last/src/lib.rs new file mode 100644 index 000000000..283fc0878 --- /dev/null +++ b/workflow/plugins/rust/list/list_last/src/lib.rs @@ -0,0 +1,33 @@ +//! Workflow plugin: get last element. + +use serde_json::Value; +use std::collections::HashMap; + +/// Get last element of list. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let list: Vec = inputs + .get("list") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let result = list.last().cloned().unwrap_or(Value::Null); + + let mut output = HashMap::new(); + output.insert("result".to_string(), result); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_last() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("list".to_string(), serde_json::json!([1, 2, 3])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(3))); + } +} diff --git a/workflow/plugins/rust/list/list_length/Cargo.toml b/workflow/plugins/rust/list/list_length/Cargo.toml new file mode 100644 index 000000000..899f498e1 --- /dev/null +++ b/workflow/plugins/rust/list/list_length/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "list_length" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Get list length" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/list/list_length/package.json b/workflow/plugins/rust/list/list_length/package.json new file mode 100644 index 000000000..c6342fea7 --- /dev/null +++ b/workflow/plugins/rust/list/list_length/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/list_length", + "version": "0.1.0", + "description": "Get list length", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "list.length", + "category": "list", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/list/list_length/src/lib.rs b/workflow/plugins/rust/list/list_length/src/lib.rs new file mode 100644 index 000000000..e7d03cc38 --- /dev/null +++ b/workflow/plugins/rust/list/list_length/src/lib.rs @@ -0,0 +1,31 @@ +//! Workflow plugin: list length. + +use serde_json::Value; +use std::collections::HashMap; + +/// Get list length. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let list: Vec = inputs + .get("list") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(list.len())); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_length() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("list".to_string(), serde_json::json!([1, 2, 3, 4, 5])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(5))); + } +} diff --git a/workflow/plugins/rust/list/list_reverse/Cargo.toml b/workflow/plugins/rust/list/list_reverse/Cargo.toml new file mode 100644 index 000000000..1e95e2082 --- /dev/null +++ b/workflow/plugins/rust/list/list_reverse/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "list_reverse" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Reverse a list" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/list/list_reverse/package.json b/workflow/plugins/rust/list/list_reverse/package.json new file mode 100644 index 000000000..1d4de6e83 --- /dev/null +++ b/workflow/plugins/rust/list/list_reverse/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/list_reverse", + "version": "0.1.0", + "description": "Reverse a list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "list.reverse", + "category": "list", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/list/list_reverse/src/lib.rs b/workflow/plugins/rust/list/list_reverse/src/lib.rs new file mode 100644 index 000000000..9b23f75ef --- /dev/null +++ b/workflow/plugins/rust/list/list_reverse/src/lib.rs @@ -0,0 +1,33 @@ +//! Workflow plugin: reverse a list. + +use serde_json::Value; +use std::collections::HashMap; + +/// Reverse a list. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let mut list: Vec = inputs + .get("list") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + list.reverse(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(list)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_reverse() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("list".to_string(), serde_json::json!([1, 2, 3])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!([3, 2, 1]))); + } +} diff --git a/workflow/plugins/rust/list/list_slice/Cargo.toml b/workflow/plugins/rust/list/list_slice/Cargo.toml new file mode 100644 index 000000000..aa502de0f --- /dev/null +++ b/workflow/plugins/rust/list/list_slice/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "list_slice" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Slice a list" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/list/list_slice/package.json b/workflow/plugins/rust/list/list_slice/package.json new file mode 100644 index 000000000..08e6b870a --- /dev/null +++ b/workflow/plugins/rust/list/list_slice/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/list_slice", + "version": "0.1.0", + "description": "Slice a list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "list.slice", + "category": "list", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/list/list_slice/src/lib.rs b/workflow/plugins/rust/list/list_slice/src/lib.rs new file mode 100644 index 000000000..b9820f1ce --- /dev/null +++ b/workflow/plugins/rust/list/list_slice/src/lib.rs @@ -0,0 +1,56 @@ +//! Workflow plugin: slice a list. + +use serde_json::Value; +use std::collections::HashMap; + +/// Slice a list. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let list: Vec = inputs + .get("list") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let start: i64 = inputs + .get("start") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0); + let end: Option = inputs + .get("end") + .and_then(|v| serde_json::from_value(v.clone()).ok()); + + let len = list.len() as i64; + + // Handle negative indices + let start_idx = if start < 0 { (len + start).max(0) } else { start.min(len) } as usize; + let end_idx = match end { + Some(e) if e < 0 => (len + e).max(0) as usize, + Some(e) => e.min(len) as usize, + None => len as usize, + }; + + let result: Vec = if start_idx < end_idx { + list[start_idx..end_idx].to_vec() + } else { + vec![] + }; + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_slice() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("list".to_string(), serde_json::json!([1, 2, 3, 4, 5])); + inputs.insert("start".to_string(), serde_json::json!(1)); + inputs.insert("end".to_string(), serde_json::json!(4)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!([2, 3, 4]))); + } +} diff --git a/workflow/plugins/rust/list/list_sort/Cargo.toml b/workflow/plugins/rust/list/list_sort/Cargo.toml new file mode 100644 index 000000000..fac8a7f1d --- /dev/null +++ b/workflow/plugins/rust/list/list_sort/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "list_sort" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Sort a list" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/list/list_sort/package.json b/workflow/plugins/rust/list/list_sort/package.json new file mode 100644 index 000000000..14c508996 --- /dev/null +++ b/workflow/plugins/rust/list/list_sort/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/list_sort", + "version": "0.1.0", + "description": "Sort a list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "list.sort", + "category": "list", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/list/list_sort/src/lib.rs b/workflow/plugins/rust/list/list_sort/src/lib.rs new file mode 100644 index 000000000..ecbd94d40 --- /dev/null +++ b/workflow/plugins/rust/list/list_sort/src/lib.rs @@ -0,0 +1,52 @@ +//! Workflow plugin: sort a list. + +use serde_json::Value; +use std::collections::HashMap; + +/// Sort a list. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let mut list: Vec = inputs + .get("list") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + list.sort_by(|a, b| { + match (a, b) { + // Numbers + (Value::Number(n1), Value::Number(n2)) => { + let f1 = n1.as_f64().unwrap_or(0.0); + let f2 = n2.as_f64().unwrap_or(0.0); + f1.partial_cmp(&f2).unwrap_or(std::cmp::Ordering::Equal) + } + // Strings + (Value::String(s1), Value::String(s2)) => s1.cmp(s2), + // Booleans (false < true) + (Value::Bool(b1), Value::Bool(b2)) => b1.cmp(b2), + // Null is smallest + (Value::Null, Value::Null) => std::cmp::Ordering::Equal, + (Value::Null, _) => std::cmp::Ordering::Less, + (_, Value::Null) => std::cmp::Ordering::Greater, + // Mixed types: compare by type name as fallback + _ => std::cmp::Ordering::Equal, + } + }); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(list)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sort() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("list".to_string(), serde_json::json!([3, 1, 2])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!([1, 2, 3]))); + } +} diff --git a/workflow/plugins/rust/list/list_unique/Cargo.toml b/workflow/plugins/rust/list/list_unique/Cargo.toml new file mode 100644 index 000000000..c0a1da8f7 --- /dev/null +++ b/workflow/plugins/rust/list/list_unique/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "list_unique" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Remove duplicates from list" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/list/list_unique/package.json b/workflow/plugins/rust/list/list_unique/package.json new file mode 100644 index 000000000..1442d1775 --- /dev/null +++ b/workflow/plugins/rust/list/list_unique/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/list_unique", + "version": "0.1.0", + "description": "Remove duplicates from list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "list.unique", + "category": "list", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/list/list_unique/src/lib.rs b/workflow/plugins/rust/list/list_unique/src/lib.rs new file mode 100644 index 000000000..1c5e86002 --- /dev/null +++ b/workflow/plugins/rust/list/list_unique/src/lib.rs @@ -0,0 +1,38 @@ +//! Workflow plugin: remove duplicates from list. + +use serde_json::Value; +use std::collections::HashMap; + +/// Remove duplicates from list. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let list: Vec = inputs + .get("list") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut seen = Vec::new(); + for item in list { + if !seen.contains(&item) { + seen.push(item); + } + } + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(seen)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_unique() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("list".to_string(), serde_json::json!([1, 2, 2, 3, 3, 3])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!([1, 2, 3]))); + } +} diff --git a/workflow/plugins/rust/list/package.json b/workflow/plugins/rust/list/package.json new file mode 100644 index 000000000..48d3039e8 --- /dev/null +++ b/workflow/plugins/rust/list/package.json @@ -0,0 +1,26 @@ +{ + "name": "@metabuilder/workflow-plugins-list-rust", + "version": "0.1.0", + "description": "List/array operation plugins (Rust)", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["list", "array", "workflow", "plugins", "rust"], + "metadata": { + "category": "list", + "runtime": "rust", + "plugin_count": 11 + }, + "plugins": [ + "list_concat", + "list_length", + "list_slice", + "list_reverse", + "list_first", + "list_last", + "list_at", + "list_contains", + "list_index_of", + "list_unique", + "list_sort" + ] +} diff --git a/workflow/plugins/rust/logic/logic_and/Cargo.toml b/workflow/plugins/rust/logic/logic_and/Cargo.toml new file mode 100644 index 000000000..70eeca156 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_and/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "logic_and" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Logical AND on boolean values" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/logic/logic_and/package.json b/workflow/plugins/rust/logic/logic_and/package.json new file mode 100644 index 000000000..be761f793 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_and/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/logic_and", + "version": "0.1.0", + "description": "Logical AND on boolean values", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "logic.and", + "category": "logic", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/logic/logic_and/src/lib.rs b/workflow/plugins/rust/logic/logic_and/src/lib.rs new file mode 100644 index 000000000..6a748186e --- /dev/null +++ b/workflow/plugins/rust/logic/logic_and/src/lib.rs @@ -0,0 +1,45 @@ +//! Workflow plugin: logical AND. + +use serde_json::Value; +use std::collections::HashMap; + +/// Helper to convert Value to bool. +fn to_bool(v: &Value) -> bool { + match v { + Value::Bool(b) => *b, + Value::Number(n) => n.as_f64().map(|f| f != 0.0).unwrap_or(false), + Value::String(s) => !s.is_empty(), + Value::Null => false, + Value::Array(a) => !a.is_empty(), + Value::Object(o) => !o.is_empty(), + } +} + +/// Logical AND on boolean values. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let values: Vec = inputs + .get("values") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let result = values.iter().all(to_bool); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_and() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("values".to_string(), serde_json::json!([true, true, true])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/logic/logic_equals/Cargo.toml b/workflow/plugins/rust/logic/logic_equals/Cargo.toml new file mode 100644 index 000000000..c3ef0d1db --- /dev/null +++ b/workflow/plugins/rust/logic/logic_equals/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "logic_equals" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Check if two values are equal" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/logic/logic_equals/package.json b/workflow/plugins/rust/logic/logic_equals/package.json new file mode 100644 index 000000000..dc283ce80 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_equals/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/logic_equals", + "version": "0.1.0", + "description": "Check if two values are equal", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "logic.equals", + "category": "logic", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/logic/logic_equals/src/lib.rs b/workflow/plugins/rust/logic/logic_equals/src/lib.rs new file mode 100644 index 000000000..f284c562f --- /dev/null +++ b/workflow/plugins/rust/logic/logic_equals/src/lib.rs @@ -0,0 +1,30 @@ +//! Workflow plugin: equals comparison. + +use serde_json::Value; +use std::collections::HashMap; + +/// Check if two values are equal. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let a = inputs.get("a").unwrap_or(&Value::Null); + let b = inputs.get("b").unwrap_or(&Value::Null); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(a == b)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_equals() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("a".to_string(), serde_json::json!(5)); + inputs.insert("b".to_string(), serde_json::json!(5)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/logic/logic_gt/Cargo.toml b/workflow/plugins/rust/logic/logic_gt/Cargo.toml new file mode 100644 index 000000000..fba687f76 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_gt/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "logic_gt" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Check if a > b" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/logic/logic_gt/package.json b/workflow/plugins/rust/logic/logic_gt/package.json new file mode 100644 index 000000000..5aada1569 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_gt/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/logic_gt", + "version": "0.1.0", + "description": "Check if a > b", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "logic.gt", + "category": "logic", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/logic/logic_gt/src/lib.rs b/workflow/plugins/rust/logic/logic_gt/src/lib.rs new file mode 100644 index 000000000..854d5f39c --- /dev/null +++ b/workflow/plugins/rust/logic/logic_gt/src/lib.rs @@ -0,0 +1,36 @@ +//! Workflow plugin: greater than comparison. + +use serde_json::Value; +use std::collections::HashMap; + +/// Check if a > b. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let a: f64 = inputs + .get("a") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + let b: f64 = inputs + .get("b") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(a > b)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_gt() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("a".to_string(), serde_json::json!(10.0)); + inputs.insert("b".to_string(), serde_json::json!(5.0)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/logic/logic_gte/Cargo.toml b/workflow/plugins/rust/logic/logic_gte/Cargo.toml new file mode 100644 index 000000000..6cdc35bef --- /dev/null +++ b/workflow/plugins/rust/logic/logic_gte/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "logic_gte" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Check if a >= b" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/logic/logic_gte/package.json b/workflow/plugins/rust/logic/logic_gte/package.json new file mode 100644 index 000000000..2cbb1550e --- /dev/null +++ b/workflow/plugins/rust/logic/logic_gte/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/logic_gte", + "version": "0.1.0", + "description": "Check if a >= b", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "logic.gte", + "category": "logic", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/logic/logic_gte/src/lib.rs b/workflow/plugins/rust/logic/logic_gte/src/lib.rs new file mode 100644 index 000000000..27be50f9b --- /dev/null +++ b/workflow/plugins/rust/logic/logic_gte/src/lib.rs @@ -0,0 +1,36 @@ +//! Workflow plugin: greater than or equal comparison. + +use serde_json::Value; +use std::collections::HashMap; + +/// Check if a >= b. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let a: f64 = inputs + .get("a") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + let b: f64 = inputs + .get("b") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(a >= b)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_gte() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("a".to_string(), serde_json::json!(10.0)); + inputs.insert("b".to_string(), serde_json::json!(10.0)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/logic/logic_in/Cargo.toml b/workflow/plugins/rust/logic/logic_in/Cargo.toml new file mode 100644 index 000000000..07057c5d8 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_in/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "logic_in" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Check if value is in list" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/logic/logic_in/package.json b/workflow/plugins/rust/logic/logic_in/package.json new file mode 100644 index 000000000..290af434d --- /dev/null +++ b/workflow/plugins/rust/logic/logic_in/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/logic_in", + "version": "0.1.0", + "description": "Check if value is in list", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "logic.in", + "category": "logic", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/logic/logic_in/src/lib.rs b/workflow/plugins/rust/logic/logic_in/src/lib.rs new file mode 100644 index 000000000..6049a2116 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_in/src/lib.rs @@ -0,0 +1,33 @@ +//! Workflow plugin: value in list check. + +use serde_json::Value; +use std::collections::HashMap; + +/// Check if value is in list. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value = inputs.get("value").unwrap_or(&Value::Null); + let list: Vec = inputs + .get("list") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(list.contains(value))); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_in() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!(2)); + inputs.insert("list".to_string(), serde_json::json!([1, 2, 3])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/logic/logic_lt/Cargo.toml b/workflow/plugins/rust/logic/logic_lt/Cargo.toml new file mode 100644 index 000000000..3cbdd5373 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_lt/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "logic_lt" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Check if a < b" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/logic/logic_lt/package.json b/workflow/plugins/rust/logic/logic_lt/package.json new file mode 100644 index 000000000..72905b4f5 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_lt/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/logic_lt", + "version": "0.1.0", + "description": "Check if a < b", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "logic.lt", + "category": "logic", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/logic/logic_lt/src/lib.rs b/workflow/plugins/rust/logic/logic_lt/src/lib.rs new file mode 100644 index 000000000..dfc758cf4 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_lt/src/lib.rs @@ -0,0 +1,36 @@ +//! Workflow plugin: less than comparison. + +use serde_json::Value; +use std::collections::HashMap; + +/// Check if a < b. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let a: f64 = inputs + .get("a") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + let b: f64 = inputs + .get("b") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(a < b)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_lt() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("a".to_string(), serde_json::json!(5.0)); + inputs.insert("b".to_string(), serde_json::json!(10.0)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/logic/logic_lte/Cargo.toml b/workflow/plugins/rust/logic/logic_lte/Cargo.toml new file mode 100644 index 000000000..d3130a14b --- /dev/null +++ b/workflow/plugins/rust/logic/logic_lte/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "logic_lte" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Check if a <= b" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/logic/logic_lte/package.json b/workflow/plugins/rust/logic/logic_lte/package.json new file mode 100644 index 000000000..55df203ec --- /dev/null +++ b/workflow/plugins/rust/logic/logic_lte/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/logic_lte", + "version": "0.1.0", + "description": "Check if a <= b", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "logic.lte", + "category": "logic", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/logic/logic_lte/src/lib.rs b/workflow/plugins/rust/logic/logic_lte/src/lib.rs new file mode 100644 index 000000000..6bdf084b0 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_lte/src/lib.rs @@ -0,0 +1,36 @@ +//! Workflow plugin: less than or equal comparison. + +use serde_json::Value; +use std::collections::HashMap; + +/// Check if a <= b. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let a: f64 = inputs + .get("a") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + let b: f64 = inputs + .get("b") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(a <= b)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_lte() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("a".to_string(), serde_json::json!(10.0)); + inputs.insert("b".to_string(), serde_json::json!(10.0)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/logic/logic_not/Cargo.toml b/workflow/plugins/rust/logic/logic_not/Cargo.toml new file mode 100644 index 000000000..7c31b7489 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_not/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "logic_not" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Logical NOT on a boolean value" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/logic/logic_not/package.json b/workflow/plugins/rust/logic/logic_not/package.json new file mode 100644 index 000000000..392f5a3b8 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_not/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/logic_not", + "version": "0.1.0", + "description": "Logical NOT on a boolean value", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "logic.not", + "category": "logic", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/logic/logic_not/src/lib.rs b/workflow/plugins/rust/logic/logic_not/src/lib.rs new file mode 100644 index 000000000..d4a999b30 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_not/src/lib.rs @@ -0,0 +1,40 @@ +//! Workflow plugin: logical NOT. + +use serde_json::Value; +use std::collections::HashMap; + +/// Helper to convert Value to bool. +fn to_bool(v: &Value) -> bool { + match v { + Value::Bool(b) => *b, + Value::Number(n) => n.as_f64().map(|f| f != 0.0).unwrap_or(false), + Value::String(s) => !s.is_empty(), + Value::Null => false, + Value::Array(a) => !a.is_empty(), + Value::Object(o) => !o.is_empty(), + } +} + +/// Logical NOT on a boolean value. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value = inputs.get("value").unwrap_or(&Value::Null); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(!to_bool(value))); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_not() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!(true)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(false))); + } +} diff --git a/workflow/plugins/rust/logic/logic_or/Cargo.toml b/workflow/plugins/rust/logic/logic_or/Cargo.toml new file mode 100644 index 000000000..7e80d9d16 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_or/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "logic_or" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Logical OR on boolean values" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/logic/logic_or/package.json b/workflow/plugins/rust/logic/logic_or/package.json new file mode 100644 index 000000000..f1e076350 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_or/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/logic_or", + "version": "0.1.0", + "description": "Logical OR on boolean values", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "logic.or", + "category": "logic", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/logic/logic_or/src/lib.rs b/workflow/plugins/rust/logic/logic_or/src/lib.rs new file mode 100644 index 000000000..4a44de592 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_or/src/lib.rs @@ -0,0 +1,45 @@ +//! Workflow plugin: logical OR. + +use serde_json::Value; +use std::collections::HashMap; + +/// Helper to convert Value to bool. +fn to_bool(v: &Value) -> bool { + match v { + Value::Bool(b) => *b, + Value::Number(n) => n.as_f64().map(|f| f != 0.0).unwrap_or(false), + Value::String(s) => !s.is_empty(), + Value::Null => false, + Value::Array(a) => !a.is_empty(), + Value::Object(o) => !o.is_empty(), + } +} + +/// Logical OR on boolean values. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let values: Vec = inputs + .get("values") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let result = values.iter().any(to_bool); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_or() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("values".to_string(), serde_json::json!([false, true, false])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/logic/logic_xor/Cargo.toml b/workflow/plugins/rust/logic/logic_xor/Cargo.toml new file mode 100644 index 000000000..3292e437a --- /dev/null +++ b/workflow/plugins/rust/logic/logic_xor/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "logic_xor" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Logical XOR on boolean values" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/logic/logic_xor/package.json b/workflow/plugins/rust/logic/logic_xor/package.json new file mode 100644 index 000000000..bb8256bcb --- /dev/null +++ b/workflow/plugins/rust/logic/logic_xor/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/logic_xor", + "version": "0.1.0", + "description": "Logical XOR on boolean values", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "logic.xor", + "category": "logic", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/logic/logic_xor/src/lib.rs b/workflow/plugins/rust/logic/logic_xor/src/lib.rs new file mode 100644 index 000000000..409598f74 --- /dev/null +++ b/workflow/plugins/rust/logic/logic_xor/src/lib.rs @@ -0,0 +1,45 @@ +//! Workflow plugin: logical XOR. + +use serde_json::Value; +use std::collections::HashMap; + +/// Helper to convert Value to bool. +fn to_bool(v: &Value) -> bool { + match v { + Value::Bool(b) => *b, + Value::Number(n) => n.as_f64().map(|f| f != 0.0).unwrap_or(false), + Value::String(s) => !s.is_empty(), + Value::Null => false, + Value::Array(a) => !a.is_empty(), + Value::Object(o) => !o.is_empty(), + } +} + +/// Logical XOR on boolean values (exactly one true). +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let values: Vec = inputs + .get("values") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let true_count = values.iter().filter(|v| to_bool(v)).count(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(true_count == 1)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_xor() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("values".to_string(), serde_json::json!([false, true, false])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/logic/package.json b/workflow/plugins/rust/logic/package.json new file mode 100644 index 000000000..3cbfedee7 --- /dev/null +++ b/workflow/plugins/rust/logic/package.json @@ -0,0 +1,25 @@ +{ + "name": "@metabuilder/workflow-plugins-logic-rust", + "version": "0.1.0", + "description": "Boolean logic operation plugins (Rust)", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["logic", "workflow", "plugins", "rust"], + "metadata": { + "category": "logic", + "runtime": "rust", + "plugin_count": 10 + }, + "plugins": [ + "logic_and", + "logic_or", + "logic_not", + "logic_xor", + "logic_equals", + "logic_gt", + "logic_gte", + "logic_lt", + "logic_lte", + "logic_in" + ] +} diff --git a/workflow/plugins/rust/math/math_abs/Cargo.toml b/workflow/plugins/rust/math/math_abs/Cargo.toml new file mode 100644 index 000000000..88814e393 --- /dev/null +++ b/workflow/plugins/rust/math/math_abs/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "math_abs" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Calculate absolute value" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/math/math_abs/package.json b/workflow/plugins/rust/math/math_abs/package.json new file mode 100644 index 000000000..371e76050 --- /dev/null +++ b/workflow/plugins/rust/math/math_abs/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/math_abs", + "version": "0.1.0", + "description": "Calculate absolute value", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "math.abs", + "category": "math", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/math/math_abs/src/lib.rs b/workflow/plugins/rust/math/math_abs/src/lib.rs new file mode 100644 index 000000000..820251b55 --- /dev/null +++ b/workflow/plugins/rust/math/math_abs/src/lib.rs @@ -0,0 +1,31 @@ +//! Workflow plugin: absolute value. + +use serde_json::Value; +use std::collections::HashMap; + +/// Calculate absolute value of a number. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value: f64 = inputs + .get("value") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(value.abs())); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_abs() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!(-5.0)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(5.0))); + } +} diff --git a/workflow/plugins/rust/math/math_add/Cargo.toml b/workflow/plugins/rust/math/math_add/Cargo.toml new file mode 100644 index 000000000..c0e285f2c --- /dev/null +++ b/workflow/plugins/rust/math/math_add/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "math_add" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Add two or more numbers" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/math/math_add/package.json b/workflow/plugins/rust/math/math_add/package.json new file mode 100644 index 000000000..a8c851787 --- /dev/null +++ b/workflow/plugins/rust/math/math_add/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/math_add", + "version": "0.1.0", + "description": "Add two or more numbers", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "math.add", + "category": "math", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/math/math_add/src/lib.rs b/workflow/plugins/rust/math/math_add/src/lib.rs new file mode 100644 index 000000000..a1790ecc5 --- /dev/null +++ b/workflow/plugins/rust/math/math_add/src/lib.rs @@ -0,0 +1,33 @@ +//! Workflow plugin: add numbers. + +use serde_json::Value; +use std::collections::HashMap; + +/// Add two or more numbers. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let numbers: Vec = inputs + .get("numbers") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let sum: f64 = numbers.iter().sum(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(sum)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_add() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("numbers".to_string(), serde_json::json!([1.0, 2.0, 3.0])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(6.0))); + } +} diff --git a/workflow/plugins/rust/math/math_ceil/Cargo.toml b/workflow/plugins/rust/math/math_ceil/Cargo.toml new file mode 100644 index 000000000..34e1989a5 --- /dev/null +++ b/workflow/plugins/rust/math/math_ceil/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "math_ceil" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Ceil a number (round up)" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/math/math_ceil/package.json b/workflow/plugins/rust/math/math_ceil/package.json new file mode 100644 index 000000000..93232f37f --- /dev/null +++ b/workflow/plugins/rust/math/math_ceil/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/math_ceil", + "version": "0.1.0", + "description": "Ceil a number (round up)", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "math.ceil", + "category": "math", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/math/math_ceil/src/lib.rs b/workflow/plugins/rust/math/math_ceil/src/lib.rs new file mode 100644 index 000000000..40cbe4595 --- /dev/null +++ b/workflow/plugins/rust/math/math_ceil/src/lib.rs @@ -0,0 +1,31 @@ +//! Workflow plugin: ceil a number. + +use serde_json::Value; +use std::collections::HashMap; + +/// Ceil a number (round up). +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value: f64 = inputs + .get("value") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(value.ceil())); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_ceil() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!(3.2)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(4.0))); + } +} diff --git a/workflow/plugins/rust/math/math_divide/Cargo.toml b/workflow/plugins/rust/math/math_divide/Cargo.toml new file mode 100644 index 000000000..ae8e28554 --- /dev/null +++ b/workflow/plugins/rust/math/math_divide/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "math_divide" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Divide the first number by subsequent numbers" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/math/math_divide/package.json b/workflow/plugins/rust/math/math_divide/package.json new file mode 100644 index 000000000..91752a6ba --- /dev/null +++ b/workflow/plugins/rust/math/math_divide/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/math_divide", + "version": "0.1.0", + "description": "Divide the first number by subsequent numbers", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "math.divide", + "category": "math", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/math/math_divide/src/lib.rs b/workflow/plugins/rust/math/math_divide/src/lib.rs new file mode 100644 index 000000000..bb2b90e0e --- /dev/null +++ b/workflow/plugins/rust/math/math_divide/src/lib.rs @@ -0,0 +1,47 @@ +//! Workflow plugin: divide numbers. + +use serde_json::Value; +use std::collections::HashMap; + +/// Divide the first number by subsequent numbers. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let numbers: Vec = inputs + .get("numbers") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + + if numbers.len() < 2 { + output.insert("result".to_string(), serde_json::json!(0)); + output.insert("error".to_string(), serde_json::json!("need at least 2 numbers")); + return Ok(output); + } + + for &n in &numbers[1..] { + if n == 0.0 { + output.insert("result".to_string(), serde_json::json!(0)); + output.insert("error".to_string(), serde_json::json!("division by zero")); + return Ok(output); + } + } + + let result = numbers.iter().skip(1).fold(numbers[0], |acc, x| acc / x); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_divide() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("numbers".to_string(), serde_json::json!([24.0, 3.0, 2.0])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(4.0))); + } +} diff --git a/workflow/plugins/rust/math/math_floor/Cargo.toml b/workflow/plugins/rust/math/math_floor/Cargo.toml new file mode 100644 index 000000000..6ea8bce1b --- /dev/null +++ b/workflow/plugins/rust/math/math_floor/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "math_floor" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Floor a number (round down)" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/math/math_floor/package.json b/workflow/plugins/rust/math/math_floor/package.json new file mode 100644 index 000000000..db8d05eaa --- /dev/null +++ b/workflow/plugins/rust/math/math_floor/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/math_floor", + "version": "0.1.0", + "description": "Floor a number (round down)", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "math.floor", + "category": "math", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/math/math_floor/src/lib.rs b/workflow/plugins/rust/math/math_floor/src/lib.rs new file mode 100644 index 000000000..bcdee6726 --- /dev/null +++ b/workflow/plugins/rust/math/math_floor/src/lib.rs @@ -0,0 +1,31 @@ +//! Workflow plugin: floor a number. + +use serde_json::Value; +use std::collections::HashMap; + +/// Floor a number (round down). +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value: f64 = inputs + .get("value") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(value.floor())); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_floor() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!(3.7)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(3.0))); + } +} diff --git a/workflow/plugins/rust/math/math_modulo/Cargo.toml b/workflow/plugins/rust/math/math_modulo/Cargo.toml new file mode 100644 index 000000000..0f753b016 --- /dev/null +++ b/workflow/plugins/rust/math/math_modulo/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "math_modulo" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Calculate modulo of two numbers" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/math/math_modulo/package.json b/workflow/plugins/rust/math/math_modulo/package.json new file mode 100644 index 000000000..eb4170013 --- /dev/null +++ b/workflow/plugins/rust/math/math_modulo/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/math_modulo", + "version": "0.1.0", + "description": "Calculate modulo of two numbers", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "math.modulo", + "category": "math", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/math/math_modulo/src/lib.rs b/workflow/plugins/rust/math/math_modulo/src/lib.rs new file mode 100644 index 000000000..c19c6e61a --- /dev/null +++ b/workflow/plugins/rust/math/math_modulo/src/lib.rs @@ -0,0 +1,43 @@ +//! Workflow plugin: modulo operation. + +use serde_json::Value; +use std::collections::HashMap; + +/// Calculate modulo of two numbers. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let a: f64 = inputs + .get("a") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + let b: f64 = inputs + .get("b") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(1.0); + + let mut output = HashMap::new(); + + if b == 0.0 { + output.insert("result".to_string(), serde_json::json!(0)); + output.insert("error".to_string(), serde_json::json!("division by zero")); + return Ok(output); + } + + output.insert("result".to_string(), serde_json::json!(a % b)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_modulo() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("a".to_string(), serde_json::json!(10.0)); + inputs.insert("b".to_string(), serde_json::json!(3.0)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(1.0))); + } +} diff --git a/workflow/plugins/rust/math/math_multiply/Cargo.toml b/workflow/plugins/rust/math/math_multiply/Cargo.toml new file mode 100644 index 000000000..b0e84ee26 --- /dev/null +++ b/workflow/plugins/rust/math/math_multiply/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "math_multiply" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Multiply two or more numbers" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/math/math_multiply/package.json b/workflow/plugins/rust/math/math_multiply/package.json new file mode 100644 index 000000000..3e4fefa98 --- /dev/null +++ b/workflow/plugins/rust/math/math_multiply/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/math_multiply", + "version": "0.1.0", + "description": "Multiply two or more numbers", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "math.multiply", + "category": "math", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/math/math_multiply/src/lib.rs b/workflow/plugins/rust/math/math_multiply/src/lib.rs new file mode 100644 index 000000000..fa42e150b --- /dev/null +++ b/workflow/plugins/rust/math/math_multiply/src/lib.rs @@ -0,0 +1,38 @@ +//! Workflow plugin: multiply numbers. + +use serde_json::Value; +use std::collections::HashMap; + +/// Multiply two or more numbers. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let numbers: Vec = inputs + .get("numbers") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + + if numbers.is_empty() { + output.insert("result".to_string(), serde_json::json!(0)); + return Ok(output); + } + + let result: f64 = numbers.iter().product(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_multiply() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("numbers".to_string(), serde_json::json!([2.0, 3.0, 4.0])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(24.0))); + } +} diff --git a/workflow/plugins/rust/math/math_power/Cargo.toml b/workflow/plugins/rust/math/math_power/Cargo.toml new file mode 100644 index 000000000..b0b887fe8 --- /dev/null +++ b/workflow/plugins/rust/math/math_power/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "math_power" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Calculate power of a number" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/math/math_power/package.json b/workflow/plugins/rust/math/math_power/package.json new file mode 100644 index 000000000..f8ea878f6 --- /dev/null +++ b/workflow/plugins/rust/math/math_power/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/math_power", + "version": "0.1.0", + "description": "Calculate power of a number", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "math.power", + "category": "math", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/math/math_power/src/lib.rs b/workflow/plugins/rust/math/math_power/src/lib.rs new file mode 100644 index 000000000..6e5909c29 --- /dev/null +++ b/workflow/plugins/rust/math/math_power/src/lib.rs @@ -0,0 +1,36 @@ +//! Workflow plugin: power operation. + +use serde_json::Value; +use std::collections::HashMap; + +/// Calculate power of a number. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let base: f64 = inputs + .get("base") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + let exp: f64 = inputs + .get("exponent") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(1.0); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(base.powf(exp))); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_power() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("base".to_string(), serde_json::json!(2.0)); + inputs.insert("exponent".to_string(), serde_json::json!(3.0)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(8.0))); + } +} diff --git a/workflow/plugins/rust/math/math_round/Cargo.toml b/workflow/plugins/rust/math/math_round/Cargo.toml new file mode 100644 index 000000000..e63024686 --- /dev/null +++ b/workflow/plugins/rust/math/math_round/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "math_round" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Round a number to specified decimals" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/math/math_round/package.json b/workflow/plugins/rust/math/math_round/package.json new file mode 100644 index 000000000..ca4a3ea12 --- /dev/null +++ b/workflow/plugins/rust/math/math_round/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/math_round", + "version": "0.1.0", + "description": "Round a number to specified decimals", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "math.round", + "category": "math", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/math/math_round/src/lib.rs b/workflow/plugins/rust/math/math_round/src/lib.rs new file mode 100644 index 000000000..6300cfee0 --- /dev/null +++ b/workflow/plugins/rust/math/math_round/src/lib.rs @@ -0,0 +1,39 @@ +//! Workflow plugin: round a number. + +use serde_json::Value; +use std::collections::HashMap; + +/// Round a number to specified decimal places. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let value: f64 = inputs + .get("value") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0.0); + let decimals: i32 = inputs + .get("decimals") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0); + + let factor = 10_f64.powi(decimals); + let result = (value * factor).round() / factor; + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_round() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("value".to_string(), serde_json::json!(3.14159)); + inputs.insert("decimals".to_string(), serde_json::json!(2)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(3.14))); + } +} diff --git a/workflow/plugins/rust/math/math_subtract/Cargo.toml b/workflow/plugins/rust/math/math_subtract/Cargo.toml new file mode 100644 index 000000000..b5698023a --- /dev/null +++ b/workflow/plugins/rust/math/math_subtract/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "math_subtract" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Subtract numbers from the first number" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/math/math_subtract/package.json b/workflow/plugins/rust/math/math_subtract/package.json new file mode 100644 index 000000000..9b3bff174 --- /dev/null +++ b/workflow/plugins/rust/math/math_subtract/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/math_subtract", + "version": "0.1.0", + "description": "Subtract numbers from the first number", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "math.subtract", + "category": "math", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/math/math_subtract/src/lib.rs b/workflow/plugins/rust/math/math_subtract/src/lib.rs new file mode 100644 index 000000000..98a7e9dd5 --- /dev/null +++ b/workflow/plugins/rust/math/math_subtract/src/lib.rs @@ -0,0 +1,39 @@ +//! Workflow plugin: subtract numbers. + +use serde_json::Value; +use std::collections::HashMap; + +/// Subtract numbers from the first number. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let numbers: Vec = inputs + .get("numbers") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + + if numbers.is_empty() { + output.insert("result".to_string(), serde_json::json!(0)); + output.insert("error".to_string(), serde_json::json!("numbers must be non-empty")); + return Ok(output); + } + + let result = numbers.iter().skip(1).fold(numbers[0], |acc, x| acc - x); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_subtract() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("numbers".to_string(), serde_json::json!([10.0, 3.0, 2.0])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(5.0))); + } +} diff --git a/workflow/plugins/rust/math/package.json b/workflow/plugins/rust/math/package.json new file mode 100644 index 000000000..7f4fd7528 --- /dev/null +++ b/workflow/plugins/rust/math/package.json @@ -0,0 +1,25 @@ +{ + "name": "@metabuilder/workflow-plugins-math-rust", + "version": "0.1.0", + "description": "Mathematical operation plugins (Rust)", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["math", "workflow", "plugins", "rust"], + "metadata": { + "category": "math", + "runtime": "rust", + "plugin_count": 10 + }, + "plugins": [ + "math_add", + "math_subtract", + "math_multiply", + "math_divide", + "math_modulo", + "math_power", + "math_abs", + "math_round", + "math_floor", + "math_ceil" + ] +} diff --git a/workflow/plugins/rust/src/lib.rs b/workflow/plugins/rust/plugin.rs similarity index 70% rename from workflow/plugins/rust/src/lib.rs rename to workflow/plugins/rust/plugin.rs index fe9635c89..37245b1ea 100644 --- a/workflow/plugins/rust/src/lib.rs +++ b/workflow/plugins/rust/plugin.rs @@ -1,20 +1,10 @@ -//! MetaBuilder Workflow Plugins for Rust +//! MetaBuilder Workflow Plugin Base Types //! -//! Rust plugins follow the same pattern as Python: -//! - Each module contains one operation -//! - All plugins implement the `run` function -//! - Input/output are `serde_json::Value` +//! Shared types for all Rust workflow plugins. use serde_json::Value; use std::collections::HashMap; -pub mod convert; -pub mod list; -pub mod logic; -pub mod math; -pub mod string; -pub mod var; - /// Runtime context for plugin execution. pub struct Runtime { /// Workflow state storage @@ -42,16 +32,25 @@ impl Default for Runtime { pub type PluginResult = Result, PluginError>; /// Error type for plugin operations -#[derive(Debug, thiserror::Error)] +#[derive(Debug)] pub enum PluginError { - #[error("Missing required input: {0}")] MissingInput(String), - #[error("Invalid input type: {0}")] InvalidType(String), - #[error("Operation failed: {0}")] OperationFailed(String), } +impl std::fmt::Display for PluginError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PluginError::MissingInput(s) => write!(f, "Missing required input: {}", s), + PluginError::InvalidType(s) => write!(f, "Invalid input type: {}", s), + PluginError::OperationFailed(s) => write!(f, "Operation failed: {}", s), + } + } +} + +impl std::error::Error for PluginError {} + /// Trait for workflow plugins pub trait Plugin { fn run(&self, runtime: &mut Runtime, inputs: &HashMap) -> PluginResult; @@ -65,7 +64,7 @@ pub fn get_input( inputs.get(key).and_then(|v| serde_json::from_value(v.clone()).ok()) } -/// Helper to create output map +/// Helper macro to create output map #[macro_export] macro_rules! output { ($($key:expr => $value:expr),* $(,)?) => {{ diff --git a/workflow/plugins/rust/src/convert.rs b/workflow/plugins/rust/src/convert.rs deleted file mode 100644 index 78f7a1be9..000000000 --- a/workflow/plugins/rust/src/convert.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! Type conversion workflow plugins - -use crate::{get_input, output, PluginResult, Runtime}; -use serde_json::Value; -use std::collections::HashMap; - -/// Convert value to string. -pub fn to_string(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value = inputs.get("value").unwrap_or(&Value::Null); - - let result = match value { - Value::String(s) => s.clone(), - Value::Null => String::new(), - _ => serde_json::to_string(value).unwrap_or_default(), - }; - - Ok(output!("result" => result)) -} - -/// Convert value to number. -pub fn to_number(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value = inputs.get("value").unwrap_or(&Value::Null); - - let result = match value { - Value::Number(n) => n.as_f64().unwrap_or(0.0), - Value::String(s) => s.parse::().unwrap_or(0.0), - Value::Bool(b) => if *b { 1.0 } else { 0.0 }, - _ => 0.0, - }; - - Ok(output!("result" => result)) -} - -/// Convert value to boolean. -pub fn to_boolean(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value = inputs.get("value").unwrap_or(&Value::Null); - - let result = match value { - Value::Bool(b) => *b, - Value::Number(n) => n.as_f64().map(|f| f != 0.0).unwrap_or(false), - Value::String(s) => { - let lower = s.to_lowercase(); - lower == "true" || lower == "1" || lower == "yes" - } - Value::Null => false, - Value::Array(a) => !a.is_empty(), - Value::Object(o) => !o.is_empty(), - }; - - Ok(output!("result" => result)) -} - -/// Convert value to JSON string. -pub fn to_json(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value = inputs.get("value").unwrap_or(&Value::Null); - let pretty: bool = get_input(inputs, "pretty").unwrap_or(false); - - let result = if pretty { - serde_json::to_string_pretty(value).unwrap_or_default() - } else { - serde_json::to_string(value).unwrap_or_default() - }; - - Ok(output!("result" => result)) -} - -/// Parse JSON string to value. -pub fn parse_json(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let string: String = get_input(inputs, "string").unwrap_or_default(); - - match serde_json::from_str::(&string) { - Ok(value) => Ok(output!("result" => value)), - Err(e) => Ok(output!("result" => Value::Null, "error" => e.to_string())), - } -} - -/// Convert value to list. -pub fn to_list(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value = inputs.get("value").unwrap_or(&Value::Null); - - let result = match value { - Value::Array(a) => a.clone(), - Value::String(s) => s.chars().map(|c| Value::String(c.to_string())).collect(), - Value::Null => vec![], - _ => vec![value.clone()], - }; - - Ok(output!("result" => result)) -} - -/// Convert value to object/dict. -pub fn to_object(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value = inputs.get("value").unwrap_or(&Value::Null); - - let result = match value { - Value::Object(o) => Value::Object(o.clone()), - Value::Array(a) => { - // Convert array of [key, value] pairs to object - let mut obj = serde_json::Map::new(); - for item in a { - if let Value::Array(pair) = item { - if pair.len() >= 2 { - if let Value::String(key) = &pair[0] { - obj.insert(key.clone(), pair[1].clone()); - } - } - } - } - Value::Object(obj) - } - _ => Value::Object(serde_json::Map::new()), - }; - - Ok(output!("result" => result)) -} diff --git a/workflow/plugins/rust/src/list.rs b/workflow/plugins/rust/src/list.rs deleted file mode 100644 index 249306b31..000000000 --- a/workflow/plugins/rust/src/list.rs +++ /dev/null @@ -1,141 +0,0 @@ -//! List manipulation workflow plugins - -use crate::{get_input, output, PluginResult, Runtime}; -use serde_json::Value; -use std::collections::HashMap; - -/// Concatenate multiple lists. -pub fn concat(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let lists: Vec> = get_input(inputs, "lists").unwrap_or_default(); - - let result: Vec = lists.into_iter().flatten().collect(); - Ok(output!("result" => result)) -} - -/// Get list length. -pub fn length(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let list: Vec = get_input(inputs, "list").unwrap_or_default(); - Ok(output!("result" => list.len())) -} - -/// Slice a list. -pub fn slice(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let list: Vec = get_input(inputs, "list").unwrap_or_default(); - let start: i64 = get_input(inputs, "start").unwrap_or(0); - let end: Option = get_input(inputs, "end"); - - let len = list.len() as i64; - - // Handle negative indices - let start_idx = if start < 0 { (len + start).max(0) } else { start.min(len) } as usize; - let end_idx = match end { - Some(e) if e < 0 => (len + e).max(0) as usize, - Some(e) => e.min(len) as usize, - None => len as usize, - }; - - let result: Vec = if start_idx < end_idx { - list[start_idx..end_idx].to_vec() - } else { - vec![] - }; - - Ok(output!("result" => result)) -} - -/// Reverse a list. -pub fn reverse(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let mut list: Vec = get_input(inputs, "list").unwrap_or_default(); - list.reverse(); - Ok(output!("result" => list)) -} - -/// Get first element of list. -pub fn first(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let list: Vec = get_input(inputs, "list").unwrap_or_default(); - let result = list.first().cloned().unwrap_or(Value::Null); - Ok(output!("result" => result)) -} - -/// Get last element of list. -pub fn last(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let list: Vec = get_input(inputs, "list").unwrap_or_default(); - let result = list.last().cloned().unwrap_or(Value::Null); - Ok(output!("result" => result)) -} - -/// Get element at index. -pub fn at(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let list: Vec = get_input(inputs, "list").unwrap_or_default(); - let index: i64 = get_input(inputs, "index").unwrap_or(0); - - let len = list.len() as i64; - let idx = if index < 0 { len + index } else { index }; - - let result = if idx >= 0 && (idx as usize) < list.len() { - list[idx as usize].clone() - } else { - Value::Null - }; - - Ok(output!("result" => result)) -} - -/// Check if list contains value. -pub fn contains(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let list: Vec = get_input(inputs, "list").unwrap_or_default(); - let value = inputs.get("value").unwrap_or(&Value::Null); - - Ok(output!("result" => list.contains(value))) -} - -/// Find index of value in list. -pub fn index_of(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let list: Vec = get_input(inputs, "list").unwrap_or_default(); - let value = inputs.get("value").unwrap_or(&Value::Null); - - let result = list.iter().position(|v| v == value).map(|i| i as i64).unwrap_or(-1); - Ok(output!("result" => result)) -} - -/// Remove duplicates from list. -pub fn unique(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let list: Vec = get_input(inputs, "list").unwrap_or_default(); - - let mut seen = Vec::new(); - for item in list { - if !seen.contains(&item) { - seen.push(item); - } - } - - Ok(output!("result" => seen)) -} - -/// Sort a list. -pub fn sort(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let mut list: Vec = get_input(inputs, "list").unwrap_or_default(); - - list.sort_by(|a, b| { - match (a, b) { - // Numbers - (Value::Number(n1), Value::Number(n2)) => { - let f1 = n1.as_f64().unwrap_or(0.0); - let f2 = n2.as_f64().unwrap_or(0.0); - f1.partial_cmp(&f2).unwrap_or(std::cmp::Ordering::Equal) - } - // Strings - (Value::String(s1), Value::String(s2)) => s1.cmp(s2), - // Booleans (false < true) - (Value::Bool(b1), Value::Bool(b2)) => b1.cmp(b2), - // Null is smallest - (Value::Null, Value::Null) => std::cmp::Ordering::Equal, - (Value::Null, _) => std::cmp::Ordering::Less, - (_, Value::Null) => std::cmp::Ordering::Greater, - // Mixed types: compare by type name as fallback - _ => std::cmp::Ordering::Equal, - } - }); - - Ok(output!("result" => list)) -} diff --git a/workflow/plugins/rust/src/logic.rs b/workflow/plugins/rust/src/logic.rs deleted file mode 100644 index ae2fd34bd..000000000 --- a/workflow/plugins/rust/src/logic.rs +++ /dev/null @@ -1,95 +0,0 @@ -//! Boolean logic workflow plugins - -use crate::{get_input, output, PluginResult, Runtime}; -use serde_json::Value; -use std::collections::HashMap; - -/// Helper to convert Value to bool -fn to_bool(v: &Value) -> bool { - match v { - Value::Bool(b) => *b, - Value::Number(n) => n.as_f64().map(|f| f != 0.0).unwrap_or(false), - Value::String(s) => !s.is_empty(), - Value::Null => false, - Value::Array(a) => !a.is_empty(), - Value::Object(o) => !o.is_empty(), - } -} - -/// Logical AND on boolean values. -pub fn and(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let values: Vec = get_input(inputs, "values").unwrap_or_default(); - - let result = values.iter().all(to_bool); - Ok(output!("result" => result)) -} - -/// Logical OR on boolean values. -pub fn or(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let values: Vec = get_input(inputs, "values").unwrap_or_default(); - - let result = values.iter().any(to_bool); - Ok(output!("result" => result)) -} - -/// Logical NOT on a boolean value. -pub fn not(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value = inputs.get("value").unwrap_or(&Value::Null); - Ok(output!("result" => !to_bool(value))) -} - -/// Logical XOR on boolean values. -pub fn xor(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let values: Vec = get_input(inputs, "values").unwrap_or_default(); - - let true_count = values.iter().filter(|v| to_bool(v)).count(); - Ok(output!("result" => true_count == 1)) -} - -/// Check if two values are equal. -pub fn equals(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let a = inputs.get("a").unwrap_or(&Value::Null); - let b = inputs.get("b").unwrap_or(&Value::Null); - - Ok(output!("result" => a == b)) -} - -/// Check if a > b. -pub fn greater_than(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let a: f64 = get_input(inputs, "a").unwrap_or(0.0); - let b: f64 = get_input(inputs, "b").unwrap_or(0.0); - - Ok(output!("result" => a > b)) -} - -/// Check if a >= b. -pub fn greater_than_or_equal(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let a: f64 = get_input(inputs, "a").unwrap_or(0.0); - let b: f64 = get_input(inputs, "b").unwrap_or(0.0); - - Ok(output!("result" => a >= b)) -} - -/// Check if a < b. -pub fn less_than(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let a: f64 = get_input(inputs, "a").unwrap_or(0.0); - let b: f64 = get_input(inputs, "b").unwrap_or(0.0); - - Ok(output!("result" => a < b)) -} - -/// Check if a <= b. -pub fn less_than_or_equal(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let a: f64 = get_input(inputs, "a").unwrap_or(0.0); - let b: f64 = get_input(inputs, "b").unwrap_or(0.0); - - Ok(output!("result" => a <= b)) -} - -/// Check if value is in list. -pub fn is_in(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value = inputs.get("value").unwrap_or(&Value::Null); - let list: Vec = get_input(inputs, "list").unwrap_or_default(); - - Ok(output!("result" => list.contains(value))) -} diff --git a/workflow/plugins/rust/src/math.rs b/workflow/plugins/rust/src/math.rs deleted file mode 100644 index 3789319a0..000000000 --- a/workflow/plugins/rust/src/math.rs +++ /dev/null @@ -1,100 +0,0 @@ -//! Mathematical workflow plugins - -use crate::{get_input, output, PluginResult, Runtime}; -use serde_json::Value; -use std::collections::HashMap; - -/// Add two or more numbers. -pub fn add(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let numbers: Vec = get_input(inputs, "numbers").unwrap_or_default(); - let sum: f64 = numbers.iter().sum(); - Ok(output!("result" => sum)) -} - -/// Subtract numbers from the first number. -pub fn subtract(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let numbers: Vec = get_input(inputs, "numbers").unwrap_or_default(); - if numbers.is_empty() { - return Ok(output!("result" => 0, "error" => "numbers must be non-empty")); - } - - let result = numbers.iter().skip(1).fold(numbers[0], |acc, x| acc - x); - Ok(output!("result" => result)) -} - -/// Multiply two or more numbers. -pub fn multiply(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let numbers: Vec = get_input(inputs, "numbers").unwrap_or_default(); - if numbers.is_empty() { - return Ok(output!("result" => 0)); - } - - let result: f64 = numbers.iter().product(); - Ok(output!("result" => result)) -} - -/// Divide the first number by subsequent numbers. -pub fn divide(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let numbers: Vec = get_input(inputs, "numbers").unwrap_or_default(); - if numbers.len() < 2 { - return Ok(output!("result" => 0, "error" => "need at least 2 numbers")); - } - - for &n in &numbers[1..] { - if n == 0.0 { - return Ok(output!("result" => 0, "error" => "division by zero")); - } - } - - let result = numbers.iter().skip(1).fold(numbers[0], |acc, x| acc / x); - Ok(output!("result" => result)) -} - -/// Calculate modulo. -pub fn modulo(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let a: f64 = get_input(inputs, "a").unwrap_or(0.0); - let b: f64 = get_input(inputs, "b").unwrap_or(1.0); - - if b == 0.0 { - return Ok(output!("result" => 0, "error" => "division by zero")); - } - - Ok(output!("result" => a % b)) -} - -/// Calculate power. -pub fn power(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let base: f64 = get_input(inputs, "base").unwrap_or(0.0); - let exp: f64 = get_input(inputs, "exponent").unwrap_or(1.0); - - Ok(output!("result" => base.powf(exp))) -} - -/// Calculate absolute value. -pub fn abs(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value: f64 = get_input(inputs, "value").unwrap_or(0.0); - Ok(output!("result" => value.abs())) -} - -/// Round a number. -pub fn round(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value: f64 = get_input(inputs, "value").unwrap_or(0.0); - let decimals: i32 = get_input(inputs, "decimals").unwrap_or(0); - - let factor = 10_f64.powi(decimals); - let result = (value * factor).round() / factor; - - Ok(output!("result" => result)) -} - -/// Floor a number (round down). -pub fn floor(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value: f64 = get_input(inputs, "value").unwrap_or(0.0); - Ok(output!("result" => value.floor())) -} - -/// Ceil a number (round up). -pub fn ceil(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let value: f64 = get_input(inputs, "value").unwrap_or(0.0); - Ok(output!("result" => value.ceil())) -} diff --git a/workflow/plugins/rust/src/string.rs b/workflow/plugins/rust/src/string.rs deleted file mode 100644 index b876526cb..000000000 --- a/workflow/plugins/rust/src/string.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! String manipulation workflow plugins - -use crate::{get_input, output, PluginResult, Runtime}; -use serde_json::Value; -use std::collections::HashMap; - -/// Concatenate multiple strings. -pub fn concat(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let strings: Vec = get_input(inputs, "strings").unwrap_or_default(); - let separator: String = get_input(inputs, "separator").unwrap_or_default(); - - let result = strings.join(&separator); - Ok(output!("result" => result)) -} - -/// Split a string by separator. -pub fn split(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let string: String = get_input(inputs, "string").unwrap_or_default(); - let separator: String = get_input(inputs, "separator").unwrap_or_default(); - - let result: Vec<&str> = if separator.is_empty() { - string.chars().map(|c| { - // Return character as string slice - need to collect differently - Box::leak(c.to_string().into_boxed_str()) as &str - }).collect() - } else { - string.split(&separator).collect() - }; - - Ok(output!("result" => result)) -} - -/// Replace occurrences in a string. -pub fn replace(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let string: String = get_input(inputs, "string").unwrap_or_default(); - let old: String = get_input(inputs, "old").unwrap_or_default(); - let new: String = get_input(inputs, "new").unwrap_or_default(); - - let result = string.replace(&old, &new); - Ok(output!("result" => result)) -} - -/// Convert string to uppercase. -pub fn upper(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let string: String = get_input(inputs, "string").unwrap_or_default(); - Ok(output!("result" => string.to_uppercase())) -} - -/// Convert string to lowercase. -pub fn lower(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let string: String = get_input(inputs, "string").unwrap_or_default(); - Ok(output!("result" => string.to_lowercase())) -} - -/// Trim whitespace from string. -pub fn trim(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let string: String = get_input(inputs, "string").unwrap_or_default(); - Ok(output!("result" => string.trim())) -} - -/// Get string length. -pub fn length(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let string: String = get_input(inputs, "string").unwrap_or_default(); - Ok(output!("result" => string.len())) -} - -/// Check if string contains substring. -pub fn contains(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let string: String = get_input(inputs, "string").unwrap_or_default(); - let substring: String = get_input(inputs, "substring").unwrap_or_default(); - - Ok(output!("result" => string.contains(&substring))) -} - -/// Check if string starts with prefix. -pub fn starts_with(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let string: String = get_input(inputs, "string").unwrap_or_default(); - let prefix: String = get_input(inputs, "prefix").unwrap_or_default(); - - Ok(output!("result" => string.starts_with(&prefix))) -} - -/// Check if string ends with suffix. -pub fn ends_with(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let string: String = get_input(inputs, "string").unwrap_or_default(); - let suffix: String = get_input(inputs, "suffix").unwrap_or_default(); - - Ok(output!("result" => string.ends_with(&suffix))) -} - -/// Extract a substring from a string. -pub fn substring(_runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let string: String = get_input(inputs, "string").unwrap_or_default(); - let start: i64 = get_input(inputs, "start").unwrap_or(0); - let end: Option = get_input(inputs, "end"); - - let chars: Vec = string.chars().collect(); - let len = chars.len() as i64; - - // Handle negative indices - let start_idx = if start < 0 { (len + start).max(0) } else { start.min(len) } as usize; - let end_idx = match end { - Some(e) if e < 0 => (len + e).max(0) as usize, - Some(e) => e.min(len) as usize, - None => len as usize, - }; - - let result: String = if start_idx < end_idx { - chars[start_idx..end_idx].iter().collect() - } else { - String::new() - }; - - Ok(output!("result" => result)) -} diff --git a/workflow/plugins/rust/src/var.rs b/workflow/plugins/rust/src/var.rs deleted file mode 100644 index edceab1d4..000000000 --- a/workflow/plugins/rust/src/var.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! Variable management workflow plugins - -use crate::{get_input, output, PluginResult, Runtime}; -use serde_json::Value; -use std::collections::HashMap; - -/// Get variable from workflow store. -pub fn get(runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let key: String = match get_input(inputs, "key") { - Some(k) => k, - None => return Ok(output!("result" => Value::Null, "exists" => false, "error" => "key is required")), - }; - - let default = inputs.get("default").cloned().unwrap_or(Value::Null); - - let exists = runtime.store.contains_key(&key); - let value = runtime.store.get(&key).cloned().unwrap_or(default); - - Ok(output!("result" => value, "exists" => exists)) -} - -/// Set variable in workflow store. -pub fn set(runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let key: String = match get_input(inputs, "key") { - Some(k) => k, - None => return Ok(output!("success" => false, "error" => "key is required")), - }; - - let value = inputs.get("value").cloned().unwrap_or(Value::Null); - runtime.store.insert(key.clone(), value); - - Ok(output!("success" => true, "key" => key)) -} - -/// Delete variable from workflow store. -pub fn delete(runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let key: String = match get_input(inputs, "key") { - Some(k) => k, - None => return Ok(output!("success" => false, "error" => "key is required")), - }; - - let existed = runtime.store.remove(&key).is_some(); - - Ok(output!("success" => true, "existed" => existed)) -} - -/// Check if variable exists in workflow store. -pub fn exists(runtime: &mut Runtime, inputs: &HashMap) -> PluginResult { - let key: String = match get_input(inputs, "key") { - Some(k) => k, - None => return Ok(output!("result" => false, "error" => "key is required")), - }; - - Ok(output!("result" => runtime.store.contains_key(&key))) -} - -/// Get all variable keys from workflow store. -pub fn keys(runtime: &mut Runtime, _inputs: &HashMap) -> PluginResult { - let keys: Vec = runtime.store.keys().cloned().collect(); - Ok(output!("result" => keys)) -} - -/// Clear all variables from workflow store. -pub fn clear(runtime: &mut Runtime, _inputs: &HashMap) -> PluginResult { - let count = runtime.store.len(); - runtime.store.clear(); - Ok(output!("success" => true, "cleared" => count)) -} diff --git a/workflow/plugins/rust/string/package.json b/workflow/plugins/rust/string/package.json new file mode 100644 index 000000000..87f348c47 --- /dev/null +++ b/workflow/plugins/rust/string/package.json @@ -0,0 +1,26 @@ +{ + "name": "@metabuilder/workflow-plugins-string-rust", + "version": "0.1.0", + "description": "String manipulation plugins (Rust)", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugins", "rust"], + "metadata": { + "category": "string", + "runtime": "rust", + "plugin_count": 11 + }, + "plugins": [ + "string_concat", + "string_split", + "string_replace", + "string_upper", + "string_lower", + "string_trim", + "string_length", + "string_contains", + "string_starts_with", + "string_ends_with", + "string_substring" + ] +} diff --git a/workflow/plugins/rust/string/string_concat/Cargo.toml b/workflow/plugins/rust/string/string_concat/Cargo.toml new file mode 100644 index 000000000..9e57a53ab --- /dev/null +++ b/workflow/plugins/rust/string/string_concat/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "string_concat" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Concatenate multiple strings" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/string/string_concat/package.json b/workflow/plugins/rust/string/string_concat/package.json new file mode 100644 index 000000000..4b1dad744 --- /dev/null +++ b/workflow/plugins/rust/string/string_concat/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/string_concat", + "version": "0.1.0", + "description": "Concatenate multiple strings", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "string.concat", + "category": "string", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/string/string_concat/src/lib.rs b/workflow/plugins/rust/string/string_concat/src/lib.rs new file mode 100644 index 000000000..2ebfe59b4 --- /dev/null +++ b/workflow/plugins/rust/string/string_concat/src/lib.rs @@ -0,0 +1,37 @@ +//! Workflow plugin: concatenate strings. + +use serde_json::Value; +use std::collections::HashMap; + +/// Concatenate multiple strings with optional separator. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let strings: Vec = inputs + .get("strings") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let separator: String = inputs + .get("separator") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let result = strings.join(&separator); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_concat() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("strings".to_string(), serde_json::json!(["hello", " ", "world"])); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!("hello world"))); + } +} diff --git a/workflow/plugins/rust/string/string_contains/Cargo.toml b/workflow/plugins/rust/string/string_contains/Cargo.toml new file mode 100644 index 000000000..9a05aa727 --- /dev/null +++ b/workflow/plugins/rust/string/string_contains/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "string_contains" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Check if string contains substring" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/string/string_contains/package.json b/workflow/plugins/rust/string/string_contains/package.json new file mode 100644 index 000000000..9b2c8f3e7 --- /dev/null +++ b/workflow/plugins/rust/string/string_contains/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/string_contains", + "version": "0.1.0", + "description": "Check if string contains substring", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "string.contains", + "category": "string", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/string/string_contains/src/lib.rs b/workflow/plugins/rust/string/string_contains/src/lib.rs new file mode 100644 index 000000000..c1269d7b3 --- /dev/null +++ b/workflow/plugins/rust/string/string_contains/src/lib.rs @@ -0,0 +1,36 @@ +//! Workflow plugin: string contains. + +use serde_json::Value; +use std::collections::HashMap; + +/// Check if string contains substring. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let string: String = inputs + .get("string") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let substring: String = inputs + .get("substring") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(string.contains(&substring))); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_contains() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("string".to_string(), serde_json::json!("hello world")); + inputs.insert("substring".to_string(), serde_json::json!("world")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/string/string_ends_with/Cargo.toml b/workflow/plugins/rust/string/string_ends_with/Cargo.toml new file mode 100644 index 000000000..373577be0 --- /dev/null +++ b/workflow/plugins/rust/string/string_ends_with/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "string_ends_with" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Check if string ends with suffix" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/string/string_ends_with/package.json b/workflow/plugins/rust/string/string_ends_with/package.json new file mode 100644 index 000000000..ec5c76204 --- /dev/null +++ b/workflow/plugins/rust/string/string_ends_with/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/string_ends_with", + "version": "0.1.0", + "description": "Check if string ends with suffix", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "string.ends_with", + "category": "string", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/string/string_ends_with/src/lib.rs b/workflow/plugins/rust/string/string_ends_with/src/lib.rs new file mode 100644 index 000000000..d30bc7d39 --- /dev/null +++ b/workflow/plugins/rust/string/string_ends_with/src/lib.rs @@ -0,0 +1,36 @@ +//! Workflow plugin: string ends with. + +use serde_json::Value; +use std::collections::HashMap; + +/// Check if string ends with suffix. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let string: String = inputs + .get("string") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let suffix: String = inputs + .get("suffix") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(string.ends_with(&suffix))); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_ends_with() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("string".to_string(), serde_json::json!("hello world")); + inputs.insert("suffix".to_string(), serde_json::json!("world")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/string/string_length/Cargo.toml b/workflow/plugins/rust/string/string_length/Cargo.toml new file mode 100644 index 000000000..7bde60548 --- /dev/null +++ b/workflow/plugins/rust/string/string_length/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "string_length" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Get string length" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/string/string_length/package.json b/workflow/plugins/rust/string/string_length/package.json new file mode 100644 index 000000000..75b6bb607 --- /dev/null +++ b/workflow/plugins/rust/string/string_length/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/string_length", + "version": "0.1.0", + "description": "Get string length", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "string.length", + "category": "string", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/string/string_length/src/lib.rs b/workflow/plugins/rust/string/string_length/src/lib.rs new file mode 100644 index 000000000..2c2f6e90f --- /dev/null +++ b/workflow/plugins/rust/string/string_length/src/lib.rs @@ -0,0 +1,31 @@ +//! Workflow plugin: string length. + +use serde_json::Value; +use std::collections::HashMap; + +/// Get string length. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let string: String = inputs + .get("string") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(string.len())); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_length() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("string".to_string(), serde_json::json!("hello")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(5))); + } +} diff --git a/workflow/plugins/rust/string/string_lower/Cargo.toml b/workflow/plugins/rust/string/string_lower/Cargo.toml new file mode 100644 index 000000000..f367a8b28 --- /dev/null +++ b/workflow/plugins/rust/string/string_lower/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "string_lower" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Convert string to lowercase" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/string/string_lower/package.json b/workflow/plugins/rust/string/string_lower/package.json new file mode 100644 index 000000000..41ea28827 --- /dev/null +++ b/workflow/plugins/rust/string/string_lower/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/string_lower", + "version": "0.1.0", + "description": "Convert string to lowercase", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "string.lower", + "category": "string", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/string/string_lower/src/lib.rs b/workflow/plugins/rust/string/string_lower/src/lib.rs new file mode 100644 index 000000000..c6f716e63 --- /dev/null +++ b/workflow/plugins/rust/string/string_lower/src/lib.rs @@ -0,0 +1,31 @@ +//! Workflow plugin: lowercase string. + +use serde_json::Value; +use std::collections::HashMap; + +/// Convert string to lowercase. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let string: String = inputs + .get("string") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(string.to_lowercase())); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_lower() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("string".to_string(), serde_json::json!("HELLO")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!("hello"))); + } +} diff --git a/workflow/plugins/rust/string/string_replace/Cargo.toml b/workflow/plugins/rust/string/string_replace/Cargo.toml new file mode 100644 index 000000000..3a1fa02b4 --- /dev/null +++ b/workflow/plugins/rust/string/string_replace/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "string_replace" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Replace occurrences in a string" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/string/string_replace/package.json b/workflow/plugins/rust/string/string_replace/package.json new file mode 100644 index 000000000..98810f54d --- /dev/null +++ b/workflow/plugins/rust/string/string_replace/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/string_replace", + "version": "0.1.0", + "description": "Replace occurrences in a string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "string.replace", + "category": "string", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/string/string_replace/src/lib.rs b/workflow/plugins/rust/string/string_replace/src/lib.rs new file mode 100644 index 000000000..6ca8f9874 --- /dev/null +++ b/workflow/plugins/rust/string/string_replace/src/lib.rs @@ -0,0 +1,43 @@ +//! Workflow plugin: replace in string. + +use serde_json::Value; +use std::collections::HashMap; + +/// Replace occurrences in a string. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let string: String = inputs + .get("string") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let old: String = inputs + .get("old") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let new: String = inputs + .get("new") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let result = string.replace(&old, &new); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_replace() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("string".to_string(), serde_json::json!("hello world")); + inputs.insert("old".to_string(), serde_json::json!("world")); + inputs.insert("new".to_string(), serde_json::json!("rust")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!("hello rust"))); + } +} diff --git a/workflow/plugins/rust/string/string_split/Cargo.toml b/workflow/plugins/rust/string/string_split/Cargo.toml new file mode 100644 index 000000000..b94cfb174 --- /dev/null +++ b/workflow/plugins/rust/string/string_split/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "string_split" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Split a string by separator" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/string/string_split/package.json b/workflow/plugins/rust/string/string_split/package.json new file mode 100644 index 000000000..54994d50b --- /dev/null +++ b/workflow/plugins/rust/string/string_split/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/string_split", + "version": "0.1.0", + "description": "Split a string by separator", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "string.split", + "category": "string", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/string/string_split/src/lib.rs b/workflow/plugins/rust/string/string_split/src/lib.rs new file mode 100644 index 000000000..aab5b8c7c --- /dev/null +++ b/workflow/plugins/rust/string/string_split/src/lib.rs @@ -0,0 +1,42 @@ +//! Workflow plugin: split a string. + +use serde_json::Value; +use std::collections::HashMap; + +/// Split a string by separator. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let string: String = inputs + .get("string") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let separator: String = inputs + .get("separator") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let result: Vec = if separator.is_empty() { + string.chars().map(|c| c.to_string()).collect() + } else { + string.split(&separator).map(|s| s.to_string()).collect() + }; + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_split() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("string".to_string(), serde_json::json!("a,b,c")); + inputs.insert("separator".to_string(), serde_json::json!(",")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(["a", "b", "c"]))); + } +} diff --git a/workflow/plugins/rust/string/string_starts_with/Cargo.toml b/workflow/plugins/rust/string/string_starts_with/Cargo.toml new file mode 100644 index 000000000..bc8c863fe --- /dev/null +++ b/workflow/plugins/rust/string/string_starts_with/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "string_starts_with" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Check if string starts with prefix" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/string/string_starts_with/package.json b/workflow/plugins/rust/string/string_starts_with/package.json new file mode 100644 index 000000000..4c85d82ef --- /dev/null +++ b/workflow/plugins/rust/string/string_starts_with/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/string_starts_with", + "version": "0.1.0", + "description": "Check if string starts with prefix", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "string.starts_with", + "category": "string", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/string/string_starts_with/src/lib.rs b/workflow/plugins/rust/string/string_starts_with/src/lib.rs new file mode 100644 index 000000000..c89ab1702 --- /dev/null +++ b/workflow/plugins/rust/string/string_starts_with/src/lib.rs @@ -0,0 +1,36 @@ +//! Workflow plugin: string starts with. + +use serde_json::Value; +use std::collections::HashMap; + +/// Check if string starts with prefix. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let string: String = inputs + .get("string") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let prefix: String = inputs + .get("prefix") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(string.starts_with(&prefix))); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_starts_with() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("string".to_string(), serde_json::json!("hello world")); + inputs.insert("prefix".to_string(), serde_json::json!("hello")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/string/string_substring/Cargo.toml b/workflow/plugins/rust/string/string_substring/Cargo.toml new file mode 100644 index 000000000..b9131f9fe --- /dev/null +++ b/workflow/plugins/rust/string/string_substring/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "string_substring" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Extract a substring from a string" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/string/string_substring/package.json b/workflow/plugins/rust/string/string_substring/package.json new file mode 100644 index 000000000..48e5b2fc6 --- /dev/null +++ b/workflow/plugins/rust/string/string_substring/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/string_substring", + "version": "0.1.0", + "description": "Extract a substring from a string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "string.substring", + "category": "string", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/string/string_substring/src/lib.rs b/workflow/plugins/rust/string/string_substring/src/lib.rs new file mode 100644 index 000000000..0903d6727 --- /dev/null +++ b/workflow/plugins/rust/string/string_substring/src/lib.rs @@ -0,0 +1,57 @@ +//! Workflow plugin: substring. + +use serde_json::Value; +use std::collections::HashMap; + +/// Extract a substring from a string. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let string: String = inputs + .get("string") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + let start: i64 = inputs + .get("start") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or(0); + let end: Option = inputs + .get("end") + .and_then(|v| serde_json::from_value(v.clone()).ok()); + + let chars: Vec = string.chars().collect(); + let len = chars.len() as i64; + + // Handle negative indices + let start_idx = if start < 0 { (len + start).max(0) } else { start.min(len) } as usize; + let end_idx = match end { + Some(e) if e < 0 => (len + e).max(0) as usize, + Some(e) => e.min(len) as usize, + None => len as usize, + }; + + let result: String = if start_idx < end_idx { + chars[start_idx..end_idx].iter().collect() + } else { + String::new() + }; + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(result)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_substring() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("string".to_string(), serde_json::json!("hello world")); + inputs.insert("start".to_string(), serde_json::json!(0)); + inputs.insert("end".to_string(), serde_json::json!(5)); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!("hello"))); + } +} diff --git a/workflow/plugins/rust/string/string_trim/Cargo.toml b/workflow/plugins/rust/string/string_trim/Cargo.toml new file mode 100644 index 000000000..f6680826d --- /dev/null +++ b/workflow/plugins/rust/string/string_trim/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "string_trim" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Trim whitespace from string" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/string/string_trim/package.json b/workflow/plugins/rust/string/string_trim/package.json new file mode 100644 index 000000000..ed4f2963c --- /dev/null +++ b/workflow/plugins/rust/string/string_trim/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/string_trim", + "version": "0.1.0", + "description": "Trim whitespace from string", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "string.trim", + "category": "string", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/string/string_trim/src/lib.rs b/workflow/plugins/rust/string/string_trim/src/lib.rs new file mode 100644 index 000000000..aeba0f1c5 --- /dev/null +++ b/workflow/plugins/rust/string/string_trim/src/lib.rs @@ -0,0 +1,31 @@ +//! Workflow plugin: trim string. + +use serde_json::Value; +use std::collections::HashMap; + +/// Trim whitespace from string. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let string: String = inputs + .get("string") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(string.trim())); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_trim() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("string".to_string(), serde_json::json!(" hello ")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!("hello"))); + } +} diff --git a/workflow/plugins/rust/string/string_upper/Cargo.toml b/workflow/plugins/rust/string/string_upper/Cargo.toml new file mode 100644 index 000000000..f6fb8fede --- /dev/null +++ b/workflow/plugins/rust/string/string_upper/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "string_upper" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Convert string to uppercase" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/string/string_upper/package.json b/workflow/plugins/rust/string/string_upper/package.json new file mode 100644 index 000000000..b31388142 --- /dev/null +++ b/workflow/plugins/rust/string/string_upper/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/string_upper", + "version": "0.1.0", + "description": "Convert string to uppercase", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["string", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "string.upper", + "category": "string", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/string/string_upper/src/lib.rs b/workflow/plugins/rust/string/string_upper/src/lib.rs new file mode 100644 index 000000000..989bda407 --- /dev/null +++ b/workflow/plugins/rust/string/string_upper/src/lib.rs @@ -0,0 +1,31 @@ +//! Workflow plugin: uppercase string. + +use serde_json::Value; +use std::collections::HashMap; + +/// Convert string to uppercase. +pub fn run(_runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let string: String = inputs + .get("string") + .and_then(|v| serde_json::from_value(v.clone()).ok()) + .unwrap_or_default(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(string.to_uppercase())); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_upper() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("string".to_string(), serde_json::json!("hello")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!("HELLO"))); + } +} diff --git a/workflow/plugins/rust/var/package.json b/workflow/plugins/rust/var/package.json new file mode 100644 index 000000000..245826243 --- /dev/null +++ b/workflow/plugins/rust/var/package.json @@ -0,0 +1,21 @@ +{ + "name": "@metabuilder/workflow-plugins-var-rust", + "version": "0.1.0", + "description": "Variable management plugins (Rust)", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "variable", "workflow", "plugins", "rust"], + "metadata": { + "category": "var", + "runtime": "rust", + "plugin_count": 6 + }, + "plugins": [ + "var_get", + "var_set", + "var_delete", + "var_exists", + "var_keys", + "var_clear" + ] +} diff --git a/workflow/plugins/rust/var/var_clear/Cargo.toml b/workflow/plugins/rust/var/var_clear/Cargo.toml new file mode 100644 index 000000000..65a6b61fc --- /dev/null +++ b/workflow/plugins/rust/var/var_clear/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "var_clear" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Clear all variables from workflow store" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/var/var_clear/package.json b/workflow/plugins/rust/var/var_clear/package.json new file mode 100644 index 000000000..1a6c6b533 --- /dev/null +++ b/workflow/plugins/rust/var/var_clear/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/var_clear", + "version": "0.1.0", + "description": "Clear all variables from workflow store", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "var.clear", + "category": "var", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/var/var_clear/src/lib.rs b/workflow/plugins/rust/var/var_clear/src/lib.rs new file mode 100644 index 000000000..0c3403011 --- /dev/null +++ b/workflow/plugins/rust/var/var_clear/src/lib.rs @@ -0,0 +1,34 @@ +//! Workflow plugin: clear all variables. + +use serde_json::Value; +use std::collections::HashMap; + +/// Clear all variables from workflow store. +pub fn run(runtime: &mut HashMap, _inputs: &HashMap) -> Result, String> { + let count = runtime.len(); + runtime.clear(); + + let mut output = HashMap::new(); + output.insert("success".to_string(), serde_json::json!(true)); + output.insert("cleared".to_string(), serde_json::json!(count)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_clear() { + let mut runtime = HashMap::new(); + runtime.insert("foo".to_string(), serde_json::json!("bar")); + runtime.insert("baz".to_string(), serde_json::json!("qux")); + + let inputs = HashMap::new(); + let result = run(&mut runtime, &inputs).unwrap(); + + assert_eq!(result.get("success"), Some(&serde_json::json!(true))); + assert_eq!(result.get("cleared"), Some(&serde_json::json!(2))); + assert!(runtime.is_empty()); + } +} diff --git a/workflow/plugins/rust/var/var_delete/Cargo.toml b/workflow/plugins/rust/var/var_delete/Cargo.toml new file mode 100644 index 000000000..17e735f8c --- /dev/null +++ b/workflow/plugins/rust/var/var_delete/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "var_delete" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Delete variable from workflow store" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/var/var_delete/package.json b/workflow/plugins/rust/var/var_delete/package.json new file mode 100644 index 000000000..425a9ae14 --- /dev/null +++ b/workflow/plugins/rust/var/var_delete/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/var_delete", + "version": "0.1.0", + "description": "Delete variable from workflow store", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "var.delete", + "category": "var", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/var/var_delete/src/lib.rs b/workflow/plugins/rust/var/var_delete/src/lib.rs new file mode 100644 index 000000000..aee98c810 --- /dev/null +++ b/workflow/plugins/rust/var/var_delete/src/lib.rs @@ -0,0 +1,47 @@ +//! Workflow plugin: delete variable. + +use serde_json::Value; +use std::collections::HashMap; + +/// Delete variable from workflow store. +pub fn run(runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let key: Option = inputs + .get("key") + .and_then(|v| serde_json::from_value(v.clone()).ok()); + + let mut output = HashMap::new(); + + match key { + Some(k) => { + let existed = runtime.remove(&k).is_some(); + + output.insert("success".to_string(), serde_json::json!(true)); + output.insert("existed".to_string(), serde_json::json!(existed)); + } + None => { + output.insert("success".to_string(), serde_json::json!(false)); + output.insert("error".to_string(), serde_json::json!("key is required")); + } + } + + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_delete() { + let mut runtime = HashMap::new(); + runtime.insert("foo".to_string(), serde_json::json!("bar")); + + let mut inputs = HashMap::new(); + inputs.insert("key".to_string(), serde_json::json!("foo")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("success"), Some(&serde_json::json!(true))); + assert_eq!(result.get("existed"), Some(&serde_json::json!(true))); + assert!(!runtime.contains_key("foo")); + } +} diff --git a/workflow/plugins/rust/var/var_exists/Cargo.toml b/workflow/plugins/rust/var/var_exists/Cargo.toml new file mode 100644 index 000000000..f2032e94d --- /dev/null +++ b/workflow/plugins/rust/var/var_exists/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "var_exists" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Check if variable exists in workflow store" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/var/var_exists/package.json b/workflow/plugins/rust/var/var_exists/package.json new file mode 100644 index 000000000..3c20332ac --- /dev/null +++ b/workflow/plugins/rust/var/var_exists/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/var_exists", + "version": "0.1.0", + "description": "Check if variable exists in workflow store", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "var.exists", + "category": "var", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/var/var_exists/src/lib.rs b/workflow/plugins/rust/var/var_exists/src/lib.rs new file mode 100644 index 000000000..59df9ba17 --- /dev/null +++ b/workflow/plugins/rust/var/var_exists/src/lib.rs @@ -0,0 +1,42 @@ +//! Workflow plugin: check if variable exists. + +use serde_json::Value; +use std::collections::HashMap; + +/// Check if variable exists in workflow store. +pub fn run(runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let key: Option = inputs + .get("key") + .and_then(|v| serde_json::from_value(v.clone()).ok()); + + let mut output = HashMap::new(); + + match key { + Some(k) => { + output.insert("result".to_string(), serde_json::json!(runtime.contains_key(&k))); + } + None => { + output.insert("result".to_string(), serde_json::json!(false)); + output.insert("error".to_string(), serde_json::json!("key is required")); + } + } + + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_exists() { + let mut runtime = HashMap::new(); + runtime.insert("foo".to_string(), serde_json::json!("bar")); + + let mut inputs = HashMap::new(); + inputs.insert("key".to_string(), serde_json::json!("foo")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/var/var_get/Cargo.toml b/workflow/plugins/rust/var/var_get/Cargo.toml new file mode 100644 index 000000000..7a0bddb29 --- /dev/null +++ b/workflow/plugins/rust/var/var_get/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "var_get" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Get variable from workflow store" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/var/var_get/package.json b/workflow/plugins/rust/var/var_get/package.json new file mode 100644 index 000000000..d96f44c87 --- /dev/null +++ b/workflow/plugins/rust/var/var_get/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/var_get", + "version": "0.1.0", + "description": "Get variable from workflow store", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "var.get", + "category": "var", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/var/var_get/src/lib.rs b/workflow/plugins/rust/var/var_get/src/lib.rs new file mode 100644 index 000000000..e8061d2c6 --- /dev/null +++ b/workflow/plugins/rust/var/var_get/src/lib.rs @@ -0,0 +1,49 @@ +//! Workflow plugin: get variable. + +use serde_json::Value; +use std::collections::HashMap; + +/// Get variable from workflow store. +pub fn run(runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let key: Option = inputs + .get("key") + .and_then(|v| serde_json::from_value(v.clone()).ok()); + + let mut output = HashMap::new(); + + match key { + Some(k) => { + let default = inputs.get("default").cloned().unwrap_or(Value::Null); + let exists = runtime.contains_key(&k); + let value = runtime.get(&k).cloned().unwrap_or(default); + + output.insert("result".to_string(), value); + output.insert("exists".to_string(), serde_json::json!(exists)); + } + None => { + output.insert("result".to_string(), Value::Null); + output.insert("exists".to_string(), serde_json::json!(false)); + output.insert("error".to_string(), serde_json::json!("key is required")); + } + } + + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get() { + let mut runtime = HashMap::new(); + runtime.insert("foo".to_string(), serde_json::json!("bar")); + + let mut inputs = HashMap::new(); + inputs.insert("key".to_string(), serde_json::json!("foo")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("result"), Some(&serde_json::json!("bar"))); + assert_eq!(result.get("exists"), Some(&serde_json::json!(true))); + } +} diff --git a/workflow/plugins/rust/var/var_keys/Cargo.toml b/workflow/plugins/rust/var/var_keys/Cargo.toml new file mode 100644 index 000000000..d14d563f2 --- /dev/null +++ b/workflow/plugins/rust/var/var_keys/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "var_keys" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Get all variable keys from workflow store" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/var/var_keys/package.json b/workflow/plugins/rust/var/var_keys/package.json new file mode 100644 index 000000000..d71603f3b --- /dev/null +++ b/workflow/plugins/rust/var/var_keys/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/var_keys", + "version": "0.1.0", + "description": "Get all variable keys from workflow store", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "var.keys", + "category": "var", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/var/var_keys/src/lib.rs b/workflow/plugins/rust/var/var_keys/src/lib.rs new file mode 100644 index 000000000..d67dcbbc6 --- /dev/null +++ b/workflow/plugins/rust/var/var_keys/src/lib.rs @@ -0,0 +1,31 @@ +//! Workflow plugin: get all variable keys. + +use serde_json::Value; +use std::collections::HashMap; + +/// Get all variable keys from workflow store. +pub fn run(runtime: &mut HashMap, _inputs: &HashMap) -> Result, String> { + let keys: Vec = runtime.keys().cloned().collect(); + + let mut output = HashMap::new(); + output.insert("result".to_string(), serde_json::json!(keys)); + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_keys() { + let mut runtime = HashMap::new(); + runtime.insert("foo".to_string(), serde_json::json!("bar")); + runtime.insert("baz".to_string(), serde_json::json!("qux")); + + let inputs = HashMap::new(); + let result = run(&mut runtime, &inputs).unwrap(); + + let keys = result.get("result").unwrap().as_array().unwrap(); + assert_eq!(keys.len(), 2); + } +} diff --git a/workflow/plugins/rust/var/var_set/Cargo.toml b/workflow/plugins/rust/var/var_set/Cargo.toml new file mode 100644 index 000000000..e47b2dcb3 --- /dev/null +++ b/workflow/plugins/rust/var/var_set/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "var_set" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +description = "Set variable in workflow store" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/workflow/plugins/rust/var/var_set/package.json b/workflow/plugins/rust/var/var_set/package.json new file mode 100644 index 000000000..0bf5622b7 --- /dev/null +++ b/workflow/plugins/rust/var/var_set/package.json @@ -0,0 +1,14 @@ +{ + "name": "@metabuilder/var_set", + "version": "0.1.0", + "description": "Set variable in workflow store", + "author": "MetaBuilder", + "license": "MIT", + "keywords": ["var", "workflow", "plugin", "rust"], + "main": "src/lib.rs", + "metadata": { + "plugin_type": "var.set", + "category": "var", + "runtime": "rust" + } +} diff --git a/workflow/plugins/rust/var/var_set/src/lib.rs b/workflow/plugins/rust/var/var_set/src/lib.rs new file mode 100644 index 000000000..65043af47 --- /dev/null +++ b/workflow/plugins/rust/var/var_set/src/lib.rs @@ -0,0 +1,46 @@ +//! Workflow plugin: set variable. + +use serde_json::Value; +use std::collections::HashMap; + +/// Set variable in workflow store. +pub fn run(runtime: &mut HashMap, inputs: &HashMap) -> Result, String> { + let key: Option = inputs + .get("key") + .and_then(|v| serde_json::from_value(v.clone()).ok()); + + let mut output = HashMap::new(); + + match key { + Some(k) => { + let value = inputs.get("value").cloned().unwrap_or(Value::Null); + runtime.insert(k.clone(), value); + + output.insert("success".to_string(), serde_json::json!(true)); + output.insert("key".to_string(), serde_json::json!(k)); + } + None => { + output.insert("success".to_string(), serde_json::json!(false)); + output.insert("error".to_string(), serde_json::json!("key is required")); + } + } + + Ok(output) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_set() { + let mut runtime = HashMap::new(); + let mut inputs = HashMap::new(); + inputs.insert("key".to_string(), serde_json::json!("foo")); + inputs.insert("value".to_string(), serde_json::json!("bar")); + + let result = run(&mut runtime, &inputs).unwrap(); + assert_eq!(result.get("success"), Some(&serde_json::json!(true))); + assert_eq!(runtime.get("foo"), Some(&serde_json::json!("bar"))); + } +}