@voxgig/sdkgen 0.26.1 → 0.28.0

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.
Files changed (157) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/cmp/Feature.js +11 -9
  3. package/dist/cmp/Feature.js.map +1 -1
  4. package/dist/cmp/Main.js +6 -2
  5. package/dist/cmp/Main.js.map +1 -1
  6. package/model/sdkgen.jsonic +1 -1
  7. package/package.json +3 -3
  8. package/project/.sdk/model/feature/log.jsonic +1 -1
  9. package/project/.sdk/model/feature/test.jsonic +1 -1
  10. package/project/.sdk/model/target/go.jsonic +19 -4
  11. package/project/.sdk/model/target/ts.jsonic +3 -3
  12. package/project/.sdk/src/cmp/go/Config_go.ts +119 -0
  13. package/project/.sdk/src/cmp/go/EntityOperation_go.ts +48 -0
  14. package/project/.sdk/src/cmp/go/Entity_go.ts +67 -0
  15. package/project/.sdk/src/cmp/go/MainEntity_go.ts +22 -0
  16. package/project/.sdk/src/cmp/go/Main_go.ts +209 -0
  17. package/project/.sdk/src/cmp/go/Package_go.ts +89 -0
  18. package/project/.sdk/src/cmp/go/TestDirect_go.ts +373 -0
  19. package/project/.sdk/src/cmp/go/TestEntity_go.ts +341 -0
  20. package/project/.sdk/src/cmp/go/Test_go.ts +37 -0
  21. package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +146 -0
  22. package/project/.sdk/src/cmp/go/fragment/EntityCreateOp.fragment.go +35 -0
  23. package/project/.sdk/src/cmp/go/fragment/EntityListOp.fragment.go +26 -0
  24. package/project/.sdk/src/cmp/go/fragment/EntityLoadOp.fragment.go +38 -0
  25. package/project/.sdk/src/cmp/go/fragment/EntityRemoveOp.fragment.go +38 -0
  26. package/project/.sdk/src/cmp/go/fragment/EntityUpdateOp.fragment.go +38 -0
  27. package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +250 -0
  28. package/project/.sdk/src/cmp/go/fragment/SdkError.fragment.go +22 -0
  29. package/project/.sdk/src/cmp/go/tsconfig.json +15 -0
  30. package/project/.sdk/src/cmp/go/utility_go.ts +88 -0
  31. package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +6 -6
  32. package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +6 -6
  33. package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +6 -6
  34. package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +6 -6
  35. package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +6 -6
  36. package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +85 -1
  37. package/project/.sdk/src/cmp/ts/EntityOperation_ts.ts +1 -1
  38. package/project/.sdk/src/cmp/ts/Main_ts.ts +4 -4
  39. package/project/.sdk/src/cmp/ts/SdkError_ts.ts +42 -0
  40. package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +288 -0
  41. package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +14 -6
  42. package/project/.sdk/src/cmp/ts/Test_ts.ts +2 -0
  43. package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +30 -0
  44. package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +12 -12
  45. package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +12 -12
  46. package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +12 -12
  47. package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +13 -13
  48. package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +12 -12
  49. package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +102 -6
  50. package/project/.sdk/src/cmp/ts/fragment/SdkError.fragment.ts +25 -0
  51. package/project/.sdk/tm/go/Makefile +10 -0
  52. package/project/.sdk/tm/go/core/context.go +267 -0
  53. package/project/.sdk/tm/go/core/control.go +7 -0
  54. package/project/.sdk/tm/go/core/error.go +25 -0
  55. package/project/.sdk/tm/go/core/helpers.go +33 -0
  56. package/project/.sdk/tm/go/core/operation.go +61 -0
  57. package/project/.sdk/tm/go/core/response.go +55 -0
  58. package/project/.sdk/tm/go/core/result.go +73 -0
  59. package/project/.sdk/tm/go/core/spec.go +97 -0
  60. package/project/.sdk/tm/go/core/target.go +102 -0
  61. package/project/.sdk/tm/go/core/types.go +44 -0
  62. package/project/.sdk/tm/go/core/utility_type.go +54 -0
  63. package/project/.sdk/tm/go/feature/base_feature.go +40 -0
  64. package/project/.sdk/tm/go/feature/test_feature.go +196 -0
  65. package/project/.sdk/tm/go/src/feature/README.md +1 -0
  66. package/project/.sdk/tm/go/src/feature/base/.gitkeep +0 -0
  67. package/project/.sdk/tm/go/src/feature/test/.gitkeep +0 -0
  68. package/project/.sdk/tm/go/test/custom_utility_test.go +80 -0
  69. package/project/.sdk/tm/go/test/exists_test.go +16 -0
  70. package/project/.sdk/tm/go/test/primary_utility_test.go +899 -0
  71. package/project/.sdk/tm/go/test/runner_test.go +428 -0
  72. package/project/.sdk/tm/go/test/struct_runner_test.go +1094 -0
  73. package/project/.sdk/tm/go/test/struct_utility_test.go +1423 -0
  74. package/project/.sdk/tm/go/utility/clean.go +7 -0
  75. package/project/.sdk/tm/go/utility/done.go +20 -0
  76. package/project/.sdk/tm/go/utility/feature_add.go +10 -0
  77. package/project/.sdk/tm/go/utility/feature_hook.go +30 -0
  78. package/project/.sdk/tm/go/utility/feature_init.go +30 -0
  79. package/project/.sdk/tm/go/utility/fetcher.go +102 -0
  80. package/project/.sdk/tm/go/utility/make_context.go +7 -0
  81. package/project/.sdk/tm/go/utility/make_error.go +69 -0
  82. package/project/.sdk/tm/go/utility/make_fetch_def.go +44 -0
  83. package/project/.sdk/tm/go/utility/make_options.go +130 -0
  84. package/project/.sdk/tm/go/utility/make_request.go +59 -0
  85. package/project/.sdk/tm/go/utility/make_response.go +46 -0
  86. package/project/.sdk/tm/go/utility/make_result.go +55 -0
  87. package/project/.sdk/tm/go/utility/make_spec.go +68 -0
  88. package/project/.sdk/tm/go/utility/make_target.go +95 -0
  89. package/project/.sdk/tm/go/utility/make_url.go +41 -0
  90. package/project/.sdk/tm/go/utility/param.go +66 -0
  91. package/project/.sdk/tm/go/utility/prepare_auth.go +40 -0
  92. package/project/.sdk/tm/go/utility/prepare_body.go +14 -0
  93. package/project/.sdk/tm/go/utility/prepare_headers.go +22 -0
  94. package/project/.sdk/tm/go/utility/prepare_method.go +21 -0
  95. package/project/.sdk/tm/go/utility/prepare_params.go +41 -0
  96. package/project/.sdk/tm/go/utility/prepare_path.go +21 -0
  97. package/project/.sdk/tm/go/utility/prepare_query.go +47 -0
  98. package/project/.sdk/tm/go/utility/register.go +39 -0
  99. package/project/.sdk/tm/go/utility/result_basic.go +31 -0
  100. package/project/.sdk/tm/go/utility/result_body.go +17 -0
  101. package/project/.sdk/tm/go/utility/result_headers.go +22 -0
  102. package/project/.sdk/tm/go/utility/struct/go.mod +3 -0
  103. package/project/.sdk/tm/go/utility/struct/voxgigstruct.go +4891 -0
  104. package/project/.sdk/tm/go/utility/transform_request.go +32 -0
  105. package/project/.sdk/tm/go/utility/transform_response.go +45 -0
  106. package/project/.sdk/tm/js/src/feature/log/LogFeature.js +2 -2
  107. package/project/.sdk/tm/ts/src/Context.ts +144 -0
  108. package/project/.sdk/tm/ts/src/Control.ts +20 -0
  109. package/project/.sdk/tm/ts/src/Operation.ts +24 -0
  110. package/project/.sdk/tm/ts/src/Response.ts +26 -0
  111. package/project/.sdk/tm/ts/src/Result.ts +30 -0
  112. package/project/.sdk/tm/ts/src/Spec.ts +40 -0
  113. package/project/.sdk/tm/ts/src/Target.ts +36 -0
  114. package/project/.sdk/tm/ts/src/feature/base/BaseFeature.ts +1 -1
  115. package/project/.sdk/tm/ts/src/feature/log/LogFeature.ts +2 -2
  116. package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +7 -7
  117. package/project/.sdk/tm/ts/src/types.ts +15 -205
  118. package/project/.sdk/tm/ts/src/utility/DoneUtility.ts +2 -3
  119. package/project/.sdk/tm/ts/src/utility/{AddfeatureUtility.ts → FeatureAddUtility.ts} +2 -2
  120. package/project/.sdk/tm/ts/src/utility/{InitfeatureUtility.ts → FeatureInitUtility.ts} +2 -2
  121. package/project/.sdk/tm/ts/src/utility/FetcherUtility.ts +5 -3
  122. package/project/.sdk/tm/ts/src/utility/{ErrorUtility.ts → MakeErrorUtility.ts} +4 -4
  123. package/project/.sdk/tm/ts/src/utility/MakeFetchDefUtility.ts +46 -0
  124. package/project/.sdk/tm/ts/src/utility/{OptionsUtility.ts → MakeOptionsUtility.ts} +10 -7
  125. package/project/.sdk/tm/ts/src/utility/MakeRequestUtility.ts +66 -0
  126. package/project/.sdk/tm/ts/src/utility/MakeResponseUtility.ts +61 -0
  127. package/project/.sdk/tm/ts/src/utility/{ResultUtility.ts → MakeResultUtility.ts} +6 -6
  128. package/project/.sdk/tm/ts/src/utility/MakeSpecUtility.ts +61 -0
  129. package/project/.sdk/tm/ts/src/utility/{SelectionUtility.ts → MakeTargetUtility.ts} +22 -24
  130. package/project/.sdk/tm/ts/src/utility/{FullurlUtility.ts → MakeUrlUtility.ts} +7 -8
  131. package/project/.sdk/tm/ts/src/utility/{FindparamUtility.ts → ParamUtility.ts} +21 -8
  132. package/project/.sdk/tm/ts/src/utility/{AuthUtility.ts → PrepareAuthUtility.ts} +4 -4
  133. package/project/.sdk/tm/ts/src/utility/{BodyUtility.ts → PrepareBodyUtility.ts} +7 -7
  134. package/project/.sdk/tm/ts/src/utility/{HeadersUtility.ts → PrepareHeadersUtility.ts} +5 -7
  135. package/project/.sdk/tm/ts/src/utility/{MethodUtility.ts → PrepareMethodUtility.ts} +6 -6
  136. package/project/.sdk/tm/ts/src/utility/PrepareParamsUtility.ts +37 -0
  137. package/project/.sdk/tm/ts/src/utility/PreparePathUtility.ts +3 -4
  138. package/project/.sdk/tm/ts/src/utility/PrepareQueryUtility.ts +30 -0
  139. package/project/.sdk/tm/ts/src/utility/{ResbasicUtility.ts → ResultBasicUtility.ts} +11 -6
  140. package/project/.sdk/tm/ts/src/utility/{ResbodyUtility.ts → ResultBodyUtility.ts} +4 -3
  141. package/project/.sdk/tm/ts/src/utility/{ResheadersUtility.ts → ResultHeadersUtility.ts} +4 -3
  142. package/project/.sdk/tm/ts/src/utility/{ReqformUtility.ts → TransformRequestUtility.ts} +9 -7
  143. package/project/.sdk/tm/ts/src/utility/{ResformUtility.ts → TransformResponseUtility.ts} +10 -7
  144. package/project/.sdk/tm/ts/src/utility/Utility.ts +47 -62
  145. package/project/.sdk/tm/ts/test/runner.ts +25 -4
  146. package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +386 -175
  147. package/src/cmp/Feature.ts +11 -9
  148. package/src/cmp/Main.ts +8 -2
  149. package/project/.sdk/tm/ts/src/utility/JoinurlUtility.ts +0 -15
  150. package/project/.sdk/tm/ts/src/utility/OperationUtility.ts +0 -23
  151. package/project/.sdk/tm/ts/src/utility/ParamsUtility.ts +0 -37
  152. package/project/.sdk/tm/ts/src/utility/QueryUtility.ts +0 -27
  153. package/project/.sdk/tm/ts/src/utility/RequestUtility.ts +0 -83
  154. package/project/.sdk/tm/ts/src/utility/ResponseUtility.ts +0 -61
  155. package/project/.sdk/tm/ts/src/utility/SpecUtility.ts +0 -68
  156. /package/project/.sdk/tm/ts/src/utility/{FeaturehookUtility.ts → FeatureHookUtility.ts} +0 -0
  157. /package/project/.sdk/tm/ts/src/utility/{ContextUtility.ts → MakeContextUtility.ts} +0 -0
