ondc-code-generator 0.6.22 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/copilot-instructions.md +128 -0
- package/GOLANG_IMPLEMENTATION.md +156 -0
- package/README.md +10 -1
- package/dist/bin/cli-tool.d.ts +70 -0
- package/dist/bin/cli-tool.js +310 -0
- package/dist/bin/cli.d.ts +2 -0
- package/dist/bin/cli.js +80 -0
- package/dist/generator/config-compiler.d.ts +1 -0
- package/dist/generator/config-compiler.js +14 -0
- package/dist/generator/generators/go/go-ast.d.ts +1 -0
- package/dist/generator/generators/go/go-ast.js +60 -0
- package/dist/generator/generators/go/go-generator.d.ts +13 -0
- package/dist/generator/generators/go/go-generator.js +322 -0
- package/dist/generator/generators/go/templates/api-tests.mustache +65 -0
- package/dist/generator/generators/go/templates/go-mod.mustache +3 -0
- package/dist/generator/generators/go/templates/index.mustache +34 -0
- package/dist/generator/generators/go/templates/json-normalizer.mustache +155 -0
- package/dist/generator/generators/go/templates/json-path-utils.mustache +63 -0
- package/dist/generator/generators/go/templates/storage-templates/api-save-utils.mustache +84 -0
- package/dist/generator/generators/go/templates/storage-templates/api-save.mustache +44 -0
- package/dist/generator/generators/go/templates/storage-templates/index.mustache +72 -0
- package/dist/generator/generators/go/templates/storage-templates/save-utils.mustache +75 -0
- package/dist/generator/generators/go/templates/storage-templates/storage-interface.mustache +107 -0
- package/dist/generator/generators/go/templates/test-config.mustache +62 -0
- package/dist/generator/generators/go/templates/test-object.mustache +52 -0
- package/dist/generator/generators/go/templates/validation-code.mustache +66 -0
- package/dist/generator/generators/go/templates/validation-utils.mustache +321 -0
- package/dist/generator/generators/typescript/templates/index.mustache +1 -1
- package/dist/generator/generators/typescript/ts-generator.js +2 -2
- package/dist/index.d.ts +7 -1
- package/dist/index.js +6 -1
- package/dist/index.test.js +8 -1
- package/dist/types/build.d.ts +2 -0
- package/dist/types/compiler-types.d.ts +2 -1
- package/dist/types/compiler-types.js +1 -0
- package/dist/utils/fs-utils.d.ts +1 -0
- package/dist/utils/fs-utils.js +24 -0
- package/dist/utils/general-utils/string-utils.d.ts +1 -0
- package/dist/utils/general-utils/string-utils.js +11 -0
- package/package.json +5 -1
- package/sample.md +273 -0
- package/test-python-session.js +0 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// Code generated by github.com/ONDC-Official/automation-validation-compiler, DO NOT EDIT.
|
|
2
|
+
|
|
3
|
+
package validationutils
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"encoding/json"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
// NormalizeKeys normalizes JSON structures so that:
|
|
10
|
+
// - All objects with the same property name share the union of keys seen anywhere
|
|
11
|
+
// - All objects inside the same array share the union of keys at that array level
|
|
12
|
+
// - Missing keys are filled with nil
|
|
13
|
+
func NormalizeKeys(input interface{}) interface{} {
|
|
14
|
+
// Step 1: Collect templates by property name
|
|
15
|
+
templatesByPropName := make(map[string]map[string]struct{})
|
|
16
|
+
collectTemplates(input, templatesByPropName)
|
|
17
|
+
|
|
18
|
+
// Step 2: Apply templates and within-array unions
|
|
19
|
+
return applyTemplates(input, templatesByPropName)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// collectTemplates walks the data structure and collects all keys for each property name
|
|
23
|
+
func collectTemplates(node interface{}, templates map[string]map[string]struct{}) {
|
|
24
|
+
switch v := node.(type) {
|
|
25
|
+
case []interface{}:
|
|
26
|
+
// Recurse into array items
|
|
27
|
+
for _, item := range v {
|
|
28
|
+
collectTemplates(item, templates)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
case map[string]interface{}:
|
|
32
|
+
// For each property: if it's an object (non-array), record its keys
|
|
33
|
+
for propName, propValue := range v {
|
|
34
|
+
if obj, ok := propValue.(map[string]interface{}); ok {
|
|
35
|
+
// Initialize set for this property name if needed
|
|
36
|
+
if templates[propName] == nil {
|
|
37
|
+
templates[propName] = make(map[string]struct{})
|
|
38
|
+
}
|
|
39
|
+
// Add all keys from this object to the template
|
|
40
|
+
for childKey := range obj {
|
|
41
|
+
templates[propName][childKey] = struct{}{}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Recurse into the value
|
|
45
|
+
collectTemplates(propValue, templates)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// applyTemplates applies the collected templates and array-level unions
|
|
51
|
+
func applyTemplates(node interface{}, templates map[string]map[string]struct{}) interface{} {
|
|
52
|
+
switch v := node.(type) {
|
|
53
|
+
case []interface{}:
|
|
54
|
+
// Compute union of keys across all object elements at this array level
|
|
55
|
+
arrayUnion := make(map[string]struct{})
|
|
56
|
+
for _, item := range v {
|
|
57
|
+
if obj, ok := item.(map[string]interface{}); ok {
|
|
58
|
+
for key := range obj {
|
|
59
|
+
arrayUnion[key] = struct{}{}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Apply union to each array element
|
|
65
|
+
result := make([]interface{}, len(v))
|
|
66
|
+
for i, item := range v {
|
|
67
|
+
if obj, ok := item.(map[string]interface{}); ok {
|
|
68
|
+
// Create new object with array union keys
|
|
69
|
+
next := make(map[string]interface{})
|
|
70
|
+
|
|
71
|
+
// Copy existing keys
|
|
72
|
+
for k, val := range obj {
|
|
73
|
+
next[k] = val
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Add missing keys from array union
|
|
77
|
+
for key := range arrayUnion {
|
|
78
|
+
if _, exists := next[key]; !exists {
|
|
79
|
+
next[key] = nil
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Now apply templates per property name for nested objects
|
|
84
|
+
for propName, propValue := range next {
|
|
85
|
+
if nestedObj, ok := propValue.(map[string]interface{}); ok {
|
|
86
|
+
// Align to template for this property name
|
|
87
|
+
next[propName] = fillFromTemplate(propName, nestedObj, templates)
|
|
88
|
+
} else {
|
|
89
|
+
// Recurse for arrays or other structures
|
|
90
|
+
next[propName] = applyTemplates(propValue, templates)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
result[i] = next
|
|
94
|
+
} else {
|
|
95
|
+
// Not an object, just recurse
|
|
96
|
+
result[i] = applyTemplates(item, templates)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return result
|
|
100
|
+
|
|
101
|
+
case map[string]interface{}:
|
|
102
|
+
out := make(map[string]interface{})
|
|
103
|
+
for propName, propValue := range v {
|
|
104
|
+
if nestedObj, ok := propValue.(map[string]interface{}); ok {
|
|
105
|
+
// Align object to the template for this property name
|
|
106
|
+
out[propName] = fillFromTemplate(propName, nestedObj, templates)
|
|
107
|
+
} else {
|
|
108
|
+
out[propName] = applyTemplates(propValue, templates)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return out
|
|
112
|
+
|
|
113
|
+
default:
|
|
114
|
+
// Primitives unchanged
|
|
115
|
+
return v
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// fillFromTemplate applies the template for a given property name
|
|
120
|
+
func fillFromTemplate(propName string, obj map[string]interface{}, templates map[string]map[string]struct{}) interface{} {
|
|
121
|
+
// First recurse on children so nested arrays/objects also normalize
|
|
122
|
+
base := applyTemplates(obj, templates).(map[string]interface{})
|
|
123
|
+
|
|
124
|
+
// Get template for this property name
|
|
125
|
+
template, hasTemplate := templates[propName]
|
|
126
|
+
if !hasTemplate {
|
|
127
|
+
return base // No known template keys for this prop
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Fill missing keys with nil
|
|
131
|
+
filled := make(map[string]interface{})
|
|
132
|
+
for k, v := range base {
|
|
133
|
+
filled[k] = v
|
|
134
|
+
}
|
|
135
|
+
for key := range template {
|
|
136
|
+
if _, exists := filled[key]; !exists {
|
|
137
|
+
filled[key] = nil
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return filled
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// DeepCloneJSON creates a deep clone of a JSON-serializable structure
|
|
145
|
+
func DeepCloneJSON(v interface{}) interface{} {
|
|
146
|
+
b, err := json.Marshal(v)
|
|
147
|
+
if err != nil {
|
|
148
|
+
panic(err) // or handle error
|
|
149
|
+
}
|
|
150
|
+
var out interface{}
|
|
151
|
+
if err := json.Unmarshal(b, &out); err != nil {
|
|
152
|
+
panic(err)
|
|
153
|
+
}
|
|
154
|
+
return out
|
|
155
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Code generated by github.com/ONDC-Official/automation-validation-compiler, DO NOT EDIT.
|
|
2
|
+
|
|
3
|
+
package validationutils
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"github.com/AsaiYusuke/jsonpath"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
// isListOfStringsOrNull checks if the variable is a slice containing only strings or nil values
|
|
10
|
+
func isListOfStringsOrNull(variable interface{}) bool {
|
|
11
|
+
slice, ok := variable.([]interface{})
|
|
12
|
+
if !ok {
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
for _, item := range slice {
|
|
17
|
+
if item == nil {
|
|
18
|
+
continue
|
|
19
|
+
}
|
|
20
|
+
if _, isString := item.(string); !isString {
|
|
21
|
+
return false
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return true
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// GetJsonPath queries a payload using JSONPath and returns the results
|
|
28
|
+
func GetJsonPath(payload interface{}, path string, flattenResult bool) []interface{} {
|
|
29
|
+
output, err := jsonpath.Retrieve(path, payload)
|
|
30
|
+
if err != nil {
|
|
31
|
+
return []interface{}{}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if isListOfStringsOrNull(output) {
|
|
35
|
+
for i, item := range output {
|
|
36
|
+
if item == nil {
|
|
37
|
+
output[i] = "null"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if flattenResult {
|
|
43
|
+
output = flattenSlice(output)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if len(output) == 0 {
|
|
47
|
+
return []interface{}{}
|
|
48
|
+
}
|
|
49
|
+
return output
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// flattenSlice recursively flattens nested slices
|
|
53
|
+
func flattenSlice(slice []interface{}) []interface{} {
|
|
54
|
+
result := make([]interface{}, 0)
|
|
55
|
+
for _, item := range slice {
|
|
56
|
+
if nestedSlice, ok := item.([]interface{}); ok {
|
|
57
|
+
result = append(result, flattenSlice(nestedSlice)...)
|
|
58
|
+
} else {
|
|
59
|
+
result = append(result, item)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return result
|
|
63
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Code generated by github.com/ONDC-Official/automation-validation-compiler, DO NOT EDIT.
|
|
2
|
+
|
|
3
|
+
package storageutils
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"encoding/json"
|
|
7
|
+
"fmt"
|
|
8
|
+
"time"
|
|
9
|
+
"validationpkg/validationutils"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
// saveFunction saves extracted data from payload to storage
|
|
14
|
+
func saveFunction(
|
|
15
|
+
payload interface{},
|
|
16
|
+
uniquePrefix string,
|
|
17
|
+
key string,
|
|
18
|
+
path string,
|
|
19
|
+
store validationutils.StorageInterface,
|
|
20
|
+
config StorageConfig,
|
|
21
|
+
action string,
|
|
22
|
+
) error {
|
|
23
|
+
if path == "" || key == "_SELF" {
|
|
24
|
+
return nil
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Extract value using JSONPath
|
|
28
|
+
value := validationutils.GetJsonPath(payload, path, true)
|
|
29
|
+
|
|
30
|
+
// Create data structure
|
|
31
|
+
data := map[string]interface{}{
|
|
32
|
+
"stored_from": action + "_action",
|
|
33
|
+
"key_path": path,
|
|
34
|
+
"value": value,
|
|
35
|
+
"timestamp": time.Now().UTC().Format(time.RFC3339),
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Serialize to JSON
|
|
39
|
+
dataBytes, err := json.Marshal(data)
|
|
40
|
+
if err != nil {
|
|
41
|
+
return fmt.Errorf("failed to marshal data: %w", err)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Save with retry logic
|
|
45
|
+
return SaveData(uniquePrefix, key, string(dataBytes), store, config)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// loadFunction loads and parses stored data from storage
|
|
49
|
+
func loadFunction(
|
|
50
|
+
store validationutils.StorageInterface,
|
|
51
|
+
uniquePrefix string,
|
|
52
|
+
key string,
|
|
53
|
+
) ([]string, error) {
|
|
54
|
+
value, err := store.GetKey(uniquePrefix, key)
|
|
55
|
+
if err != nil {
|
|
56
|
+
// Return empty slice on error (matches TS behavior)
|
|
57
|
+
return []string{}, nil
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if value == "" {
|
|
61
|
+
return []string{}, nil
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Parse JSON
|
|
65
|
+
var data struct {
|
|
66
|
+
Value []interface{} `json:"value"`
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if err := json.Unmarshal([]byte(value), &data); err != nil {
|
|
70
|
+
return []string{}, nil
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Convert to string slice
|
|
74
|
+
result := make([]string, 0, len(data.Value))
|
|
75
|
+
for _, v := range data.Value {
|
|
76
|
+
if v == nil {
|
|
77
|
+
result = append(result, "null")
|
|
78
|
+
} else {
|
|
79
|
+
result = append(result, fmt.Sprintf("%v", v))
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return result, nil
|
|
84
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Code generated by github.com/ONDC-Official/automation-validation-compiler, DO NOT EDIT.
|
|
2
|
+
|
|
3
|
+
package storageutils
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"validationpkg/validationutils"
|
|
7
|
+
"fmt"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// Store_{{action}} stores data from payload to storage for the {{action}} action
|
|
11
|
+
func Store_{{action}}(
|
|
12
|
+
uniquePrefix string,
|
|
13
|
+
payload interface{},
|
|
14
|
+
store validationutils.StorageInterface,
|
|
15
|
+
config StorageConfig,
|
|
16
|
+
) error {
|
|
17
|
+
{{#storeActions}}
|
|
18
|
+
if err := saveFunction(payload, uniquePrefix, "{{{key}}}", "{{{value}}}", store, config, "{{$action}}"); err != nil {
|
|
19
|
+
return fmt.Errorf("failed to save key {{{key}}}: %w", err)
|
|
20
|
+
}
|
|
21
|
+
{{/storeActions}}
|
|
22
|
+
fmt.Printf("Stored data for action {{action}} successfully\n")
|
|
23
|
+
return nil
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// LoadFor_{{action}} loads stored data for the {{action}} action
|
|
27
|
+
func LoadFor_{{action}}(
|
|
28
|
+
uniquePrefix string,
|
|
29
|
+
store validationutils.StorageInterface,
|
|
30
|
+
) (validationutils.ExternalData, error) {
|
|
31
|
+
result := validationutils.ExternalData{}
|
|
32
|
+
|
|
33
|
+
{{#loadActions}}
|
|
34
|
+
{{{key}}}_value, err := loadFunction(store, uniquePrefix, "{{{key}}}")
|
|
35
|
+
if err != nil {
|
|
36
|
+
return result, fmt.Errorf("failed to load key {{{key}}}: %w", err)
|
|
37
|
+
}
|
|
38
|
+
result.{{{key}}} = {{{key}}}_value
|
|
39
|
+
{{/loadActions}}
|
|
40
|
+
|
|
41
|
+
fmt.Printf("Loaded external data for action {{action}}: %+v\n", result)
|
|
42
|
+
return result, nil
|
|
43
|
+
}
|
|
44
|
+
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Code generated by github.com/ONDC-Official/automation-validation-compiler, DO NOT EDIT.
|
|
2
|
+
package storageutils
|
|
3
|
+
|
|
4
|
+
import (
|
|
5
|
+
"fmt"
|
|
6
|
+
"validationpkg/validationutils"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
// Perform{{functionName}}Save saves validation state data for a given action
|
|
10
|
+
//
|
|
11
|
+
// Parameters:
|
|
12
|
+
// - action: The action name
|
|
13
|
+
// - uniquePrefix: Unique namespace prefix
|
|
14
|
+
// - payload: The payload data to extract and save
|
|
15
|
+
// - store: Storage interface implementation
|
|
16
|
+
// - config: Optional storage configuration (nil uses defaults)
|
|
17
|
+
//
|
|
18
|
+
// Returns error if the action is not found or save fails
|
|
19
|
+
func Perform{{functionName}}Save(
|
|
20
|
+
action string,
|
|
21
|
+
uniquePrefix string,
|
|
22
|
+
payload interface{},
|
|
23
|
+
store validationutils.StorageInterface,
|
|
24
|
+
config *StorageConfig,
|
|
25
|
+
) error {
|
|
26
|
+
// Set default config if not provided
|
|
27
|
+
completeConfig := StorageConfig{
|
|
28
|
+
RetryAttempts: 3,
|
|
29
|
+
RetryDelayMs: 1000,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if config != nil {
|
|
33
|
+
if config.RetryAttempts > 0 {
|
|
34
|
+
completeConfig.RetryAttempts = config.RetryAttempts
|
|
35
|
+
}
|
|
36
|
+
if config.RetryDelayMs > 0 {
|
|
37
|
+
completeConfig.RetryDelayMs = config.RetryDelayMs
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
switch action {
|
|
42
|
+
{{#actions}}
|
|
43
|
+
case "{{action}}":
|
|
44
|
+
return Store_{{{action}}}(uniquePrefix, payload, store, completeConfig)
|
|
45
|
+
{{/actions}}
|
|
46
|
+
default:
|
|
47
|
+
return fmt.Errorf("action not found: %s", action)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Perform{{functionName}}Load loads validation state data for a given action
|
|
52
|
+
//
|
|
53
|
+
// Parameters:
|
|
54
|
+
// - action: The action name
|
|
55
|
+
// - uniquePrefix: Unique namespace prefix
|
|
56
|
+
// - store: Storage interface implementation
|
|
57
|
+
//
|
|
58
|
+
// Returns ExternalData with loaded values and error if action not found
|
|
59
|
+
func Perform{{functionName}}Load(
|
|
60
|
+
action string,
|
|
61
|
+
uniquePrefix string,
|
|
62
|
+
store validationutils.StorageInterface,
|
|
63
|
+
) (validationutils.ExternalData, error) {
|
|
64
|
+
switch action {
|
|
65
|
+
{{#actions}}
|
|
66
|
+
case "{{action}}":
|
|
67
|
+
return LoadFor_{{{action}}}(uniquePrefix, store)
|
|
68
|
+
{{/actions}}
|
|
69
|
+
default:
|
|
70
|
+
return validationutils.ExternalData{}, fmt.Errorf("action not found: %s", action)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Code generated by github.com/ONDC-Official/automation-validation-compiler, DO NOT EDIT.
|
|
2
|
+
|
|
3
|
+
package storageutils
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"fmt"
|
|
7
|
+
"time"
|
|
8
|
+
"validationpkg/validationutils"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
// StorageConfig holds configuration for storage operations
|
|
12
|
+
type StorageConfig struct {
|
|
13
|
+
// RetryAttempts is the number of times to retry a failed operation
|
|
14
|
+
RetryAttempts int
|
|
15
|
+
// RetryDelayMs is the delay in milliseconds between retry attempts
|
|
16
|
+
RetryDelayMs int
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// DefaultStorageConfig returns a StorageConfig with sensible defaults
|
|
20
|
+
func DefaultStorageConfig() StorageConfig {
|
|
21
|
+
return StorageConfig{
|
|
22
|
+
RetryAttempts: 3,
|
|
23
|
+
RetryDelayMs: 100,
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// SaveData saves data to storage with retry logic
|
|
28
|
+
//
|
|
29
|
+
// Parameters:
|
|
30
|
+
// - uniquePrefix: The namespace prefix for the key
|
|
31
|
+
// - key: The key to store the data under
|
|
32
|
+
// - saveData: The string data to save
|
|
33
|
+
// - store: The storage interface implementation
|
|
34
|
+
// - config: Configuration including retry settings
|
|
35
|
+
//
|
|
36
|
+
// Returns error if all retry attempts fail
|
|
37
|
+
func SaveData(
|
|
38
|
+
uniquePrefix string,
|
|
39
|
+
key string,
|
|
40
|
+
saveData string,
|
|
41
|
+
store validationutils.StorageInterface,
|
|
42
|
+
config StorageConfig,
|
|
43
|
+
) error {
|
|
44
|
+
finalKey := key
|
|
45
|
+
retryTimes := config.RetryAttempts
|
|
46
|
+
delayMs := config.RetryDelayMs
|
|
47
|
+
attempts := 0
|
|
48
|
+
|
|
49
|
+
for attempts < retryTimes {
|
|
50
|
+
err := store.SaveKey(uniquePrefix, finalKey, saveData)
|
|
51
|
+
if err == nil {
|
|
52
|
+
return nil
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
attempts++
|
|
56
|
+
if attempts >= retryTimes {
|
|
57
|
+
return fmt.Errorf("failed to save data after %d attempts: %w", retryTimes, err)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
time.Sleep(time.Duration(delayMs) * time.Millisecond)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return nil
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// CreateKey creates a fully qualified storage key from prefix and key
|
|
67
|
+
//
|
|
68
|
+
// Parameters:
|
|
69
|
+
// - uniquePrefix: The namespace prefix
|
|
70
|
+
// - key: The key within the namespace
|
|
71
|
+
//
|
|
72
|
+
// Returns the combined key in format "prefix:key"
|
|
73
|
+
func CreateKey(uniquePrefix string, key string) string {
|
|
74
|
+
return fmt.Sprintf("%s:%s", uniquePrefix, key)
|
|
75
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Code generated by github.com/ONDC-Official/automation-validation-compiler, DO NOT EDIT.
|
|
2
|
+
|
|
3
|
+
package validationutils
|
|
4
|
+
|
|
5
|
+
// StorageInterface provides a standardized abstraction layer for storage operations
|
|
6
|
+
// that can be implemented by different storage backends (Redis, Memory, File, etc.).
|
|
7
|
+
//
|
|
8
|
+
// Implementation Notes:
|
|
9
|
+
// - Keys should be strings and values are stored as strings
|
|
10
|
+
// - Implementations should handle serialization/deserialization as needed
|
|
11
|
+
// - Prefix-based operations allow for namespacing and bulk operations
|
|
12
|
+
//
|
|
13
|
+
// Example:
|
|
14
|
+
//
|
|
15
|
+
// type RedisStorage struct {
|
|
16
|
+
// client *redis.Client
|
|
17
|
+
// }
|
|
18
|
+
//
|
|
19
|
+
// func (r *RedisStorage) SaveKey(uniquePrefix, key, value string) error {
|
|
20
|
+
// fullKey := fmt.Sprintf("%s:%s", uniquePrefix, key)
|
|
21
|
+
// return r.client.Set(ctx, fullKey, value, 0).Err()
|
|
22
|
+
// }
|
|
23
|
+
//
|
|
24
|
+
// storage := &RedisStorage{client: redisClient}
|
|
25
|
+
// userData, _ := json.Marshal(user)
|
|
26
|
+
// storage.SaveKey("app1", "user:123", string(userData))
|
|
27
|
+
type StorageInterface interface {
|
|
28
|
+
// SaveKey saves a key-value pair to storage with a unique prefix for namespacing.
|
|
29
|
+
//
|
|
30
|
+
// Parameters:
|
|
31
|
+
// - uniquePrefix: A unique identifier/namespace prefix to prevent key collisions
|
|
32
|
+
// - key: The unique identifier for the stored value within the prefix namespace
|
|
33
|
+
// - value: The string value to store
|
|
34
|
+
//
|
|
35
|
+
// Returns error if the operation fails
|
|
36
|
+
//
|
|
37
|
+
// Example:
|
|
38
|
+
// sessionData, _ := json.Marshal(session)
|
|
39
|
+
// err := storage.SaveKey("app1", "session:abc123", string(sessionData))
|
|
40
|
+
SaveKey(uniquePrefix string, key string, value string) error
|
|
41
|
+
|
|
42
|
+
// GetKey retrieves a value by its key from storage within a specific namespace.
|
|
43
|
+
//
|
|
44
|
+
// Parameters:
|
|
45
|
+
// - uniquePrefix: The unique identifier/namespace prefix used when storing
|
|
46
|
+
// - key: The unique identifier for the value to retrieve within the prefix namespace
|
|
47
|
+
//
|
|
48
|
+
// Returns the stored value and error if the key does not exist
|
|
49
|
+
//
|
|
50
|
+
// Example:
|
|
51
|
+
// sessionData, err := storage.GetKey("app1", "session:abc123")
|
|
52
|
+
// if err != nil {
|
|
53
|
+
// // handle key not found
|
|
54
|
+
// }
|
|
55
|
+
GetKey(uniquePrefix string, key string) (string, error)
|
|
56
|
+
|
|
57
|
+
// DeleteKey removes a key-value pair from storage within a specific namespace.
|
|
58
|
+
//
|
|
59
|
+
// Parameters:
|
|
60
|
+
// - uniquePrefix: The unique identifier/namespace prefix used when storing
|
|
61
|
+
// - key: The unique identifier for the value to delete within the prefix namespace
|
|
62
|
+
//
|
|
63
|
+
// Returns error if the operation fails
|
|
64
|
+
//
|
|
65
|
+
// Example:
|
|
66
|
+
// err := storage.DeleteKey("app1", "session:abc123")
|
|
67
|
+
DeleteKey(uniquePrefix string, key string) error
|
|
68
|
+
|
|
69
|
+
// ListKeys lists all keys within a specific namespace/prefix.
|
|
70
|
+
//
|
|
71
|
+
// Parameters:
|
|
72
|
+
// - uniquePrefix: The unique identifier/namespace prefix to list keys from
|
|
73
|
+
//
|
|
74
|
+
// Returns an array of keys within that namespace
|
|
75
|
+
//
|
|
76
|
+
// Example:
|
|
77
|
+
// app1Keys, err := storage.ListKeys("app1")
|
|
78
|
+
// // Returns keys stored under the "app1" namespace
|
|
79
|
+
// // e.g., []string{"session:abc123", "user:456", "config:settings"}
|
|
80
|
+
ListKeys(uniquePrefix string) ([]string, error)
|
|
81
|
+
|
|
82
|
+
// ClearStorage clears all stored data from the storage backend.
|
|
83
|
+
//
|
|
84
|
+
// WARNING: This operation is destructive and cannot be undone.
|
|
85
|
+
// Use with caution, especially in production environments.
|
|
86
|
+
//
|
|
87
|
+
// Returns error if the operation fails
|
|
88
|
+
//
|
|
89
|
+
// Example:
|
|
90
|
+
// err := storage.ClearStorage() // All data is now removed
|
|
91
|
+
ClearStorage() error
|
|
92
|
+
|
|
93
|
+
// KeyExists checks if a key exists in storage within a specific namespace.
|
|
94
|
+
//
|
|
95
|
+
// Parameters:
|
|
96
|
+
// - uniquePrefix: The unique identifier/namespace prefix to check within
|
|
97
|
+
// - key: The unique identifier to check for existence within the prefix namespace
|
|
98
|
+
//
|
|
99
|
+
// Returns true if the key exists, false otherwise
|
|
100
|
+
//
|
|
101
|
+
// Example:
|
|
102
|
+
// exists, err := storage.KeyExists("app1", "user:123")
|
|
103
|
+
// if err == nil && exists {
|
|
104
|
+
// userData, _ := storage.GetKey("app1", "user:123")
|
|
105
|
+
// }
|
|
106
|
+
KeyExists(uniquePrefix string, key string) (bool, error)
|
|
107
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Code generated by github.com/ONDC-Official/automation-validation-compiler, DO NOT EDIT.
|
|
2
|
+
|
|
3
|
+
package validationutils
|
|
4
|
+
|
|
5
|
+
// ValidationConfig holds configuration options for running validation routines.
|
|
6
|
+
type ValidationConfig struct {
|
|
7
|
+
// StateFullValidations enables stateful validations that may depend on previous data
|
|
8
|
+
StateFullValidations bool
|
|
9
|
+
// UniqueKey is an optional unique key for the validation instance
|
|
10
|
+
UniqueKey *string
|
|
11
|
+
// Store is an optional implementation of StorageInterface for persisting data across validations
|
|
12
|
+
Store StorageInterface
|
|
13
|
+
// OnlyInvalid if true, only invalid results will be returned
|
|
14
|
+
OnlyInvalid bool
|
|
15
|
+
// HideParentErrors hides nested error details if set to true
|
|
16
|
+
HideParentErrors bool
|
|
17
|
+
// Debug enables debug mode for additional diagnostic information
|
|
18
|
+
Debug bool
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// ValidationOutput represents the output of a validation run.
|
|
22
|
+
// Each element corresponds to a single validation test result.
|
|
23
|
+
type ValidationOutput struct {
|
|
24
|
+
// TestName is the name of the validation test
|
|
25
|
+
TestName string `json:"testName"`
|
|
26
|
+
// Valid indicates whether the test passed (true) or failed (false)
|
|
27
|
+
Valid bool `json:"valid"`
|
|
28
|
+
// Code is a numeric code representing the result or error type
|
|
29
|
+
Code int `json:"code"`
|
|
30
|
+
// Description provides additional details about the test result
|
|
31
|
+
Description string `json:"description,omitempty"`
|
|
32
|
+
// DebugInfo contains diagnostic information useful for debugging
|
|
33
|
+
DebugInfo *DebugInfo `json:"_debugInfo,omitempty"`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// DebugInfo contains diagnostic information for validation results
|
|
37
|
+
type DebugInfo struct {
|
|
38
|
+
// FedConfig is the configuration used to generate the validation
|
|
39
|
+
FedConfig interface{} `json:"fedConfig"`
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ExternalData holds external data references for validation
|
|
43
|
+
type ExternalData struct {
|
|
44
|
+
Self interface{} `json:"_SELF,omitempty"`
|
|
45
|
+
{{#externalData}}
|
|
46
|
+
{{name}} []string `json:"{{name}},omitempty"`
|
|
47
|
+
{{/externalData}}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ValidationInput represents the input data for validation functions
|
|
51
|
+
type ValidationInput struct {
|
|
52
|
+
Payload interface{}
|
|
53
|
+
ExternalData ExternalData
|
|
54
|
+
Config ValidationConfig
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// TestFunction is a function type that takes ValidationInput and returns a slice of ValidationOutput
|
|
58
|
+
type TestFunction func(input ValidationInput) ([]ValidationOutput, error)
|
|
59
|
+
|
|
60
|
+
// TestFunctionArray is a slice of test functions
|
|
61
|
+
type TestFunctionArray []TestFunction
|
|
62
|
+
|