bring back yahoo pipes!
1package transforms
2
3import (
4 "context"
5 "fmt"
6 "strings"
7
8 "github.com/kierank/pipes/nodes"
9)
10
11type MapNode struct{}
12
13func (n *MapNode) Type() string { return "map" }
14func (n *MapNode) Label() string { return "Map Fields" }
15func (n *MapNode) Description() string { return "Rename, extract, or create new fields" }
16func (n *MapNode) Category() string { return "transform" }
17func (n *MapNode) Inputs() int { return 1 }
18func (n *MapNode) Outputs() int { return 1 }
19
20func (n *MapNode) Execute(ctx context.Context, config map[string]interface{}, inputs [][]interface{}, execCtx *nodes.Context) ([]interface{}, error) {
21 if len(inputs) == 0 || len(inputs[0]) == 0 {
22 return []interface{}{}, nil
23 }
24
25 items := inputs[0]
26 mappings, _ := config["mappings"].(string)
27 keepOriginal, _ := config["keep_original"].(bool)
28
29 if mappings == "" {
30 return items, nil
31 }
32
33 // Parse mappings: "newField:sourceField, title:name"
34 fieldMap := parseMappings(mappings)
35
36 var result []interface{}
37 for _, item := range items {
38 itemMap, ok := item.(map[string]interface{})
39 if !ok {
40 result = append(result, item)
41 continue
42 }
43
44 var newItem map[string]interface{}
45 if keepOriginal {
46 newItem = make(map[string]interface{})
47 for k, v := range itemMap {
48 newItem[k] = v
49 }
50 } else {
51 newItem = make(map[string]interface{})
52 }
53
54 for newField, sourceField := range fieldMap {
55 if val := getNestedValue(itemMap, sourceField); val != nil {
56 newItem[newField] = val
57 }
58 }
59
60 result = append(result, newItem)
61 }
62
63 execCtx.Log("map", "info", fmt.Sprintf("Mapped %d items", len(result)))
64 return result, nil
65}
66
67func parseMappings(s string) map[string]string {
68 result := make(map[string]string)
69 parts := strings.Split(s, ",")
70 for _, part := range parts {
71 part = strings.TrimSpace(part)
72 if kv := strings.SplitN(part, ":", 2); len(kv) == 2 {
73 result[strings.TrimSpace(kv[0])] = strings.TrimSpace(kv[1])
74 }
75 }
76 return result
77}
78
79func (n *MapNode) ValidateConfig(config map[string]interface{}) error {
80 return nil
81}
82
83func (n *MapNode) GetConfigSchema() *nodes.ConfigSchema {
84 return &nodes.ConfigSchema{
85 Fields: []nodes.ConfigField{
86 {
87 Name: "mappings",
88 Label: "Field Mappings",
89 Type: "textarea",
90 Required: true,
91 Placeholder: "title:name, url:link, summary:description",
92 HelpText: "Map fields as newField:sourceField, separated by commas. Use dot notation for nested fields.",
93 },
94 {
95 Name: "keep_original",
96 Label: "Keep Original Fields",
97 Type: "checkbox",
98 Required: false,
99 DefaultValue: true,
100 HelpText: "Keep all original fields in addition to mapped ones",
101 },
102 },
103 }
104}