@voxgig/sdkgen 1.3.17 → 1.3.18

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 (220) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/cmp/Entity.js +5 -1
  3. package/dist/cmp/Entity.js.map +1 -1
  4. package/dist/cmp/Feature.js +2 -1
  5. package/dist/cmp/Feature.js.map +1 -1
  6. package/dist/helpers/canonType.js +8 -3
  7. package/dist/helpers/canonType.js.map +1 -1
  8. package/dist/helpers/collectDeps.d.ts +1 -1
  9. package/dist/helpers/collectDeps.js +36 -13
  10. package/dist/helpers/collectDeps.js.map +1 -1
  11. package/dist/helpers/naming.d.ts +3 -1
  12. package/dist/helpers/naming.js +53 -0
  13. package/dist/helpers/naming.js.map +1 -1
  14. package/dist/helpers/opShape.d.ts +3 -1
  15. package/dist/helpers/opShape.js +87 -8
  16. package/dist/helpers/opShape.js.map +1 -1
  17. package/dist/sdkgen.d.ts +3 -3
  18. package/dist/sdkgen.js +6 -2
  19. package/dist/sdkgen.js.map +1 -1
  20. package/dist/tsconfig.tsbuildinfo +1 -1
  21. package/package.json +15 -10
  22. package/project/.sdk/model/target/cpp.aontu +4 -4
  23. package/project/.sdk/model/target/go-cli.aontu +17 -17
  24. package/project/.sdk/model/target/go-mcp.aontu +11 -11
  25. package/project/.sdk/model/target/go.aontu +1 -1
  26. package/project/.sdk/model/target/java.aontu +4 -4
  27. package/project/.sdk/model/target/kotlin.aontu +4 -4
  28. package/project/.sdk/model/target/lean.aontu +51 -0
  29. package/project/.sdk/model/target/scala.aontu +4 -4
  30. package/project/.sdk/src/cmp/c/EntityTypes_c.ts +3 -4
  31. package/project/.sdk/src/cmp/c/Entity_c.ts +3 -3
  32. package/project/.sdk/src/cmp/c/ReadmeExamplesTest_c.ts +24 -7
  33. package/project/.sdk/src/cmp/c/TestDirect_c.ts +3 -3
  34. package/project/.sdk/src/cmp/c/TestEntity_c.ts +1 -1
  35. package/project/.sdk/src/cmp/clojure/Entity_clojure.ts +1 -1
  36. package/project/.sdk/src/cmp/clojure/ReadmeExamplesTest_clojure.ts +19 -8
  37. package/project/.sdk/src/cmp/cpp/EntityTypes_cpp.ts +2 -2
  38. package/project/.sdk/src/cmp/cpp/Entity_cpp.ts +3 -3
  39. package/project/.sdk/src/cmp/cpp/MainEntity_cpp.ts +2 -2
  40. package/project/.sdk/src/cmp/cpp/ReadmeExamplesTest_cpp.ts +136 -0
  41. package/project/.sdk/src/cmp/cpp/TestDirect_cpp.ts +3 -3
  42. package/project/.sdk/src/cmp/cpp/Test_cpp.ts +4 -0
  43. package/project/.sdk/src/cmp/csharp/EntityTypes_csharp.ts +2 -3
  44. package/project/.sdk/src/cmp/csharp/Entity_csharp.ts +3 -3
  45. package/project/.sdk/src/cmp/csharp/MainEntity_csharp.ts +2 -2
  46. package/project/.sdk/src/cmp/csharp/Package_csharp.ts +1 -1
  47. package/project/.sdk/src/cmp/csharp/ReadmeExamplesTest_csharp.ts +13 -1
  48. package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +3 -3
  49. package/project/.sdk/src/cmp/dart/EntityTypes_dart.ts +2 -3
  50. package/project/.sdk/src/cmp/dart/Entity_dart.ts +3 -3
  51. package/project/.sdk/src/cmp/dart/MainEntity_dart.ts +2 -2
  52. package/project/.sdk/src/cmp/dart/Main_dart.ts +3 -3
  53. package/project/.sdk/src/cmp/dart/Package_dart.ts +1 -1
  54. package/project/.sdk/src/cmp/dart/TestDirect_dart.ts +4 -4
  55. package/project/.sdk/src/cmp/elixir/EntityTypes_elixir.ts +2 -3
  56. package/project/.sdk/src/cmp/elixir/Entity_elixir.ts +1 -1
  57. package/project/.sdk/src/cmp/elixir/ReadmeExamplesTest_elixir.ts +21 -3
  58. package/project/.sdk/src/cmp/go/Config_go.ts +4 -1
  59. package/project/.sdk/src/cmp/go/EntityTypes_go.ts +110 -18
  60. package/project/.sdk/src/cmp/go/Entity_go.ts +3 -3
  61. package/project/.sdk/src/cmp/go/Main_go.ts +7 -6
  62. package/project/.sdk/src/cmp/go/Package_go.ts +1 -1
  63. package/project/.sdk/src/cmp/go/TestDirect_go.ts +3 -3
  64. package/project/.sdk/src/cmp/go/TestEntity_go.ts +1 -1
  65. package/project/.sdk/src/cmp/go/utility_go.ts +25 -0
  66. package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +9 -1
  67. package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +9 -1
  68. package/project/.sdk/src/cmp/haskell/ReadmeExamplesTest_haskell.ts +28 -18
  69. package/project/.sdk/src/cmp/java/EntityTypes_java.ts +2 -3
  70. package/project/.sdk/src/cmp/java/Entity_java.ts +3 -3
  71. package/project/.sdk/src/cmp/java/MainEntity_java.ts +2 -2
  72. package/project/.sdk/src/cmp/java/Package_java.ts +1 -1
  73. package/project/.sdk/src/cmp/java/ReadmeExamplesTest_java.ts +23 -1
  74. package/project/.sdk/src/cmp/java/TestDirect_java.ts +3 -3
  75. package/project/.sdk/src/cmp/js/EntityTypes_js.ts +2 -3
  76. package/project/.sdk/src/cmp/js/Entity_js.ts +3 -3
  77. package/project/.sdk/src/cmp/js/MainEntity_js.ts +2 -2
  78. package/project/.sdk/src/cmp/js/Main_js.ts +2 -2
  79. package/project/.sdk/src/cmp/js/TestDirect_js.ts +4 -4
  80. package/project/.sdk/src/cmp/kotlin/EntityTypes_kotlin.ts +2 -3
  81. package/project/.sdk/src/cmp/kotlin/Entity_kotlin.ts +3 -3
  82. package/project/.sdk/src/cmp/kotlin/MainEntity_kotlin.ts +2 -2
  83. package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +1 -1
  84. package/project/.sdk/src/cmp/kotlin/ReadmeExamplesTest_kotlin.ts +27 -2
  85. package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +3 -3
  86. package/project/.sdk/src/cmp/lean/Config_lean.ts +88 -0
  87. package/project/.sdk/src/cmp/lean/Entity_lean.ts +9 -0
  88. package/project/.sdk/src/cmp/lean/Gitignore_lean.ts +18 -0
  89. package/project/.sdk/src/cmp/lean/Main_lean.ts +120 -0
  90. package/project/.sdk/src/cmp/lean/Package_lean.ts +68 -0
  91. package/project/.sdk/src/cmp/lean/ReadmeEntity_lean.ts +29 -0
  92. package/project/.sdk/src/cmp/lean/ReadmeExplanation_lean.ts +19 -0
  93. package/project/.sdk/src/cmp/lean/ReadmeHowto_lean.ts +25 -0
  94. package/project/.sdk/src/cmp/lean/ReadmeInstall_lean.ts +38 -0
  95. package/project/.sdk/src/cmp/lean/ReadmeIntro_lean.ts +25 -0
  96. package/project/.sdk/src/cmp/lean/ReadmeModel_lean.ts +24 -0
  97. package/project/.sdk/src/cmp/lean/ReadmeOptions_lean.ts +22 -0
  98. package/project/.sdk/src/cmp/lean/ReadmeQuick_lean.ts +50 -0
  99. package/project/.sdk/src/cmp/lean/ReadmeRef_lean.ts +16 -0
  100. package/project/.sdk/src/cmp/lean/ReadmeTopHowto_lean.ts +16 -0
  101. package/project/.sdk/src/cmp/lean/ReadmeTopQuick_lean.ts +23 -0
  102. package/project/.sdk/src/cmp/lean/ReadmeTopTest_lean.ts +18 -0
  103. package/project/.sdk/src/cmp/lean/Test_lean.ts +207 -0
  104. package/project/.sdk/src/cmp/lean/utility_lean.ts +78 -0
  105. package/project/.sdk/src/cmp/lua/EntityTypes_lua.ts +2 -3
  106. package/project/.sdk/src/cmp/lua/Entity_lua.ts +3 -3
  107. package/project/.sdk/src/cmp/lua/Package_lua.ts +1 -1
  108. package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +3 -3
  109. package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +1 -1
  110. package/project/.sdk/src/cmp/ocaml/ReadmeExamplesTest_ocaml.ts +29 -14
  111. package/project/.sdk/src/cmp/perl/Entity_perl.ts +3 -3
  112. package/project/.sdk/src/cmp/perl/MainEntity_perl.ts +2 -2
  113. package/project/.sdk/src/cmp/perl/Package_perl.ts +1 -1
  114. package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +3 -3
  115. package/project/.sdk/src/cmp/php/EntityTypes_php.ts +2 -3
  116. package/project/.sdk/src/cmp/php/Entity_php.ts +3 -3
  117. package/project/.sdk/src/cmp/php/MainEntity_php.ts +2 -2
  118. package/project/.sdk/src/cmp/php/Package_php.ts +1 -1
  119. package/project/.sdk/src/cmp/php/TestDirect_php.ts +3 -3
  120. package/project/.sdk/src/cmp/php/TestEntity_php.ts +1 -1
  121. package/project/.sdk/src/cmp/py/EntityTypes_py.ts +2 -3
  122. package/project/.sdk/src/cmp/py/Entity_py.ts +3 -3
  123. package/project/.sdk/src/cmp/py/MainEntity_py.ts +2 -2
  124. package/project/.sdk/src/cmp/py/Main_py.ts +2 -2
  125. package/project/.sdk/src/cmp/py/Package_py.ts +1 -1
  126. package/project/.sdk/src/cmp/py/TestDirect_py.ts +3 -3
  127. package/project/.sdk/src/cmp/py/TestEntity_py.ts +1 -1
  128. package/project/.sdk/src/cmp/rb/EntityTypes_rb.ts +15 -5
  129. package/project/.sdk/src/cmp/rb/Entity_rb.ts +3 -3
  130. package/project/.sdk/src/cmp/rb/MainEntity_rb.ts +2 -2
  131. package/project/.sdk/src/cmp/rb/Package_rb.ts +2 -2
  132. package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +3 -3
  133. package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +1 -1
  134. package/project/.sdk/src/cmp/rust/EntityBase_rust.ts +2 -2
  135. package/project/.sdk/src/cmp/rust/EntityTypes_rust.ts +3 -4
  136. package/project/.sdk/src/cmp/rust/Entity_rust.ts +3 -3
  137. package/project/.sdk/src/cmp/rust/MainEntity_rust.ts +2 -2
  138. package/project/.sdk/src/cmp/rust/Package_rust.ts +1 -1
  139. package/project/.sdk/src/cmp/rust/ReadmeExamplesTest_rust.ts +22 -10
  140. package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +3 -3
  141. package/project/.sdk/src/cmp/scala/EntityTypes_scala.ts +2 -3
  142. package/project/.sdk/src/cmp/scala/Entity_scala.ts +3 -3
  143. package/project/.sdk/src/cmp/scala/MainEntity_scala.ts +2 -2
  144. package/project/.sdk/src/cmp/scala/ReadmeExamplesTest_scala.ts +22 -3
  145. package/project/.sdk/src/cmp/scala/TestDirect_scala.ts +3 -3
  146. package/project/.sdk/src/cmp/scala/Test_scala.ts +1 -1
  147. package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +3 -4
  148. package/project/.sdk/src/cmp/swift/Entity_swift.ts +3 -3
  149. package/project/.sdk/src/cmp/swift/MainEntity_swift.ts +2 -2
  150. package/project/.sdk/src/cmp/swift/Package_swift.ts +1 -1
  151. package/project/.sdk/src/cmp/swift/ReadmeExamplesTest_swift.ts +18 -1
  152. package/project/.sdk/src/cmp/swift/TestDirect_swift.ts +1 -1
  153. package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +2 -3
  154. package/project/.sdk/src/cmp/ts/Entity_ts.ts +3 -3
  155. package/project/.sdk/src/cmp/ts/MainEntity_ts.ts +2 -2
  156. package/project/.sdk/src/cmp/ts/Main_ts.ts +2 -2
  157. package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +4 -4
  158. package/project/.sdk/src/cmp/zig/Entity_zig.ts +3 -3
  159. package/project/.sdk/src/cmp/zig/MainEntity_zig.ts +2 -2
  160. package/project/.sdk/src/cmp/zig/Package_zig.ts +10 -2
  161. package/project/.sdk/tm/cpp/test/primary_utility_test.cpp +8 -16
  162. package/project/.sdk/tm/csharp/test/PrimaryUtilityTest.cs +10 -28
  163. package/project/.sdk/tm/dart/test/primary_test.dart +7 -0
  164. package/project/.sdk/tm/go/feature/test_feature.go +33 -1
  165. package/project/.sdk/tm/go/test/primary_utility_test.go +41 -42
  166. package/project/.sdk/tm/go/test/runner_test.go +30 -1
  167. package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +7 -24
  168. package/project/.sdk/tm/js/src/feature/test/TestFeature.js +18 -1
  169. package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +8 -0
  170. package/project/.sdk/tm/kotlin/test/PrimaryUtilityTest.kt +7 -20
  171. package/project/.sdk/tm/lean/LICENSE +21 -0
  172. package/project/.sdk/tm/lean/VERSION +1 -0
  173. package/project/.sdk/tm/lean/src/SdkFeature.lean +171 -0
  174. package/project/.sdk/tm/lean/src/SdkFeatures.lean +602 -0
  175. package/project/.sdk/tm/lean/src/SdkJson.lean +134 -0
  176. package/project/.sdk/tm/lean/src/SdkRuntime.lean +356 -0
  177. package/project/.sdk/tm/lean/src/SdkUtility.lean +617 -0
  178. package/project/.sdk/tm/lean/src/VoxgigStruct.lean +2880 -0
  179. package/project/.sdk/tm/lean/src/Vregex.lean +412 -0
  180. package/project/.sdk/tm/lean/src/feature/README.md +5 -0
  181. package/project/.sdk/tm/lean/src/feature/audit/.gitkeep +0 -0
  182. package/project/.sdk/tm/lean/src/feature/base/.gitkeep +0 -0
  183. package/project/.sdk/tm/lean/src/feature/cache/.gitkeep +0 -0
  184. package/project/.sdk/tm/lean/src/feature/clienttrack/.gitkeep +0 -0
  185. package/project/.sdk/tm/lean/src/feature/debug/.gitkeep +0 -0
  186. package/project/.sdk/tm/lean/src/feature/idempotency/.gitkeep +0 -0
  187. package/project/.sdk/tm/lean/src/feature/log/.gitkeep +0 -0
  188. package/project/.sdk/tm/lean/src/feature/metrics/.gitkeep +0 -0
  189. package/project/.sdk/tm/lean/src/feature/netsim/.gitkeep +0 -0
  190. package/project/.sdk/tm/lean/src/feature/paging/.gitkeep +0 -0
  191. package/project/.sdk/tm/lean/src/feature/proxy/.gitkeep +0 -0
  192. package/project/.sdk/tm/lean/src/feature/ratelimit/.gitkeep +0 -0
  193. package/project/.sdk/tm/lean/src/feature/rbac/.gitkeep +0 -0
  194. package/project/.sdk/tm/lean/src/feature/retry/.gitkeep +0 -0
  195. package/project/.sdk/tm/lean/src/feature/streaming/.gitkeep +0 -0
  196. package/project/.sdk/tm/lean/src/feature/telemetry/.gitkeep +0 -0
  197. package/project/.sdk/tm/lean/src/feature/test/.gitkeep +0 -0
  198. package/project/.sdk/tm/lean/src/feature/timeout/.gitkeep +0 -0
  199. package/project/.sdk/tm/lean/test/StructCorpus.lean +697 -0
  200. package/project/.sdk/tm/lean/test/TFeature.lean +268 -0
  201. package/project/.sdk/tm/lean/test/TPrimaryUtility.lean +349 -0
  202. package/project/.sdk/tm/lua/test/primary_utility_test.lua +10 -8
  203. package/project/.sdk/tm/perl/t/primary_utility.t +8 -17
  204. package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +9 -7
  205. package/project/.sdk/tm/py/feature/test_feature.py +28 -1
  206. package/project/.sdk/tm/py/test/test_primary_utility.py +13 -18
  207. package/project/.sdk/tm/rb/feature/test_feature.rb +24 -1
  208. package/project/.sdk/tm/rb/test/primary_utility_test.rb +7 -8
  209. package/project/.sdk/tm/rust/tests/common/mod.rs +37 -1
  210. package/project/.sdk/tm/rust/tests/primary_utility_test.rs +12 -26
  211. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PrimaryUtilityTest.swift +7 -8
  212. package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +18 -1
  213. package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +65 -21
  214. package/src/cmp/Entity.ts +5 -1
  215. package/src/cmp/Feature.ts +2 -1
  216. package/src/helpers/canonType.ts +8 -3
  217. package/src/helpers/collectDeps.ts +39 -12
  218. package/src/helpers/naming.ts +59 -0
  219. package/src/helpers/opShape.ts +99 -12
  220. package/src/sdkgen.ts +7 -3