@@ -0,0 +1,428 @@
1
+ package sdktest
2
+
3
+ import (
4
+ "encoding/json"
5
+ "fmt"
6
+ "os"
7
+ "path/filepath"
8
+ "reflect"
9
+ "runtime"
10
+ "strings"
11
+ "sync"
12
+ "testing"
13
+
14
+ sdk "GOMODULE"
15
+
16
+ vs "github.com/voxgig/struct"
17
+ )
18
+
19
+ var envLocalOnce sync.Once
20
+
21
+ func loadEnvLocal() {
22
+ envLocalOnce.Do(func() {
23
+ _, filename, _, _ := runtime.Caller(0)
24
+ dir := filepath.Dir(filename)
25
+ envFile := filepath.Join(dir, "..", "..", ".env.local")
26
+
27
+ data, err := os.ReadFile(envFile)
28
+ if err != nil {
29
+ return
30
+ }
31
+ for _, line := range strings.Split(string(data), "\n") {
32
+ line = strings.TrimSpace(line)
33
+ if line == "" || strings.HasPrefix(line, "#") {
34
+ continue
35
+ }
36
+ parts := strings.SplitN(line, "=", 2)
37
+ if len(parts) == 2 {
38
+ key := strings.TrimSpace(parts[0])
39
+ val := strings.TrimSpace(parts[1])
40
+ os.Setenv(key, val)
41
+ }
42
+ }
43
+ })
44
+ }
45
+
46
+ func envOverride(m map[string]any) map[string]any {
47
+ if os.Getenv("PROJECTNAME_TEST_LIVE") == "TRUE" ||
48
+ os.Getenv("PROJECTNAME_TEST_OVERRIDE") == "TRUE" {
49
+ for key := range m {
50
+ envval := os.Getenv(key)
51
+ if envval != "" {
52
+ envval = strings.TrimSpace(envval)
53
+ if strings.HasPrefix(envval, "{") {
54
+ var parsed any
55
+ if err := json.Unmarshal([]byte(envval), &parsed); err == nil {
56
+ m[key] = parsed
57
+ continue
58
+ }
59
+ }
60
+ m[key] = envval
61
+ }
62
+ }
63
+ }
64
+
65
+ if explain := os.Getenv("PROJECTNAME_TEST_EXPLAIN"); explain != "" {
66
+ m["PROJECTNAME_TEST_EXPLAIN"] = explain
67
+ }
68
+
69
+ return m
70
+ }
71
+
72
+ type entityTestSetup struct {
73
+ client *sdk.ProjectNameSDK
74
+ data map[string]any
75
+ idmap map[string]any
76
+ env map[string]any
77
+ explain bool
78
+ now int64
79
+ }
80
+
81
+ var cachedTestSpec map[string]any
82
+
83
+ func loadTestSpec(t *testing.T) map[string]any {
84
+ t.Helper()
85
+ if cachedTestSpec != nil {
86
+ return cachedTestSpec
87
+ }
88
+ data, err := os.ReadFile("../../.sdk/test/test.json")
89
+ if err != nil {
90
+ t.Fatalf("Failed to load test.json: %v", err)
91
+ }
92
+ var spec map[string]any
93
+ if err := json.Unmarshal(data, &spec); err != nil {
94
+ t.Fatalf("Failed to parse test.json: %v", err)
95
+ }
96
+ cachedTestSpec = spec
97
+ return spec
98
+ }
99
+
100
+ func getSpec(spec map[string]any, keys ...string) map[string]any {
101
+ var cur any = spec
102
+ for _, key := range keys {
103
+ if m, ok := cur.(map[string]any); ok {
104
+ cur = m[key]
105
+ } else {
106
+ return nil
107
+ }
108
+ }
109
+ if m, ok := cur.(map[string]any); ok {
110
+ return m
111
+ }
112
+ return nil
113
+ }
114
+
115
+ type RunSubject func(entry map[string]any) (any, error)
116
+
117
+ func runset(t *testing.T, testspec map[string]any, subject RunSubject) {
118
+ t.Helper()
119
+ set, ok := testspec["set"].([]any)
120
+ if !ok {
121
+ return
122
+ }
123
+
124
+ for i, e := range set {
125
+ entry, ok := e.(map[string]any)
126
+ if !ok {
127
+ continue
128
+ }
129
+
130
+ mark := ""
131
+ if m := entry["mark"]; m != nil {
132
+ mark = fmt.Sprintf(" (mark=%v)", m)
133
+ }
134
+
135
+ result, err := subject(entry)
136
+
137
+ expectedErr := entry["err"]
138
+
139
+ if err != nil {
140
+ if expectedErr != nil {
141
+ errMsg := err.Error()
142
+ if expStr, ok := expectedErr.(string); ok {
143
+ if !strings.Contains(errMsg, expStr) {
144
+ t.Errorf("entry %d%s: error mismatch: got %q, want contains %q",
145
+ i, mark, errMsg, expStr)
146
+ }
147
+ } else if expBool, ok := expectedErr.(bool); ok && expBool {
148
+ // err: true means any error is acceptable
149
+ }
150
+ if matchSpec, ok := entry["match"].(map[string]any); ok {
151
+ resultMap := map[string]any{
152
+ "in": entry["in"],
153
+ "out": jsonNormalize(result),
154
+ "err": map[string]any{"message": err.Error()},
155
+ }
156
+ matchDeep(t, i, mark, matchSpec, resultMap, "")
157
+ }
158
+ continue
159
+ }
160
+ t.Errorf("entry %d%s: unexpected error: %v", i, mark, err)
161
+ continue
162
+ }
163
+
164
+ if expectedErr != nil {
165
+ t.Errorf("entry %d%s: expected error containing %q but got result: %v",
166
+ i, mark, expectedErr, jsonStr(result))
167
+ continue
168
+ }
169
+
170
+ matched := false
171
+ if matchSpec, ok := entry["match"].(map[string]any); ok {
172
+ resultMap := map[string]any{
173
+ "in": entry["in"],
174
+ "out": jsonNormalize(result),
175
+ }
176
+ if args := entry["args"]; args != nil {
177
+ resultMap["args"] = args
178
+ } else if entry["in"] != nil {
179
+ resultMap["args"] = []any{entry["in"]}
180
+ }
181
+ if ctxData := entry["ctx"]; ctxData != nil {
182
+ resultMap["ctx"] = ctxData
183
+ }
184
+ matchDeep(t, i, mark, matchSpec, resultMap, "")
185
+ matched = true
186
+ }
187
+
188
+ expectedOut := entry["out"]
189
+ if expectedOut == nil && matched {
190
+ continue
191
+ }
192
+ if expectedOut != nil {
193
+ normResult := jsonNormalize(result)
194
+ normExpected := jsonNormalize(expectedOut)
195
+ if !reflect.DeepEqual(normResult, normExpected) {
196
+ t.Errorf("entry %d%s: output mismatch:\n got: %v\n want: %v",
197
+ i, mark, jsonStr(normResult), jsonStr(normExpected))
198
+ }
199
+ }
200
+ }
201
+ }
202
+
203
+ func jsonNormalize(val any) any {
204
+ if val == nil {
205
+ return nil
206
+ }
207
+ j, err := json.Marshal(val)
208
+ if err != nil {
209
+ return val
210
+ }
211
+ var out any
212
+ json.Unmarshal(j, &out)
213
+ return out
214
+ }
215
+
216
+ func jsonStr(val any) string {
217
+ j, err := json.Marshal(val)
218
+ if err != nil {
219
+ return fmt.Sprintf("%v", val)
220
+ }
221
+ return string(j)
222
+ }
223
+
224
+ func matchDeep(t *testing.T, entryIdx int, mark string, check any, base any, path string) {
225
+ t.Helper()
226
+
227
+ if check == nil {
228
+ return
229
+ }
230
+
231
+ checkMap, isMap := check.(map[string]any)
232
+ checkList, isList := check.([]any)
233
+
234
+ if isMap {
235
+ for key, checkVal := range checkMap {
236
+ childPath := path + "." + key
237
+ var baseVal any
238
+ if baseMap, ok := base.(map[string]any); ok {
239
+ baseVal = baseMap[key]
240
+ }
241
+ matchDeep(t, entryIdx, mark, checkVal, baseVal, childPath)
242
+ }
243
+ } else if isList {
244
+ for i, checkVal := range checkList {
245
+ childPath := fmt.Sprintf("%s[%d]", path, i)
246
+ var baseVal any
247
+ if baseList, ok := base.([]any); ok && i < len(baseList) {
248
+ baseVal = baseList[i]
249
+ }
250
+ matchDeep(t, entryIdx, mark, checkVal, baseVal, childPath)
251
+ }
252
+ } else {
253
+ checkStr, isStr := check.(string)
254
+ if isStr && checkStr == "__EXISTS__" {
255
+ if base == nil {
256
+ t.Errorf("entry %d%s: match %s: expected value to exist but got nil",
257
+ entryIdx, mark, path)
258
+ }
259
+ return
260
+ }
261
+ if isStr && checkStr == "__UNDEF__" {
262
+ if base != nil {
263
+ t.Errorf("entry %d%s: match %s: expected nil but got %v",
264
+ entryIdx, mark, path, base)
265
+ }
266
+ return
267
+ }
268
+
269
+ normCheck := jsonNormalize(check)
270
+ normBase := jsonNormalize(base)
271
+
272
+ if !reflect.DeepEqual(normCheck, normBase) {
273
+ if isStr && checkStr != "" {
274
+ baseStr := vs.Stringify(base)
275
+ if strings.Contains(strings.ToLower(baseStr), strings.ToLower(checkStr)) {
276
+ return
277
+ }
278
+ }
279
+ t.Errorf("entry %d%s: match %s: got %v, want %v",
280
+ entryIdx, mark, path, jsonStr(normBase), jsonStr(normCheck))
281
+ }
282
+ }
283
+ }
284
+
285
+ // makeCtxFromMap creates a Context from a JSON test entry's ctx or args map.
286
+ func makeCtxFromMap(ctxmap map[string]any, client *sdk.ProjectNameSDK, utility *sdk.Utility) *sdk.Context {
287
+ if ctxmap == nil {
288
+ ctxmap = map[string]any{}
289
+ }
290
+
291
+ ctx := sdk.NewContext(ctxmap, nil)
292
+
293
+ if client != nil {
294
+ ctx.Client = client
295
+ ctx.Utility = utility
296
+ }
297
+ if ctx.Options == nil && client != nil {
298
+ ctx.Options = client.OptionsMap()
299
+ }
300
+
301
+ // Handle spec from JSON map (NewContext expects *Spec, but JSON gives map)
302
+ if specMap, ok := ctxmap["spec"].(map[string]any); ok {
303
+ ctx.Spec = sdk.NewSpec(specMap)
304
+ }
305
+
306
+ // Handle result from JSON map
307
+ if resMap, ok := ctxmap["result"].(map[string]any); ok {
308
+ ctx.Result = sdk.NewResult(resMap)
309
+ if errMap, ok := resMap["err"].(map[string]any); ok {
310
+ if msg, ok := errMap["message"].(string); ok {
311
+ ctx.Result.Err = &sdk.ProjectNameError{Msg: msg}
312
+ }
313
+ }
314
+ }
315
+
316
+ // Handle response from JSON map
317
+ if respMap, ok := ctxmap["response"].(map[string]any); ok {
318
+ ctx.Response = sdk.NewResponse(respMap)
319
+ if body := respMap["body"]; body != nil {
320
+ bodyCopy := body
321
+ ctx.Response.JsonFunc = func() any { return bodyCopy }
322
+ }
323
+ if headers, ok := respMap["headers"].(map[string]any); ok {
324
+ lowerHeaders := map[string]any{}
325
+ for k, v := range headers {
326
+ lowerHeaders[strings.ToLower(k)] = v
327
+ }
328
+ ctx.Response.Headers = lowerHeaders
329
+ }
330
+ }
331
+
332
+ return ctx
333
+ }
334
+
335
+ func fixctx(ctx *sdk.Context, client *sdk.ProjectNameSDK) {
336
+ if ctx != nil && ctx.Client != nil && ctx.Options == nil {
337
+ ctx.Options = ctx.Client.OptionsMap()
338
+ }
339
+ }
340
+
341
+ // errFromMap creates an error from a JSON map like {"message": "...", "code": "..."}
342
+ func errFromMap(m map[string]any) error {
343
+ if m == nil {
344
+ return nil
345
+ }
346
+ msg, _ := m["message"].(string)
347
+ if msg == "" {
348
+ return nil
349
+ }
350
+ code, _ := m["code"].(string)
351
+ return &sdk.ProjectNameError{Msg: msg, Code: code}
352
+ }
353
+
354
+ // ctxToMatchMap converts a Context to a map suitable for match comparison.
355
+ func ctxToMatchMap(ctx *sdk.Context) map[string]any {
356
+ m := map[string]any{}
357
+
358
+ if ctx.Spec != nil {
359
+ spec := map[string]any{
360
+ "base": ctx.Spec.Base,
361
+ "prefix": ctx.Spec.Prefix,
362
+ "suffix": ctx.Spec.Suffix,
363
+ "path": ctx.Spec.Path,
364
+ "method": ctx.Spec.Method,
365
+ "params": ctx.Spec.Params,
366
+ "query": ctx.Spec.Query,
367
+ "headers": ctx.Spec.Headers,
368
+ "step": ctx.Spec.Step,
369
+ "alias": ctx.Spec.Alias,
370
+ }
371
+ if ctx.Spec.Body != nil {
372
+ spec["body"] = ctx.Spec.Body
373
+ }
374
+ if ctx.Spec.Url != "" {
375
+ spec["url"] = ctx.Spec.Url
376
+ }
377
+ m["spec"] = spec
378
+ }
379
+
380
+ if ctx.Result != nil {
381
+ res := map[string]any{
382
+ "ok": ctx.Result.Ok,
383
+ "status": ctx.Result.Status,
384
+ "statusText": ctx.Result.StatusText,
385
+ "headers": ctx.Result.Headers,
386
+ }
387
+ if ctx.Result.Body != nil {
388
+ res["body"] = ctx.Result.Body
389
+ }
390
+ if ctx.Result.Err != nil {
391
+ res["err"] = map[string]any{
392
+ "message": ctx.Result.Err.Error(),
393
+ }
394
+ }
395
+ if ctx.Result.Resdata != nil {
396
+ res["resdata"] = ctx.Result.Resdata
397
+ }
398
+ if ctx.Result.Resmatch != nil {
399
+ res["resmatch"] = ctx.Result.Resmatch
400
+ }
401
+ m["result"] = res
402
+ }
403
+
404
+ if ctx.Response != nil {
405
+ m["response"] = "exists"
406
+ }
407
+
408
+ return m
409
+ }
410
+
411
+ // entityListToData extracts data maps from a list of Entity objects.
412
+ func entityListToData(list []any) []any {
413
+ var out []any
414
+ for _, item := range list {
415
+ if ent, ok := item.(sdk.Entity); ok {
416
+ d := ent.Data()
417
+ if dm, ok := d.(map[string]any); ok {
418
+ out = append(out, dm)
419
+ }
420
+ } else if m, ok := item.(map[string]any); ok {
421
+ out = append(out, m)
422
+ }
423
+ }
424
+ if out == nil {
425
+ out = []any{}
426
+ }
427
+ return out
428
+ }