@voxgig/sdkgen 0.26.1 → 0.30.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 +5 -5
  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,899 @@
1
+ package sdktest
2
+
3
+ import (
4
+ "strings"
5
+ "testing"
6
+
7
+ sdk "GOMODULE"
8
+
9
+ vs "github.com/voxgig/struct"
10
+ )
11
+
12
+ func TestPrimaryUtility(t *testing.T) {
13
+ spec := loadTestSpec(t)
14
+ primary := getSpec(spec, "primary")
15
+ if primary == nil {
16
+ t.Fatal("primary section not found in test.json")
17
+ }
18
+
19
+ client := sdk.TestSDK(nil, nil)
20
+ utility := client.GetUtility()
21
+
22
+ t.Run("exists", func(t *testing.T) {
23
+ if utility.Clean == nil {
24
+ t.Error("Clean should not be nil")
25
+ }
26
+ if utility.Done == nil {
27
+ t.Error("Done should not be nil")
28
+ }
29
+ if utility.MakeError == nil {
30
+ t.Error("MakeError should not be nil")
31
+ }
32
+ if utility.FeatureAdd == nil {
33
+ t.Error("FeatureAdd should not be nil")
34
+ }
35
+ if utility.FeatureHook == nil {
36
+ t.Error("FeatureHook should not be nil")
37
+ }
38
+ if utility.FeatureInit == nil {
39
+ t.Error("FeatureInit should not be nil")
40
+ }
41
+ if utility.Fetcher == nil {
42
+ t.Error("Fetcher should not be nil")
43
+ }
44
+ if utility.MakeFetchDef == nil {
45
+ t.Error("MakeFetchDef should not be nil")
46
+ }
47
+ if utility.MakeContext == nil {
48
+ t.Error("MakeContext should not be nil")
49
+ }
50
+ if utility.MakeOptions == nil {
51
+ t.Error("MakeOptions should not be nil")
52
+ }
53
+ if utility.MakeRequest == nil {
54
+ t.Error("MakeRequest should not be nil")
55
+ }
56
+ if utility.MakeResponse == nil {
57
+ t.Error("MakeResponse should not be nil")
58
+ }
59
+ if utility.MakeResult == nil {
60
+ t.Error("MakeResult should not be nil")
61
+ }
62
+ if utility.MakeTarget == nil {
63
+ t.Error("MakeTarget should not be nil")
64
+ }
65
+ if utility.MakeSpec == nil {
66
+ t.Error("MakeSpec should not be nil")
67
+ }
68
+ if utility.MakeUrl == nil {
69
+ t.Error("MakeUrl should not be nil")
70
+ }
71
+ if utility.Param == nil {
72
+ t.Error("Param should not be nil")
73
+ }
74
+ if utility.PrepareAuth == nil {
75
+ t.Error("PrepareAuth should not be nil")
76
+ }
77
+ if utility.PrepareBody == nil {
78
+ t.Error("PrepareBody should not be nil")
79
+ }
80
+ if utility.PrepareHeaders == nil {
81
+ t.Error("PrepareHeaders should not be nil")
82
+ }
83
+ if utility.PrepareMethod == nil {
84
+ t.Error("PrepareMethod should not be nil")
85
+ }
86
+ if utility.PrepareParams == nil {
87
+ t.Error("PrepareParams should not be nil")
88
+ }
89
+ if utility.PreparePath == nil {
90
+ t.Error("PreparePath should not be nil")
91
+ }
92
+ if utility.PrepareQuery == nil {
93
+ t.Error("PrepareQuery should not be nil")
94
+ }
95
+ if utility.ResultBasic == nil {
96
+ t.Error("ResultBasic should not be nil")
97
+ }
98
+ if utility.ResultBody == nil {
99
+ t.Error("ResultBody should not be nil")
100
+ }
101
+ if utility.ResultHeaders == nil {
102
+ t.Error("ResultHeaders should not be nil")
103
+ }
104
+ if utility.TransformRequest == nil {
105
+ t.Error("TransformRequest should not be nil")
106
+ }
107
+ if utility.TransformResponse == nil {
108
+ t.Error("TransformResponse should not be nil")
109
+ }
110
+ })
111
+
112
+ t.Run("clean-basic", func(t *testing.T) {
113
+ ctx := makeTestCtx(client, utility, nil)
114
+ val := map[string]any{"key": "secret123", "name": "test"}
115
+ cleaned := utility.Clean(ctx, val)
116
+ if cleaned == nil {
117
+ t.Error("cleaned should not be nil")
118
+ }
119
+ })
120
+
121
+ t.Run("done-basic", func(t *testing.T) {
122
+ runset(t, getSpec(primary, "done", "basic"), func(entry map[string]any) (any, error) {
123
+ ctxmap, _ := entry["ctx"].(map[string]any)
124
+ ctx := makeCtxFromMap(ctxmap, client, utility)
125
+ fixctx(ctx, client)
126
+ return utility.Done(ctx)
127
+ })
128
+ })
129
+
130
+ t.Run("makeError-basic", func(t *testing.T) {
131
+ runset(t, getSpec(primary, "makeError", "basic"), func(entry map[string]any) (any, error) {
132
+ args, _ := entry["args"].([]any)
133
+ if len(args) == 0 {
134
+ args = []any{map[string]any{}}
135
+ }
136
+
137
+ ctxmap, _ := args[0].(map[string]any)
138
+ if ctxmap == nil {
139
+ ctxmap = map[string]any{}
140
+ }
141
+ ctx := makeCtxFromMap(ctxmap, client, utility)
142
+ fixctx(ctx, client)
143
+
144
+ var err error
145
+ if len(args) > 1 {
146
+ if errMap, ok := args[1].(map[string]any); ok {
147
+ err = errFromMap(errMap)
148
+ }
149
+ }
150
+
151
+ return utility.MakeError(ctx, err)
152
+ })
153
+ })
154
+
155
+ t.Run("makeError-no-throw", func(t *testing.T) {
156
+ ctx := makeTestFullCtx(client, utility)
157
+ f := false
158
+ ctx.Ctrl.Throw = &f
159
+ ctx.Result = sdk.NewResult(map[string]any{
160
+ "ok": false,
161
+ "resdata": map[string]any{"id": "safe01"},
162
+ })
163
+
164
+ out, err := utility.MakeError(ctx, ctx.MakeError("test_code", "test message"))
165
+ if err != nil {
166
+ t.Errorf("expected no error, got: %v", err)
167
+ }
168
+ if outMap, ok := out.(map[string]any); ok {
169
+ if outMap["id"] != "safe01" {
170
+ t.Errorf("expected id=safe01, got: %v", outMap["id"])
171
+ }
172
+ } else {
173
+ t.Errorf("expected map result, got: %T", out)
174
+ }
175
+ })
176
+
177
+ t.Run("featureAdd-basic", func(t *testing.T) {
178
+ ctx := makeTestCtx(client, utility, nil)
179
+ startLen := len(client.Features)
180
+
181
+ feature := sdk.NewBaseFeature()
182
+ utility.FeatureAdd(ctx, feature)
183
+
184
+ if len(client.Features) != startLen+1 {
185
+ t.Errorf("expected %d features, got %d", startLen+1, len(client.Features))
186
+ }
187
+ })
188
+
189
+ t.Run("featureHook-basic", func(t *testing.T) {
190
+ hookClient := sdk.TestSDK(nil, nil)
191
+ hookUtility := hookClient.GetUtility()
192
+ ctx := makeTestCtx(hookClient, hookUtility, nil)
193
+
194
+ called := false
195
+ hookFeature := &testHookFeature{
196
+ BaseFeature: sdk.NewBaseFeature(),
197
+ hookFn: func() { called = true },
198
+ }
199
+ hookClient.Features = []sdk.Feature{hookFeature}
200
+
201
+ hookUtility.FeatureHook(ctx, "TestHook")
202
+ if !called {
203
+ t.Error("expected TestHook to be called")
204
+ }
205
+ })
206
+
207
+ t.Run("featureInit-basic", func(t *testing.T) {
208
+ initClient := sdk.TestSDK(nil, nil)
209
+ initUtility := initClient.GetUtility()
210
+ ctx := makeTestCtx(initClient, initUtility, nil)
211
+ ctx.Options["feature"] = map[string]any{
212
+ "initfeat": map[string]any{"active": true},
213
+ }
214
+
215
+ initCalled := false
216
+ feature := &testInitFeature{
217
+ BaseFeature: sdk.NewBaseFeature(),
218
+ name: "initfeat",
219
+ active: true,
220
+ initFn: func() { initCalled = true },
221
+ }
222
+
223
+ initUtility.FeatureInit(ctx, feature)
224
+ if !initCalled {
225
+ t.Error("expected init to be called")
226
+ }
227
+ })
228
+
229
+ t.Run("featureInit-inactive", func(t *testing.T) {
230
+ initClient := sdk.TestSDK(nil, nil)
231
+ initUtility := initClient.GetUtility()
232
+ ctx := makeTestCtx(initClient, initUtility, nil)
233
+ ctx.Options["feature"] = map[string]any{
234
+ "nofeat": map[string]any{"active": false},
235
+ }
236
+
237
+ initCalled := false
238
+ feature := &testInitFeature{
239
+ BaseFeature: sdk.NewBaseFeature(),
240
+ name: "nofeat",
241
+ active: false,
242
+ initFn: func() { initCalled = true },
243
+ }
244
+
245
+ initUtility.FeatureInit(ctx, feature)
246
+ if initCalled {
247
+ t.Error("expected init NOT to be called for inactive feature")
248
+ }
249
+ })
250
+
251
+ t.Run("fetcher-live", func(t *testing.T) {
252
+ calls := []map[string]any{}
253
+ liveClient := sdk.NewProjectNameSDK(map[string]any{
254
+ "system": map[string]any{
255
+ "fetch": func(url string, fetchdef map[string]any) (map[string]any, error) {
256
+ calls = append(calls, map[string]any{"url": url, "init": fetchdef})
257
+ return map[string]any{"status": 200, "statusText": "OK"}, nil
258
+ },
259
+ },
260
+ })
261
+ liveUtility := liveClient.GetUtility()
262
+ ctx := liveUtility.MakeContext(map[string]any{
263
+ "opname": "load",
264
+ "client": liveClient,
265
+ "utility": liveUtility,
266
+ }, nil)
267
+
268
+ fetchdef := map[string]any{"method": "GET", "headers": map[string]any{}}
269
+ _, err := liveUtility.Fetcher(ctx, "http://example.com/test", fetchdef)
270
+ if err != nil {
271
+ t.Errorf("expected no error, got: %v", err)
272
+ }
273
+ if len(calls) != 1 {
274
+ t.Errorf("expected 1 call, got %d", len(calls))
275
+ }
276
+ if calls[0]["url"] != "http://example.com/test" {
277
+ t.Errorf("expected url http://example.com/test, got %v", calls[0]["url"])
278
+ }
279
+ })
280
+
281
+ t.Run("fetcher-blocked-test-mode", func(t *testing.T) {
282
+ // Create a live SDK then set mode to test (not using TestSDK, which installs test feature)
283
+ blockedClient := sdk.NewProjectNameSDK(map[string]any{
284
+ "system": map[string]any{
285
+ "fetch": func(url string, fetchdef map[string]any) (map[string]any, error) {
286
+ return map[string]any{}, nil
287
+ },
288
+ },
289
+ })
290
+ blockedClient.Mode = "test"
291
+
292
+ blockedUtility := blockedClient.GetUtility()
293
+ ctx := blockedUtility.MakeContext(map[string]any{
294
+ "opname": "load",
295
+ "client": blockedClient,
296
+ "utility": blockedUtility,
297
+ }, nil)
298
+
299
+ fetchdef := map[string]any{"method": "GET", "headers": map[string]any{}}
300
+ _, err := blockedUtility.Fetcher(ctx, "http://example.com/test", fetchdef)
301
+ if err == nil {
302
+ t.Error("expected error for test mode fetch")
303
+ } else if !strings.Contains(err.Error(), "blocked") {
304
+ t.Errorf("expected error containing 'blocked', got: %v", err)
305
+ }
306
+ })
307
+
308
+ t.Run("makeContext-basic", func(t *testing.T) {
309
+ runset(t, getSpec(primary, "makeContext", "basic"), func(entry map[string]any) (any, error) {
310
+ in := entry["in"]
311
+ if inMap, ok := in.(map[string]any); ok {
312
+ ctx := utility.MakeContext(inMap, nil)
313
+ out := map[string]any{
314
+ "id": ctx.Id,
315
+ }
316
+ if ctx.Op != nil {
317
+ out["op"] = map[string]any{
318
+ "name": ctx.Op.Name,
319
+ "input": ctx.Op.Input,
320
+ }
321
+ }
322
+ return out, nil
323
+ }
324
+ return nil, nil
325
+ })
326
+ })
327
+
328
+ t.Run("makeFetchDef-basic", func(t *testing.T) {
329
+ ctx := makeTestFullCtx(client, utility)
330
+ ctx.Spec = sdk.NewSpec(map[string]any{
331
+ "base": "http://localhost:8080",
332
+ "prefix": "/api",
333
+ "path": "items/{id}",
334
+ "suffix": "",
335
+ "params": map[string]any{"id": "item01"},
336
+ "query": map[string]any{},
337
+ "headers": map[string]any{"content-type": "application/json"},
338
+ "method": "GET",
339
+ "step": "start",
340
+ })
341
+ ctx.Result = sdk.NewResult(map[string]any{})
342
+
343
+ fetchdef, err := utility.MakeFetchDef(ctx)
344
+ if err != nil {
345
+ t.Errorf("should not be error: %v", err)
346
+ return
347
+ }
348
+ if fetchdef["method"] != "GET" {
349
+ t.Errorf("expected method GET, got %v", fetchdef["method"])
350
+ }
351
+ url, _ := fetchdef["url"].(string)
352
+ if !strings.Contains(url, "/api/items/item01") {
353
+ t.Errorf("expected url to contain /api/items/item01, got %v", url)
354
+ }
355
+ if fetchdef["headers"].(map[string]any)["content-type"] != "application/json" {
356
+ t.Error("expected content-type header")
357
+ }
358
+ if fetchdef["body"] != nil {
359
+ t.Error("expected nil body")
360
+ }
361
+ })
362
+
363
+ t.Run("makeFetchDef-with-body", func(t *testing.T) {
364
+ ctx := makeTestFullCtx(client, utility)
365
+ ctx.Spec = sdk.NewSpec(map[string]any{
366
+ "base": "http://localhost:8080",
367
+ "prefix": "",
368
+ "path": "items",
369
+ "suffix": "",
370
+ "params": map[string]any{},
371
+ "query": map[string]any{},
372
+ "headers": map[string]any{},
373
+ "method": "POST",
374
+ "step": "start",
375
+ "body": map[string]any{"name": "test"},
376
+ })
377
+ ctx.Result = sdk.NewResult(map[string]any{})
378
+
379
+ fetchdef, err := utility.MakeFetchDef(ctx)
380
+ if err != nil {
381
+ t.Errorf("should not be error: %v", err)
382
+ return
383
+ }
384
+ if fetchdef["method"] != "POST" {
385
+ t.Errorf("expected method POST, got %v", fetchdef["method"])
386
+ }
387
+ bodyStr, ok := fetchdef["body"].(string)
388
+ if !ok {
389
+ t.Errorf("expected body string, got %T", fetchdef["body"])
390
+ return
391
+ }
392
+ if !strings.Contains(bodyStr, "\"name\"") {
393
+ t.Errorf("expected body to contain name, got %v", bodyStr)
394
+ }
395
+ })
396
+
397
+ t.Run("makeOptions-basic", func(t *testing.T) {
398
+ runset(t, getSpec(primary, "makeOptions", "basic"), func(entry map[string]any) (any, error) {
399
+ in, _ := entry["in"].(map[string]any)
400
+ ctx := utility.MakeContext(map[string]any{
401
+ "options": in["options"],
402
+ "config": in["config"],
403
+ }, nil)
404
+ ctx.Client = client
405
+ ctx.Utility = utility
406
+ return utility.MakeOptions(ctx), nil
407
+ })
408
+ })
409
+
410
+ t.Run("makeRequest-basic", func(t *testing.T) {
411
+ runset(t, getSpec(primary, "makeRequest", "basic"), func(entry map[string]any) (any, error) {
412
+ ctxmap, _ := entry["ctx"].(map[string]any)
413
+ ctx := makeCtxFromMap(ctxmap, client, utility)
414
+ ctx.Options = client.OptionsMap()
415
+
416
+ _, err := utility.MakeRequest(ctx)
417
+ if err != nil {
418
+ return nil, err
419
+ }
420
+
421
+ // Update entry ctx for match checking
422
+ entryCtx, _ := entry["ctx"].(map[string]any)
423
+ if ctx.Response != nil {
424
+ entryCtx["response"] = "exists"
425
+ }
426
+ if ctx.Result != nil {
427
+ entryCtx["result"] = "exists"
428
+ }
429
+
430
+ return nil, nil
431
+ })
432
+ })
433
+
434
+ t.Run("makeResponse-basic", func(t *testing.T) {
435
+ runset(t, getSpec(primary, "makeResponse", "basic"), func(entry map[string]any) (any, error) {
436
+ ctxmap, _ := entry["ctx"].(map[string]any)
437
+ ctx := makeCtxFromMap(ctxmap, client, utility)
438
+ fixctx(ctx, client)
439
+
440
+ _, err := utility.MakeResponse(ctx)
441
+ if err != nil {
442
+ return nil, err
443
+ }
444
+
445
+ // Update entry ctx for match checking with result data
446
+ entryCtx, _ := entry["ctx"].(map[string]any)
447
+ if ctx.Result != nil {
448
+ entryCtx["result"] = map[string]any{
449
+ "ok": ctx.Result.Ok,
450
+ "status": ctx.Result.Status,
451
+ "statusText": ctx.Result.StatusText,
452
+ "headers": ctx.Result.Headers,
453
+ "body": ctx.Result.Body,
454
+ }
455
+ }
456
+
457
+ return nil, nil
458
+ })
459
+ })
460
+
461
+ t.Run("makeResult-basic", func(t *testing.T) {
462
+ ctx := makeTestFullCtx(client, utility)
463
+ ctx.Spec = sdk.NewSpec(map[string]any{
464
+ "base": "http://localhost:8080",
465
+ "prefix": "/api",
466
+ "path": "items/{id}",
467
+ "suffix": "",
468
+ "params": map[string]any{"id": "item01"},
469
+ "query": map[string]any{},
470
+ "headers": map[string]any{},
471
+ "method": "GET",
472
+ "step": "start",
473
+ })
474
+ ctx.Result = sdk.NewResult(map[string]any{
475
+ "ok": true,
476
+ "status": 200,
477
+ "statusText": "OK",
478
+ "headers": map[string]any{},
479
+ "resdata": map[string]any{"id": "item01", "name": "Test"},
480
+ })
481
+
482
+ result, err := utility.MakeResult(ctx)
483
+ if err != nil {
484
+ t.Errorf("expected no error, got: %v", err)
485
+ return
486
+ }
487
+ if result.Status != 200 {
488
+ t.Errorf("expected status 200, got %d", result.Status)
489
+ }
490
+ })
491
+
492
+ t.Run("makeResult-no-spec", func(t *testing.T) {
493
+ ctx := makeTestFullCtx(client, utility)
494
+ ctx.Spec = nil
495
+ ctx.Result = sdk.NewResult(map[string]any{
496
+ "ok": true,
497
+ "status": 200,
498
+ "statusText": "OK",
499
+ "headers": map[string]any{},
500
+ })
501
+
502
+ _, err := utility.MakeResult(ctx)
503
+ if err == nil {
504
+ t.Error("expected error for nil spec")
505
+ }
506
+ })
507
+
508
+ t.Run("makeResult-no-result", func(t *testing.T) {
509
+ ctx := makeTestFullCtx(client, utility)
510
+ ctx.Spec = sdk.NewSpec(map[string]any{"step": "start"})
511
+ ctx.Result = nil
512
+
513
+ _, err := utility.MakeResult(ctx)
514
+ if err == nil {
515
+ t.Error("expected error for nil result")
516
+ }
517
+ })
518
+
519
+ t.Run("makeSpec-basic", func(t *testing.T) {
520
+ setupOpts := getSpec(primary, "makeSpec", "DEF", "setup", "a")
521
+ specClient := sdk.TestSDK(nil, setupOpts)
522
+ specUtility := specClient.GetUtility()
523
+
524
+ runset(t, getSpec(primary, "makeSpec", "basic"), func(entry map[string]any) (any, error) {
525
+ ctxmap, _ := entry["ctx"].(map[string]any)
526
+ ctx := makeCtxFromMap(ctxmap, specClient, specUtility)
527
+ ctx.Options = specClient.OptionsMap()
528
+
529
+ _, err := utility.MakeSpec(ctx)
530
+ if err != nil {
531
+ return nil, err
532
+ }
533
+
534
+ // Update entry ctx for match
535
+ entryCtx, _ := entry["ctx"].(map[string]any)
536
+ if ctx.Spec != nil {
537
+ entryCtx["spec"] = map[string]any{
538
+ "base": ctx.Spec.Base,
539
+ "prefix": ctx.Spec.Prefix,
540
+ "suffix": ctx.Spec.Suffix,
541
+ "method": ctx.Spec.Method,
542
+ "params": ctx.Spec.Params,
543
+ "query": ctx.Spec.Query,
544
+ "headers": ctx.Spec.Headers,
545
+ "step": ctx.Spec.Step,
546
+ }
547
+ }
548
+
549
+ return nil, nil
550
+ })
551
+ })
552
+
553
+ t.Run("makeTarget-basic", func(t *testing.T) {
554
+ ctx := makeTestCtx(client, utility, nil)
555
+ target := map[string]any{
556
+ "parts": []any{"items", "{id}"},
557
+ "args": map[string]any{"params": []any{}},
558
+ "params": []any{},
559
+ "alias": map[string]any{},
560
+ "select": map[string]any{},
561
+ "active": true,
562
+ "transform": map[string]any{},
563
+ }
564
+ ctx.Op.Targets = []map[string]any{target}
565
+
566
+ _, err := utility.MakeTarget(ctx)
567
+ if err != nil {
568
+ t.Errorf("expected no error, got: %v", err)
569
+ return
570
+ }
571
+ if ctx.Target == nil {
572
+ t.Error("expected target to be set")
573
+ }
574
+ })
575
+
576
+ t.Run("makeUrl-basic", func(t *testing.T) {
577
+ runset(t, getSpec(primary, "makeUrl", "basic"), func(entry map[string]any) (any, error) {
578
+ ctxmap, _ := entry["ctx"].(map[string]any)
579
+ ctx := makeCtxFromMap(ctxmap, client, utility)
580
+ if ctx.Result == nil {
581
+ ctx.Result = sdk.NewResult(map[string]any{})
582
+ }
583
+ return utility.MakeUrl(ctx)
584
+ })
585
+ })
586
+
587
+ t.Run("operator-basic", func(t *testing.T) {
588
+ runset(t, getSpec(primary, "operator", "basic"), func(entry map[string]any) (any, error) {
589
+ in, _ := entry["in"].(map[string]any)
590
+ op := sdk.NewOperation(in)
591
+ return map[string]any{
592
+ "entity": op.Entity,
593
+ "name": op.Name,
594
+ "input": op.Input,
595
+ "targets": op.Targets,
596
+ }, nil
597
+ })
598
+ })
599
+
600
+ t.Run("param-basic", func(t *testing.T) {
601
+ runset(t, getSpec(primary, "param", "basic"), func(entry map[string]any) (any, error) {
602
+ args, _ := entry["args"].([]any)
603
+ if len(args) < 2 {
604
+ return nil, nil
605
+ }
606
+
607
+ ctxmap, _ := args[0].(map[string]any)
608
+ if ctxmap == nil {
609
+ ctxmap = map[string]any{}
610
+ }
611
+ ctx := makeCtxFromMap(ctxmap, client, utility)
612
+ paramdef := args[1]
613
+
614
+ result := utility.Param(ctx, paramdef)
615
+
616
+ // Update entry ctx for match
617
+ if matchSpec, ok := entry["match"].(map[string]any); ok {
618
+ if ctxMatch, ok := matchSpec["ctx"].(map[string]any); ok {
619
+ entryCtx, _ := entry["ctx"].(map[string]any)
620
+ if entryCtx == nil {
621
+ entryCtx = map[string]any{}
622
+ entry["ctx"] = entryCtx
623
+ }
624
+ // Copy spec alias back to entry ctx for matching
625
+ if specMatch, ok := ctxMatch["spec"].(map[string]any); ok {
626
+ if ctx.Spec != nil {
627
+ if entryCtx["spec"] == nil {
628
+ entryCtx["spec"] = map[string]any{}
629
+ }
630
+ if aliasMatch, ok := specMatch["alias"].(map[string]any); ok {
631
+ _ = aliasMatch
632
+ entryCtx["spec"] = map[string]any{
633
+ "alias": ctx.Spec.Alias,
634
+ }
635
+ }
636
+ }
637
+ }
638
+ }
639
+ }
640
+
641
+ return result, nil
642
+ })
643
+ })
644
+
645
+ t.Run("prepareAuth-basic", func(t *testing.T) {
646
+ setupOpts := getSpec(primary, "prepareAuth", "DEF", "setup", "a")
647
+ authClient := sdk.TestSDK(nil, setupOpts)
648
+ authUtility := authClient.GetUtility()
649
+
650
+ runset(t, getSpec(primary, "prepareAuth", "basic"), func(entry map[string]any) (any, error) {
651
+ ctxmap, _ := entry["ctx"].(map[string]any)
652
+ ctx := makeCtxFromMap(ctxmap, authClient, authUtility)
653
+ fixctx(ctx, authClient)
654
+
655
+ _, err := utility.PrepareAuth(ctx)
656
+ if err != nil {
657
+ return nil, err
658
+ }
659
+
660
+ // Update entry ctx for match
661
+ entryCtx, _ := entry["ctx"].(map[string]any)
662
+ if ctx.Spec != nil {
663
+ entryCtx["spec"] = map[string]any{
664
+ "headers": ctx.Spec.Headers,
665
+ }
666
+ }
667
+
668
+ return nil, nil
669
+ })
670
+ })
671
+
672
+ t.Run("prepareBody-basic", func(t *testing.T) {
673
+ runset(t, getSpec(primary, "prepareBody", "basic"), func(entry map[string]any) (any, error) {
674
+ ctxmap, _ := entry["ctx"].(map[string]any)
675
+ ctx := makeCtxFromMap(ctxmap, client, utility)
676
+ fixctx(ctx, client)
677
+ return utility.PrepareBody(ctx), nil
678
+ })
679
+ })
680
+
681
+ t.Run("prepareHeaders-basic", func(t *testing.T) {
682
+ runset(t, getSpec(primary, "prepareHeaders", "basic"), func(entry map[string]any) (any, error) {
683
+ ctxmap, _ := entry["ctx"].(map[string]any)
684
+ ctx := makeCtxFromMap(ctxmap, client, utility)
685
+ return utility.PrepareHeaders(ctx), nil
686
+ })
687
+ })
688
+
689
+ t.Run("prepareMethod-basic", func(t *testing.T) {
690
+ runset(t, getSpec(primary, "prepareMethod", "basic"), func(entry map[string]any) (any, error) {
691
+ ctxmap, _ := entry["ctx"].(map[string]any)
692
+ ctx := makeCtxFromMap(ctxmap, client, utility)
693
+ return utility.PrepareMethod(ctx), nil
694
+ })
695
+ })
696
+
697
+ t.Run("prepareParams-basic", func(t *testing.T) {
698
+ runset(t, getSpec(primary, "prepareParams", "basic"), func(entry map[string]any) (any, error) {
699
+ ctxmap, _ := entry["ctx"].(map[string]any)
700
+ ctx := makeCtxFromMap(ctxmap, client, utility)
701
+ return utility.PrepareParams(ctx), nil
702
+ })
703
+ })
704
+
705
+ t.Run("preparePath-basic", func(t *testing.T) {
706
+ ctx := makeTestFullCtx(client, utility)
707
+ ctx.Target = map[string]any{
708
+ "parts": []any{"api", "planet", "{id}"},
709
+ "args": map[string]any{"params": []any{}},
710
+ }
711
+
712
+ path := utility.PreparePath(ctx)
713
+ if path != "api/planet/{id}" {
714
+ t.Errorf("expected api/planet/{id}, got %s", path)
715
+ }
716
+ })
717
+
718
+ t.Run("preparePath-single", func(t *testing.T) {
719
+ ctx := makeTestFullCtx(client, utility)
720
+ ctx.Target = map[string]any{
721
+ "parts": []any{"items"},
722
+ "args": map[string]any{"params": []any{}},
723
+ }
724
+
725
+ path := utility.PreparePath(ctx)
726
+ if path != "items" {
727
+ t.Errorf("expected items, got %s", path)
728
+ }
729
+ })
730
+
731
+ t.Run("prepareQuery-basic", func(t *testing.T) {
732
+ runset(t, getSpec(primary, "prepareQuery", "basic"), func(entry map[string]any) (any, error) {
733
+ ctxmap, _ := entry["ctx"].(map[string]any)
734
+ ctx := makeCtxFromMap(ctxmap, client, utility)
735
+ return utility.PrepareQuery(ctx), nil
736
+ })
737
+ })
738
+
739
+ t.Run("resultBasic-basic", func(t *testing.T) {
740
+ runset(t, getSpec(primary, "resultBasic", "basic"), func(entry map[string]any) (any, error) {
741
+ ctxmap, _ := entry["ctx"].(map[string]any)
742
+ ctx := makeCtxFromMap(ctxmap, client, utility)
743
+ fixctx(ctx, client)
744
+
745
+ result := utility.ResultBasic(ctx)
746
+
747
+ out := map[string]any{
748
+ "status": result.Status,
749
+ "statusText": result.StatusText,
750
+ }
751
+ if result.Err != nil {
752
+ out["err"] = map[string]any{
753
+ "message": result.Err.Error(),
754
+ }
755
+ }
756
+
757
+ return out, nil
758
+ })
759
+ })
760
+
761
+ t.Run("resultBody-basic", func(t *testing.T) {
762
+ runset(t, getSpec(primary, "resultBody", "basic"), func(entry map[string]any) (any, error) {
763
+ ctxmap, _ := entry["ctx"].(map[string]any)
764
+ ctx := makeCtxFromMap(ctxmap, client, utility)
765
+
766
+ utility.ResultBody(ctx)
767
+
768
+ // Update entry ctx for match
769
+ entryCtx, _ := entry["ctx"].(map[string]any)
770
+ if ctx.Result != nil {
771
+ entryCtx["result"] = map[string]any{
772
+ "body": ctx.Result.Body,
773
+ }
774
+ }
775
+
776
+ return nil, nil
777
+ })
778
+ })
779
+
780
+ t.Run("resultHeaders-basic", func(t *testing.T) {
781
+ runset(t, getSpec(primary, "resultHeaders", "basic"), func(entry map[string]any) (any, error) {
782
+ ctxmap, _ := entry["ctx"].(map[string]any)
783
+ ctx := makeCtxFromMap(ctxmap, client, utility)
784
+
785
+ utility.ResultHeaders(ctx)
786
+
787
+ // Update entry ctx for match
788
+ entryCtx, _ := entry["ctx"].(map[string]any)
789
+ if ctx.Result != nil {
790
+ entryCtx["result"] = map[string]any{
791
+ "headers": ctx.Result.Headers,
792
+ }
793
+ }
794
+
795
+ return nil, nil
796
+ })
797
+ })
798
+
799
+ t.Run("transformRequest-basic", func(t *testing.T) {
800
+ runset(t, getSpec(primary, "transformRequest", "basic"), func(entry map[string]any) (any, error) {
801
+ ctxmap, _ := entry["ctx"].(map[string]any)
802
+ ctx := makeCtxFromMap(ctxmap, client, utility)
803
+
804
+ result := utility.TransformRequest(ctx)
805
+
806
+ // Update entry ctx for match (step changed)
807
+ entryCtx, _ := entry["ctx"].(map[string]any)
808
+ if ctx.Spec != nil {
809
+ if specMap, ok := entryCtx["spec"].(map[string]any); ok {
810
+ specMap["step"] = ctx.Spec.Step
811
+ }
812
+ }
813
+
814
+ return result, nil
815
+ })
816
+ })
817
+
818
+ t.Run("transformResponse-basic", func(t *testing.T) {
819
+ runset(t, getSpec(primary, "transformResponse", "basic"), func(entry map[string]any) (any, error) {
820
+ ctxmap, _ := entry["ctx"].(map[string]any)
821
+ ctx := makeCtxFromMap(ctxmap, client, utility)
822
+
823
+ result := utility.TransformResponse(ctx)
824
+
825
+ // Update entry ctx for match (step changed)
826
+ entryCtx, _ := entry["ctx"].(map[string]any)
827
+ if ctx.Spec != nil {
828
+ if specMap, ok := entryCtx["spec"].(map[string]any); ok {
829
+ specMap["step"] = ctx.Spec.Step
830
+ }
831
+ }
832
+
833
+ return result, nil
834
+ })
835
+ })
836
+ }
837
+
838
+ // Helper: test hook feature for featureHook test
839
+ type testHookFeature struct {
840
+ *sdk.BaseFeature
841
+ hookFn func()
842
+ }
843
+
844
+ func (f *testHookFeature) TestHook(ctx *sdk.Context) {
845
+ if f.hookFn != nil {
846
+ f.hookFn()
847
+ }
848
+ }
849
+
850
+ // Helper: test init feature for featureInit test
851
+ type testInitFeature struct {
852
+ *sdk.BaseFeature
853
+ name string
854
+ active bool
855
+ initFn func()
856
+ }
857
+
858
+ func (f *testInitFeature) GetName() string { return f.name }
859
+ func (f *testInitFeature) GetActive() bool { return f.active }
860
+ func (f *testInitFeature) Init(ctx *sdk.Context, options map[string]any) {
861
+ if f.initFn != nil {
862
+ f.initFn()
863
+ }
864
+ }
865
+
866
+ // Helper: create basic test context
867
+ func makeTestCtx(client *sdk.ProjectNameSDK, utility *sdk.Utility, overrides map[string]any) *sdk.Context {
868
+ ctxmap := map[string]any{
869
+ "opname": "load",
870
+ "client": client,
871
+ "utility": utility,
872
+ }
873
+ if overrides != nil {
874
+ for k, v := range overrides {
875
+ ctxmap[k] = v
876
+ }
877
+ }
878
+ return utility.MakeContext(ctxmap, client.GetRootCtx())
879
+ }
880
+
881
+ // Helper: create full test context with target and match
882
+ func makeTestFullCtx(client *sdk.ProjectNameSDK, utility *sdk.Utility) *sdk.Context {
883
+ ctx := makeTestCtx(client, utility, nil)
884
+ ctx.Target = map[string]any{
885
+ "parts": []any{"items", "{id}"},
886
+ "args": map[string]any{"params": []any{map[string]any{"name": "id", "reqd": true}}},
887
+ "params": []any{"id"},
888
+ "alias": map[string]any{},
889
+ "select": map[string]any{},
890
+ "active": true,
891
+ "transform": map[string]any{},
892
+ }
893
+ ctx.Match = map[string]any{"id": "item01"}
894
+ ctx.Reqmatch = map[string]any{"id": "item01"}
895
+ return ctx
896
+ }
897
+
898
+ // useVS prevents unused import error
899
+ var _ = vs.Clone