@@ -0,0 +1,134 @@
1
+ /- JSON reader: String -> struct `Value`.
2
+ The runtime parses HTTP response bodies into the vendored voxgig-struct
3
+ `Value` model (VoxgigStruct.lean), so specs/options/payloads/results are all
4
+ the same reference-stable node type — exactly as the Python/Go SDKs pass
5
+ `map[string]any` around. Serialisation back to a String is `stringify`
6
+ (VoxgigStruct). -/
7
+
8
+ import VoxgigStruct
9
+
10
+ open VoxgigStruct
11
+
12
+ namespace SdkJson
13
+
14
+ structure JState where
15
+ src : Array Char
16
+ pos : Nat
17
+
18
+ partial def jPeek (s : JState) : Option Char := s.src[s.pos]?
19
+
20
+ partial def jSkipWs (s : JState) : JState := Id.run do
21
+ let mut p := s.pos
22
+ while p < s.src.size &&
23
+ (s.src[p]! == ' ' || s.src[p]! == '\t' || s.src[p]! == '\n' || s.src[p]! == '\r') do
24
+ p := p + 1
25
+ return { s with pos := p }
26
+
27
+ partial def jStr (s0 : JState) : SIO (String × JState) := do
28
+ let src := s0.src
29
+ let mut p := s0.pos + 1
30
+ let mut b := ""
31
+ repeat do
32
+ if p >= src.size then break
33
+ let c := src[p]!
34
+ p := p + 1
35
+ if c == '"' then break
36
+ if c == '\\' then
37
+ let e := src[p]!
38
+ p := p + 1
39
+ match e with
40
+ | '"' => b := b.push '"'
41
+ | '\\' => b := b.push '\\'
42
+ | '/' => b := b.push '/'
43
+ | 'n' => b := b.push '\n'
44
+ | 't' => b := b.push '\t'
45
+ | 'r' => b := b.push '\r'
46
+ | 'b' => b := b.push '\x08'
47
+ | 'f' => b := b.push '\x0c'
48
+ | 'u' => do
49
+ let mut code : Nat := 0
50
+ for _ in [0:4] do
51
+ let h := src[p]!
52
+ p := p + 1
53
+ let d :=
54
+ if h >= '0' && h <= '9' then h.toNat - '0'.toNat
55
+ else if h >= 'a' && h <= 'f' then 10 + h.toNat - 'a'.toNat
56
+ else if h >= 'A' && h <= 'F' then 10 + h.toNat - 'A'.toNat
57
+ else 0
58
+ code := code * 16 + d
59
+ b := b.push (Char.ofNat code)
60
+ | c => b := b.push c
61
+ else
62
+ b := b.push c
63
+ return (b, { s0 with pos := p })
64
+
65
+ mutual
66
+
67
+ partial def jVal (s0 : JState) : SIO (Value × JState) := do
68
+ let s := jSkipWs s0
69
+ match jPeek s with
70
+ | some '{' => jObj s
71
+ | some '[' => jArr s
72
+ | some '"' => do
73
+ let (str, s') ← jStr s
74
+ pure (.str str, s')
75
+ | some 't' => pure (.bool true, { s with pos := s.pos + 4 })
76
+ | some 'f' => pure (.bool false, { s with pos := s.pos + 5 })
77
+ | some 'n' => pure (.null, { s with pos := s.pos + 4 })
78
+ | _ => jNum s
79
+
80
+ partial def jObj (s0 : JState) : SIO (Value × JState) := do
81
+ let s := jSkipWs { s0 with pos := s0.pos + 1 }
82
+ if jPeek s == some '}' then
83
+ pure (← emptyMap, { s with pos := s.pos + 1 })
84
+ else do
85
+ let m ← emptyMap
86
+ let sRef ← IO.mkRef s
87
+ repeat do
88
+ let s1 := jSkipWs (← sRef.get)
89
+ let (k, s2) ← jStr s1
90
+ let s3 := jSkipWs s2
91
+ let s4 := { s3 with pos := s3.pos + 1 } -- ':'
92
+ let (v, s5) ← jVal s4
93
+ let _ ← setprop m (.str k) v
94
+ let s6 := jSkipWs s5
95
+ let c := (jPeek s6).getD '}'
96
+ sRef.set { s6 with pos := s6.pos + 1 }
97
+ if c != ',' then break
98
+ pure (m, ← sRef.get)
99
+
100
+ partial def jArr (s0 : JState) : SIO (Value × JState) := do
101
+ let s := jSkipWs { s0 with pos := s0.pos + 1 }
102
+ if jPeek s == some ']' then
103
+ pure (← emptyList, { s with pos := s.pos + 1 })
104
+ else do
105
+ let sRef ← IO.mkRef s
106
+ let accRef ← IO.mkRef (#[] : Array Value)
107
+ repeat do
108
+ let (v, s1) ← jVal (← sRef.get)
109
+ accRef.modify (·.push v)
110
+ let s2 := jSkipWs s1
111
+ let c := (jPeek s2).getD ']'
112
+ sRef.set { s2 with pos := s2.pos + 1 }
113
+ if c != ',' then break
114
+ pure (← newList (← accRef.get), ← sRef.get)
115
+
116
+ partial def jNum (s0 : JState) : SIO (Value × JState) := do
117
+ let src := s0.src
118
+ let mut p := s0.pos
119
+ let start := p
120
+ while p < src.size &&
121
+ (let c := src[p]!
122
+ (c >= '0' && c <= '9') || c == '-' || c == '+' || c == '.' || c == 'e' || c == 'E') do
123
+ p := p + 1
124
+ let tok := String.ofList (src.extract start p).toList
125
+ pure (.num ((parseFloatJS tok).getD 0.0), { s0 with pos := p })
126
+
127
+ end
128
+
129
+ /-- Parse a JSON string into a struct `Value` (empty/blank input -> noval). -/
130
+ def jsonRead (s : String) : SIO Value := do
131
+ if s.all (fun c => c == ' ' || c == '\n' || c == '\t' || c == '\r') then pure .noval
132
+ else pure (← jVal { src := s.toList.toArray, pos := 0 }).1
133
+
134
+ end SdkJson
@@ -0,0 +1,356 @@
1
+ /- ProjectName SDK runtime: the generic, config-driven operation pipeline.
2
+
3
+ Following the Haskell target's model, entities are NOT generated per-entity;
4
+ the whole SDK is driven by the API model (a struct `Value` parsed from the
5
+ embedded config). A client holds `options` + `config`; an operation looks up
6
+ `config.entity.<name>.op.<op>.points`, selects the matching endpoint, builds
7
+ the URL/method/body, calls the `curl` transport, parses the JSON response,
8
+ and applies the response transform.
9
+
10
+ The struct `Value` is the single data model throughout (like map[string]any
11
+ in the Go/Python SDKs); everything runs in struct's `SIO` monad. -/
12
+
13
+ import VoxgigStruct
14
+ import SdkJson
15
+ import SdkUtility
16
+ import SdkFeature
17
+ import SdkFeatures
18
+
19
+ open VoxgigStruct
20
+
21
+ namespace SdkRuntime
22
+
23
+ /-- Pure string view of a scalar Value. -/
24
+ def asStr : Value → String
25
+ | .str s => s
26
+ | _ => ""
27
+
28
+ def isNv : Value → Bool
29
+ | .noval => true
30
+ | .null => true
31
+ | _ => false
32
+
33
+ /-- Get a map field by string key (noval if absent). -/
34
+ def gp (v : Value) (k : String) : SIO Value := getprop v (.str k) .noval
35
+
36
+ def gpS (v : Value) (k : String) : SIO String := do pure (asStr (← gp v k))
37
+
38
+ -- ---------------------------------------------------------------------------
39
+ -- Transport: shell out to curl. Returns (status, body).
40
+ -- ---------------------------------------------------------------------------
41
+
42
+ def curlFetch (method url : String) (body : Option String) : IO (Nat × String) := do
43
+ let base := #["-s", "-w", "\n%{http_code}", "--max-time", "20", "-X", method]
44
+ let hdr := if body.isSome then #["-H", "Content-Type: application/json"] else #[]
45
+ let dat := match body with | some b => #["-d", b] | none => #[]
46
+ let out ← IO.Process.output { cmd := "curl", args := base ++ hdr ++ dat ++ #[url] }
47
+ if out.exitCode != 0 then
48
+ throw (IO.userError s!"curl failed ({out.exitCode}): {out.stderr}")
49
+ let lines := out.stdout.splitOn "\n"
50
+ let status := (lines.getLastD "0").toNat!
51
+ let bodyStr := String.intercalate "\n" lines.dropLast
52
+ return (status, bodyStr)
53
+
54
+ -- ---------------------------------------------------------------------------
55
+ -- Point selection (mirrors SdkRuntime.hs prepareOperation): all select.exist
56
+ -- keys must be present in match/data, and select.$action must equal the
57
+ -- caller's $action (both absent = the plain point).
58
+ -- ---------------------------------------------------------------------------
59
+
60
+ def existOk (point matchV dataV : Value) : SIO Bool := do
61
+ let sel ← gp point "select"
62
+ match (← gp sel "exist") with
63
+ | .list id => do
64
+ let mut ok := true
65
+ for ek in (← listItems id) do
66
+ let k := asStr ek
67
+ if isNv (← gp matchV k) && isNv (← gp dataV k) then ok := false
68
+ pure ok
69
+ | _ => pure true
70
+
71
+ def actionOk (point matchV : Value) : SIO Bool := do
72
+ let sel ← gp point "select"
73
+ pure ((← gp sel "$action") == (← gp matchV "$action"))
74
+
75
+ def selectPoint (points matchV dataV : Value) : SIO Value := do
76
+ match points with
77
+ | .list id => do
78
+ let pts ← listItems id
79
+ if pts.size == 1 then pure pts[0]!
80
+ else do
81
+ for pt in pts do
82
+ if (← existOk pt matchV dataV) && (← actionOk pt matchV) then return pt
83
+ pure .noval
84
+ | _ => pure .noval
85
+
86
+ -- ---------------------------------------------------------------------------
87
+ -- Request building + response transform.
88
+ -- ---------------------------------------------------------------------------
89
+
90
+ /-- Substitute a `{name}` path segment from match (falling back to data). -/
91
+ def resolvePart (seg : String) (matchV dataV : Value) : SIO String := do
92
+ if seg.startsWith "{" && seg.endsWith "}" then
93
+ let key := (seg.replace "{" "").replace "}" ""
94
+ let mv ← gp matchV key
95
+ let v ← if isNv mv then gp dataV key else pure mv
96
+ pure (asStr v)
97
+ else pure seg
98
+
99
+ def buildUrl (base : String) (point matchV dataV : Value) : SIO String := do
100
+ match (← gp point "parts") with
101
+ | .list id => do
102
+ let mut segs : Array String := #[]
103
+ for p in (← listItems id) do
104
+ segs := segs.push (← resolvePart (asStr p) matchV dataV)
105
+ pure (base ++ "/" ++ String.intercalate "/" segs.toList)
106
+ | _ => pure base
107
+
108
+ /-- Strip surrounding backticks from a transform expression. -/
109
+ def unquote (s : String) : String := s.replace "`" ""
110
+
111
+ /-- Apply transform.res: `body`, `body.entity`, etc. -/
112
+ def resTransform (point body : Value) : SIO Value := do
113
+ let tr ← gp point "transform"
114
+ let e := unquote (← gpS tr "res")
115
+ let segs := e.splitOn "."
116
+ let mut cur := body
117
+ for s in segs.drop 1 do
118
+ cur ← gp cur s
119
+ pure cur
120
+
121
+ -- ---------------------------------------------------------------------------
122
+ -- Test mode: an in-memory mock transport.
123
+ --
124
+ -- The `test` feature of the other targets seeds an entity store and answers
125
+ -- operations from it, so entity behaviour is verifiable with no server. The
126
+ -- store is `client.store.<entity>` : a map of id -> entity.
127
+ -- ---------------------------------------------------------------------------
128
+
129
+ /-- Every field of `matchV` must equal the entity's field. -/
130
+ def entMatches (ent matchV : Value) : SIO Bool := do
131
+ match matchV with
132
+ | .map i => do
133
+ let mut ok := true
134
+ for k in (← keysof (.map i)) do
135
+ let want ← gp (.map i) k
136
+ if !(isNv want) then
137
+ if !((← gp ent k) == want) then ok := false
138
+ pure ok
139
+ | _ => pure true
140
+
141
+ /-- Deterministic id for created entities (no clock/RNG in Lean). -/
142
+ def nextTestId (store : Value) : SIO String := do
143
+ let n ← gp store "__seq__"
144
+ let i := (match n with | .num f => f | _ => 0.0) + 1.0
145
+ let _ ← setprop store (.str "__seq__") (.num i)
146
+ pure ("t" ++ numToString i)
147
+
148
+ def mockOp (client : Value) (entityName opName : String)
149
+ (matchV dataV : Value) : SIO Value := do
150
+ let store ← gp client "store"
151
+ let entmap ← (match (← gp store entityName) with
152
+ | .map i => pure (Value.map i)
153
+ | _ => do let m ← emptyMap; let _ ← setprop store (.str entityName) m; pure m)
154
+ let idOf (v : Value) : SIO String := do pure (asStr (← gp v "id"))
155
+ match opName with
156
+ | "list" => do
157
+ let mut out : Array Value := #[]
158
+ for k in (← keysof entmap) do
159
+ let e ← gp entmap k
160
+ if (← entMatches e matchV) then out := out.push e
161
+ newList out
162
+ | "load" => do
163
+ let wid ← idOf matchV
164
+ pure ((← gp entmap wid))
165
+ | "remove" => do
166
+ let wid ← idOf matchV
167
+ let _ ← delprop entmap (.str wid)
168
+ emptyMap
169
+ | "create" => do
170
+ let ent ← clone dataV
171
+ let given ← idOf dataV
172
+ let eid ← if given != "" then pure given else nextTestId store
173
+ let _ ← setprop ent (.str "id") (.str eid)
174
+ let _ ← setprop entmap (.str eid) ent
175
+ pure ent
176
+ | "update" => do
177
+ let wid0 ← idOf dataV
178
+ let wid ← if wid0 != "" then pure wid0 else idOf matchV
179
+ let cur ← gp entmap wid
180
+ match cur with
181
+ | .map _ => do
182
+ for k in (← keysof dataV) do
183
+ let _ ← setprop cur (.str k) (← gp dataV k)
184
+ pure cur
185
+ | _ => emptyMap
186
+ | _ => emptyMap
187
+
188
+ -- ---------------------------------------------------------------------------
189
+ -- Feature wiring
190
+ --
191
+ -- The client carries: `featureopts` (name -> options), `features` (registry
192
+ -- indices, in add order) and `fetcher` (the head of the transport chain). Each
193
+ -- active feature's `init` wraps the current fetcher, so the LAST feature added
194
+ -- is outermost; the base of the chain is the mock (test mode) or curl (live).
195
+ -- ---------------------------------------------------------------------------
196
+
197
+ /-- The base transport: curl for a live client. -/
198
+ def liveFetcher : SdkFeature.Fetcher := fun _ctx url fetchdef => do
199
+ let method := asStr (← gp fetchdef "method")
200
+ let bodyV ← gp fetchdef "body"
201
+ let bodyStr ← if isNv bodyV then pure none else (do pure (some (← jsonify bodyV)))
202
+ let (st, respBody) ← curlFetch (if method == "" then "GET" else method) url bodyStr
203
+ let json ← SdkJson.jsonRead respBody
204
+ let resp ← newMap #[("status", .num st.toFloat), ("statusText", .str "OK"),
205
+ ("body", json), ("headers", ← emptyMap)]
206
+ pure (resp, none)
207
+
208
+ /-- The base transport in test mode: answer from the seeded store. -/
209
+ def testFetcher : SdkFeature.Fetcher := fun ctx _url _fetchdef => do
210
+ let client ← gp ctx "client"
211
+ let entityName ← gpS (← gp ctx "op") "entity"
212
+ let opName ← gpS (← gp ctx "op") "name"
213
+ let matchV ← gp ctx "reqmatch"
214
+ let dataV ← gp ctx "reqdata"
215
+ let out ← mockOp client entityName opName matchV dataV
216
+ let resp ← newMap #[("status", .num 200.0), ("statusText", .str "OK"),
217
+ ("body", out), ("headers", ← emptyMap)]
218
+ pure (resp, none)
219
+
220
+ /-- Merge config.feature and options.feature into the client's feature options. -/
221
+ def resolveFeatureOpts (client : Value) : SIO Value := do
222
+ let config ← gp client "config"
223
+ let options ← gp client "options"
224
+ let cf ← (match (← gp config "feature") with | .map i => pure (Value.map i) | _ => emptyMap)
225
+ let of0 ← (match (← gp options "feature") with | .map i => pure (Value.map i) | _ => emptyMap)
226
+ let merged ← merge (← newList #[cf, of0])
227
+ let fo ← (match merged with | .map i => pure (Value.map i) | _ => emptyMap)
228
+ SdkUtility.sp client "featureopts" fo
229
+ pure fo
230
+
231
+ /-- Construct and initialise every configured feature for this client. -/
232
+ def initFeatures (client : Value) : SIO Unit := do
233
+ let fo ← resolveFeatureOpts client
234
+ let baseF := if (← gpS client "mode") == "test" then testFetcher else liveFetcher
235
+ SdkFeature.setFetcher client baseF
236
+ let ctx ← newMap #[("client", client)]
237
+ let mut ids : Array Value := #[]
238
+ for name in SdkFeatures.featureNames do
239
+ let opts ← gp fo name
240
+ if (← SdkFeature.optActive opts) then do
241
+ let f ← SdkFeatures.makeFeature name
242
+ let id ← SdkFeature.registerFeature f
243
+ ids := ids.push (.num id.toFloat)
244
+ f.init ctx opts
245
+ SdkUtility.sp client "features" (← newList ids)
246
+
247
+ -- ---------------------------------------------------------------------------
248
+ -- The generic operation, with feature hooks at every pipeline stage.
249
+ -- ---------------------------------------------------------------------------
250
+
251
+ def runOp (client : Value) (entityName opName : String)
252
+ (matchV dataV _callopts : Value) : SIO Value := do
253
+ let options ← gp client "options"
254
+ let config ← gp client "config"
255
+ let op ← newMap #[("name", .str opName), ("entity", .str entityName),
256
+ ("input", .str (SdkUtility.opInputOf opName))]
257
+ let out ← emptyMap
258
+ let ctx ← newMap #[("client", client), ("options", options), ("config", config),
259
+ ("opname", .str opName), ("op", op), ("out", out),
260
+ ("reqmatch", matchV), ("reqdata", dataV),
261
+ ("match", matchV), ("data", dataV)]
262
+ let _ ← SdkUtility.makeResult ctx
263
+
264
+ -- PrePoint: a feature may short-circuit here (rbac denies by setting out.point).
265
+ SdkFeature.dispatch client "PrePoint" ctx
266
+ let denied ← gp out "point"
267
+ if (← SdkUtility.isErrV denied) then
268
+ throw (IO.userError (← gpS denied "message"))
269
+
270
+ let ent ← gp (← gp config "entity") entityName
271
+ let opcfg ← gp (← gp ent "op") opName
272
+ let point ← selectPoint (← gp opcfg "points") matchV dataV
273
+ if isNv point then
274
+ throw (IO.userError s!"Operation \"{opName}\" has no matching endpoint for {entityName}.")
275
+ SdkUtility.sp ctx "point" point
276
+
277
+ -- PreSpec: build the request description.
278
+ let userBase ← gpS options "base"
279
+ let base ← if userBase != "" then pure userBase
280
+ else gpS (← gp config "options") "base"
281
+ let url ← buildUrl base point matchV dataV
282
+ let method ← gpS point "method"
283
+ let headers ← SdkUtility.prepareHeaders ctx
284
+ let spec ← newMap #[("base", .str base), ("method", .str method),
285
+ ("headers", headers), ("step", .str "start")]
286
+ SdkUtility.sp ctx "spec" spec
287
+ SdkUtility.sp spec "query" (← emptyMap)
288
+ SdkFeature.dispatch client "PreSpec" ctx
289
+
290
+ let hasBody := method == "POST" || method == "PUT" || method == "PATCH"
291
+ if hasBody then SdkUtility.sp spec "body" dataV
292
+
293
+ -- PreRequest: last chance to alter headers/transport (idempotency, clienttrack).
294
+ SdkFeature.dispatch client "PreRequest" ctx
295
+
296
+ let fetchdef ← SdkUtility.makeFetchDef ctx
297
+ let fetch ← SdkFeature.getFetcher client
298
+ let (resp, ferr) ← fetch ctx url fetchdef
299
+ match ferr with
300
+ | some e => throw (IO.userError (← gpS e "message"))
301
+ | none => pure ()
302
+ SdkUtility.sp ctx "response" resp
303
+
304
+ -- PreResponse / PreResult: fold the response into the result.
305
+ SdkFeature.dispatch client "PreResponse" ctx
306
+ let body ← gp resp "body"
307
+ let resdata ← resTransform point body
308
+ let result ← gp ctx "result"
309
+ SdkUtility.sp result "body" body
310
+ SdkUtility.sp result "resdata" resdata
311
+ SdkUtility.sp result "status" (← gp resp "status")
312
+ SdkUtility.sp result "ok" (.bool true)
313
+ SdkFeature.dispatch client "PreResult" ctx
314
+
315
+ -- PreDone: metrics/telemetry/audit close out here.
316
+ SdkFeature.dispatch client "PreDone" ctx
317
+ pure resdata
318
+
319
+ -- Entity operation wrappers.
320
+ def opList (c : Value) (e : String) (m co : Value) : SIO Value := do runOp c e "list" m (← emptyMap) co
321
+ def opLoad (c : Value) (e : String) (m co : Value) : SIO Value := do runOp c e "load" m (← emptyMap) co
322
+ def opCreate (c : Value) (e : String) (d co : Value) : SIO Value := do runOp c e "create" (← emptyMap) d co
323
+ def opUpdate (c : Value) (e : String) (m d co : Value) : SIO Value := do runOp c e "update" m d co
324
+ def opRemove (c : Value) (e : String) (m co : Value) : SIO Value := do runOp c e "remove" m (← emptyMap) co
325
+
326
+ /-- Build a client Value from options + config JSON strings. -/
327
+ def mkClient (optionsJson configJson : String) : SIO Value := do
328
+ let options ← SdkJson.jsonRead optionsJson
329
+ let config ← SdkJson.jsonRead configJson
330
+ let c ← newMap #[("options", options), ("config", config), ("mode", .str "live")]
331
+ initFeatures c
332
+ pure c
333
+
334
+ /-- Build a client from an options `Value` (the generated `newSdk` entry). -/
335
+ def mkClientV (options : Value) (configJson : String) : SIO Value := do
336
+ let opts ← (match options with | .map _ => pure options | _ => emptyMap)
337
+ let config ← SdkJson.jsonRead configJson
338
+ let c ← newMap #[("options", opts), ("config", config), ("mode", .str "live")]
339
+ initFeatures c
340
+ pure c
341
+
342
+ /-- A test-mode client: operations are answered from an in-memory store seeded
343
+ with the entity test data, so entity behaviour is verifiable offline. -/
344
+ def mkTestClientV (options : Value) (configJson : String) (seed : Value) : SIO Value := do
345
+ let opts ← (match options with | .map _ => pure options | _ => emptyMap)
346
+ let config ← SdkJson.jsonRead configJson
347
+ let existing ← gp seed "existing"
348
+ let store ← (match existing with
349
+ | .map _ => clone existing
350
+ | _ => emptyMap)
351
+ let c ← newMap #[("options", opts), ("config", config), ("mode", .str "test"),
352
+ ("store", store)]
353
+ initFeatures c
354
+ pure c
355
+
356
+ end SdkRuntime