@voxgig/sdkgen 1.3.8 → 1.3.9

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 (1730) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/package.json +1 -1
  3. package/project/.sdk/model/feature/audit.aontu +22 -0
  4. package/project/.sdk/model/feature/cache.aontu +23 -0
  5. package/project/.sdk/model/feature/clienttrack.aontu +20 -0
  6. package/project/.sdk/model/feature/debug.aontu +25 -0
  7. package/project/.sdk/model/feature/feature-index.aontu +20 -1
  8. package/project/.sdk/model/feature/idempotency.aontu +21 -0
  9. package/project/.sdk/model/feature/metrics.aontu +20 -0
  10. package/project/.sdk/model/feature/netsim.aontu +36 -0
  11. package/project/.sdk/model/feature/paging.aontu +23 -0
  12. package/project/.sdk/model/feature/proxy.aontu +23 -0
  13. package/project/.sdk/model/feature/ratelimit.aontu +21 -0
  14. package/project/.sdk/model/feature/rbac.aontu +24 -0
  15. package/project/.sdk/model/feature/retry.aontu +23 -0
  16. package/project/.sdk/model/feature/streaming.aontu +22 -0
  17. package/project/.sdk/model/feature/telemetry.aontu +21 -0
  18. package/project/.sdk/model/feature/timeout.aontu +18 -0
  19. package/project/.sdk/model/target/c.aontu +37 -0
  20. package/project/.sdk/model/target/clojure.aontu +36 -0
  21. package/project/.sdk/model/target/cpp.aontu +35 -0
  22. package/project/.sdk/model/target/csharp.aontu +35 -0
  23. package/project/.sdk/model/target/dart.aontu +34 -0
  24. package/project/.sdk/model/target/elixir.aontu +33 -0
  25. package/project/.sdk/model/target/haskell.aontu +47 -0
  26. package/project/.sdk/model/target/java.aontu +37 -0
  27. package/project/.sdk/model/target/kotlin.aontu +37 -0
  28. package/project/.sdk/model/target/ocaml.aontu +36 -0
  29. package/project/.sdk/model/target/perl.aontu +37 -0
  30. package/project/.sdk/model/target/rust.aontu +37 -0
  31. package/project/.sdk/model/target/scala.aontu +37 -0
  32. package/project/.sdk/model/target/swift.aontu +35 -0
  33. package/project/.sdk/model/target/zig.aontu +27 -0
  34. package/project/.sdk/src/cmp/c/Config_c.ts +109 -0
  35. package/project/.sdk/src/cmp/c/EntityBase_c.ts +61 -0
  36. package/project/.sdk/src/cmp/c/EntityOperation_c.ts +41 -0
  37. package/project/.sdk/src/cmp/c/Entity_c.ts +85 -0
  38. package/project/.sdk/src/cmp/c/Gitignore_c.ts +29 -0
  39. package/project/.sdk/src/cmp/c/MainEntity_c.ts +31 -0
  40. package/project/.sdk/src/cmp/c/Main_c.ts +83 -0
  41. package/project/.sdk/src/cmp/c/Package_c.ts +17 -0
  42. package/project/.sdk/src/cmp/c/TestDirect_c.ts +227 -0
  43. package/project/.sdk/src/cmp/c/TestEntity_c.ts +82 -0
  44. package/project/.sdk/src/cmp/c/Test_c.ts +51 -0
  45. package/project/.sdk/src/cmp/c/fragment/Entity.fragment.c +265 -0
  46. package/project/.sdk/src/cmp/c/fragment/EntityCreateOp.fragment.c +27 -0
  47. package/project/.sdk/src/cmp/c/fragment/EntityListOp.fragment.c +24 -0
  48. package/project/.sdk/src/cmp/c/fragment/EntityLoadOp.fragment.c +29 -0
  49. package/project/.sdk/src/cmp/c/fragment/EntityRemoveOp.fragment.c +29 -0
  50. package/project/.sdk/src/cmp/c/fragment/EntityUpdateOp.fragment.c +29 -0
  51. package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +220 -0
  52. package/project/.sdk/src/cmp/c/tsconfig.json +15 -0
  53. package/project/.sdk/src/cmp/c/utility_c.ts +102 -0
  54. package/project/.sdk/src/cmp/clojure/Config_clojure.ts +94 -0
  55. package/project/.sdk/src/cmp/clojure/EntityOperation_clojure.ts +35 -0
  56. package/project/.sdk/src/cmp/clojure/Entity_clojure.ts +77 -0
  57. package/project/.sdk/src/cmp/clojure/Gitignore_clojure.ts +28 -0
  58. package/project/.sdk/src/cmp/clojure/MainEntity_clojure.ts +21 -0
  59. package/project/.sdk/src/cmp/clojure/Main_clojure.ts +88 -0
  60. package/project/.sdk/src/cmp/clojure/Package_clojure.ts +41 -0
  61. package/project/.sdk/src/cmp/clojure/Test_clojure.ts +120 -0
  62. package/project/.sdk/src/cmp/clojure/fragment/Entity.fragment.clj +158 -0
  63. package/project/.sdk/src/cmp/clojure/fragment/EntityCreateOp.fragment.clj +14 -0
  64. package/project/.sdk/src/cmp/clojure/fragment/EntityListOp.fragment.clj +17 -0
  65. package/project/.sdk/src/cmp/clojure/fragment/EntityLoadOp.fragment.clj +15 -0
  66. package/project/.sdk/src/cmp/clojure/fragment/EntityRemoveOp.fragment.clj +15 -0
  67. package/project/.sdk/src/cmp/clojure/fragment/EntityUpdateOp.fragment.clj +15 -0
  68. package/project/.sdk/src/cmp/clojure/tsconfig.json +15 -0
  69. package/project/.sdk/src/cmp/clojure/utility_clojure.ts +82 -0
  70. package/project/.sdk/src/cmp/cpp/Config_cpp.ts +136 -0
  71. package/project/.sdk/src/cmp/cpp/EntityBase_cpp.ts +51 -0
  72. package/project/.sdk/src/cmp/cpp/EntityOperation_cpp.ts +37 -0
  73. package/project/.sdk/src/cmp/cpp/Entity_cpp.ts +78 -0
  74. package/project/.sdk/src/cmp/cpp/Gitignore_cpp.ts +27 -0
  75. package/project/.sdk/src/cmp/cpp/MainEntity_cpp.ts +35 -0
  76. package/project/.sdk/src/cmp/cpp/Main_cpp.ts +84 -0
  77. package/project/.sdk/src/cmp/cpp/Package_cpp.ts +17 -0
  78. package/project/.sdk/src/cmp/cpp/TestDirect_cpp.ts +258 -0
  79. package/project/.sdk/src/cmp/cpp/TestEntity_cpp.ts +454 -0
  80. package/project/.sdk/src/cmp/cpp/Test_cpp.ts +36 -0
  81. package/project/.sdk/src/cmp/cpp/fragment/Entity.fragment.cpp +40 -0
  82. package/project/.sdk/src/cmp/cpp/fragment/EntityCreateOp.fragment.cpp +22 -0
  83. package/project/.sdk/src/cmp/cpp/fragment/EntityListOp.fragment.cpp +21 -0
  84. package/project/.sdk/src/cmp/cpp/fragment/EntityLoadOp.fragment.cpp +25 -0
  85. package/project/.sdk/src/cmp/cpp/fragment/EntityRemoveOp.fragment.cpp +21 -0
  86. package/project/.sdk/src/cmp/cpp/fragment/EntityUpdateOp.fragment.cpp +22 -0
  87. package/project/.sdk/src/cmp/cpp/fragment/Main.fragment.cpp +43 -0
  88. package/project/.sdk/src/cmp/cpp/tsconfig.json +15 -0
  89. package/project/.sdk/src/cmp/cpp/utility_cpp.ts +83 -0
  90. package/project/.sdk/src/cmp/csharp/Config_csharp.ts +134 -0
  91. package/project/.sdk/src/cmp/csharp/EntityBase_csharp.ts +39 -0
  92. package/project/.sdk/src/cmp/csharp/EntityOperation_csharp.ts +41 -0
  93. package/project/.sdk/src/cmp/csharp/Entity_csharp.ts +85 -0
  94. package/project/.sdk/src/cmp/csharp/Gitignore_csharp.ts +38 -0
  95. package/project/.sdk/src/cmp/csharp/MainEntity_csharp.ts +36 -0
  96. package/project/.sdk/src/cmp/csharp/Main_csharp.ts +91 -0
  97. package/project/.sdk/src/cmp/csharp/Package_csharp.ts +101 -0
  98. package/project/.sdk/src/cmp/csharp/SdkError_csharp.ts +42 -0
  99. package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +560 -0
  100. package/project/.sdk/src/cmp/csharp/TestEntity_csharp.ts +618 -0
  101. package/project/.sdk/src/cmp/csharp/Test_csharp.ts +38 -0
  102. package/project/.sdk/src/cmp/csharp/fragment/Entity.fragment.cs +28 -0
  103. package/project/.sdk/src/cmp/csharp/fragment/EntityBase.fragment.cs +268 -0
  104. package/project/.sdk/src/cmp/csharp/fragment/EntityCreateOp.fragment.cs +37 -0
  105. package/project/.sdk/src/cmp/csharp/fragment/EntityListOp.fragment.cs +35 -0
  106. package/project/.sdk/src/cmp/csharp/fragment/EntityLoadOp.fragment.cs +41 -0
  107. package/project/.sdk/src/cmp/csharp/fragment/EntityRemoveOp.fragment.cs +41 -0
  108. package/project/.sdk/src/cmp/csharp/fragment/EntityUpdateOp.fragment.cs +41 -0
  109. package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +278 -0
  110. package/project/.sdk/src/cmp/csharp/fragment/SdkError.fragment.cs +21 -0
  111. package/project/.sdk/src/cmp/csharp/tsconfig.json +15 -0
  112. package/project/.sdk/src/cmp/csharp/utility_csharp.ts +143 -0
  113. package/project/.sdk/src/cmp/dart/Config_dart.ts +99 -0
  114. package/project/.sdk/src/cmp/dart/EntityBase_dart.ts +34 -0
  115. package/project/.sdk/src/cmp/dart/EntityOperation_dart.ts +43 -0
  116. package/project/.sdk/src/cmp/dart/EntityTypes_dart.ts +190 -0
  117. package/project/.sdk/src/cmp/dart/Entity_dart.ts +79 -0
  118. package/project/.sdk/src/cmp/dart/Gitignore_dart.ts +34 -0
  119. package/project/.sdk/src/cmp/dart/MainEntity_dart.ts +33 -0
  120. package/project/.sdk/src/cmp/dart/Main_dart.ts +105 -0
  121. package/project/.sdk/src/cmp/dart/Package_dart.ts +81 -0
  122. package/project/.sdk/src/cmp/dart/SdkError_dart.ts +42 -0
  123. package/project/.sdk/src/cmp/dart/TestDirect_dart.ts +498 -0
  124. package/project/.sdk/src/cmp/dart/TestEntity_dart.ts +552 -0
  125. package/project/.sdk/src/cmp/dart/Test_dart.ts +105 -0
  126. package/project/.sdk/src/cmp/dart/fragment/Config.fragment.dart +48 -0
  127. package/project/.sdk/src/cmp/dart/fragment/Direct.test.fragment.dart +25 -0
  128. package/project/.sdk/src/cmp/dart/fragment/Entity.fragment.dart +31 -0
  129. package/project/.sdk/src/cmp/dart/fragment/Entity.test.fragment.dart +67 -0
  130. package/project/.sdk/src/cmp/dart/fragment/EntityBase.fragment.dart +285 -0
  131. package/project/.sdk/src/cmp/dart/fragment/EntityCreateOp.fragment.dart +90 -0
  132. package/project/.sdk/src/cmp/dart/fragment/EntityListOp.fragment.dart +90 -0
  133. package/project/.sdk/src/cmp/dart/fragment/EntityLoadOp.fragment.dart +94 -0
  134. package/project/.sdk/src/cmp/dart/fragment/EntityRemoveOp.fragment.dart +94 -0
  135. package/project/.sdk/src/cmp/dart/fragment/EntityUpdateOp.fragment.dart +94 -0
  136. package/project/.sdk/src/cmp/dart/fragment/Main.fragment.dart +240 -0
  137. package/project/.sdk/src/cmp/dart/fragment/SdkError.fragment.dart +18 -0
  138. package/project/.sdk/src/cmp/dart/tsconfig.json +15 -0
  139. package/project/.sdk/src/cmp/dart/utility_dart.ts +86 -0
  140. package/project/.sdk/src/cmp/elixir/Config_elixir.ts +101 -0
  141. package/project/.sdk/src/cmp/elixir/EntityOperation_elixir.ts +27 -0
  142. package/project/.sdk/src/cmp/elixir/Entity_elixir.ts +54 -0
  143. package/project/.sdk/src/cmp/elixir/Gitignore_elixir.ts +28 -0
  144. package/project/.sdk/src/cmp/elixir/MainEntity_elixir.ts +26 -0
  145. package/project/.sdk/src/cmp/elixir/Main_elixir.ts +124 -0
  146. package/project/.sdk/src/cmp/elixir/Package_elixir.ts +64 -0
  147. package/project/.sdk/src/cmp/elixir/TestDirect_elixir.ts +95 -0
  148. package/project/.sdk/src/cmp/elixir/TestEntity_elixir.ts +115 -0
  149. package/project/.sdk/src/cmp/elixir/Test_elixir.ts +47 -0
  150. package/project/.sdk/src/cmp/elixir/fragment/Entity.fragment.ex +37 -0
  151. package/project/.sdk/src/cmp/elixir/fragment/EntityCreateOp.fragment.ex +28 -0
  152. package/project/.sdk/src/cmp/elixir/fragment/EntityListOp.fragment.ex +30 -0
  153. package/project/.sdk/src/cmp/elixir/fragment/EntityLoadOp.fragment.ex +32 -0
  154. package/project/.sdk/src/cmp/elixir/fragment/EntityRemoveOp.fragment.ex +32 -0
  155. package/project/.sdk/src/cmp/elixir/fragment/EntityUpdateOp.fragment.ex +30 -0
  156. package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +218 -0
  157. package/project/.sdk/src/cmp/elixir/fragment/Pipeline.fragment.ex +62 -0
  158. package/project/.sdk/src/cmp/elixir/tsconfig.json +15 -0
  159. package/project/.sdk/src/cmp/elixir/utility_elixir.ts +85 -0
  160. package/project/.sdk/src/cmp/go/TestEntity_go.ts +54 -0
  161. package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +133 -0
  162. package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +14 -8
  163. package/project/.sdk/src/cmp/haskell/Config_haskell.ts +115 -0
  164. package/project/.sdk/src/cmp/haskell/Entity_haskell.ts +13 -0
  165. package/project/.sdk/src/cmp/haskell/Gitignore_haskell.ts +27 -0
  166. package/project/.sdk/src/cmp/haskell/Main_haskell.ts +123 -0
  167. package/project/.sdk/src/cmp/haskell/Package_haskell.ts +58 -0
  168. package/project/.sdk/src/cmp/haskell/Test_haskell.ts +263 -0
  169. package/project/.sdk/src/cmp/haskell/tsconfig.json +15 -0
  170. package/project/.sdk/src/cmp/haskell/utility_haskell.ts +105 -0
  171. package/project/.sdk/src/cmp/java/Config_java.ts +138 -0
  172. package/project/.sdk/src/cmp/java/EntityBase_java.ts +50 -0
  173. package/project/.sdk/src/cmp/java/EntityOperation_java.ts +48 -0
  174. package/project/.sdk/src/cmp/java/Entity_java.ts +95 -0
  175. package/project/.sdk/src/cmp/java/Gitignore_java.ts +37 -0
  176. package/project/.sdk/src/cmp/java/MainEntity_java.ts +41 -0
  177. package/project/.sdk/src/cmp/java/Main_java.ts +100 -0
  178. package/project/.sdk/src/cmp/java/Package_java.ts +126 -0
  179. package/project/.sdk/src/cmp/java/SdkError_java.ts +49 -0
  180. package/project/.sdk/src/cmp/java/TestDirect_java.ts +509 -0
  181. package/project/.sdk/src/cmp/java/TestEntity_java.ts +599 -0
  182. package/project/.sdk/src/cmp/java/Test_java.ts +42 -0
  183. package/project/.sdk/src/cmp/java/fragment/Entity.fragment.java +35 -0
  184. package/project/.sdk/src/cmp/java/fragment/EntityBase.fragment.java +235 -0
  185. package/project/.sdk/src/cmp/java/fragment/EntityCreateOp.fragment.java +42 -0
  186. package/project/.sdk/src/cmp/java/fragment/EntityListOp.fragment.java +39 -0
  187. package/project/.sdk/src/cmp/java/fragment/EntityLoadOp.fragment.java +45 -0
  188. package/project/.sdk/src/cmp/java/fragment/EntityRemoveOp.fragment.java +45 -0
  189. package/project/.sdk/src/cmp/java/fragment/EntityUpdateOp.fragment.java +45 -0
  190. package/project/.sdk/src/cmp/java/fragment/Main.fragment.java +34 -0
  191. package/project/.sdk/src/cmp/java/fragment/SdkError.fragment.java +27 -0
  192. package/project/.sdk/src/cmp/java/tsconfig.json +15 -0
  193. package/project/.sdk/src/cmp/java/utility_java.ts +102 -0
  194. package/project/.sdk/src/cmp/js/Config_js.ts +4 -2
  195. package/project/.sdk/src/cmp/js/TestEntity_js.ts +1 -0
  196. package/project/.sdk/src/cmp/js/fragment/Entity.test.fragment.js +32 -1
  197. package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +81 -0
  198. package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +10 -5
  199. package/project/.sdk/src/cmp/kotlin/Config_kotlin.ts +128 -0
  200. package/project/.sdk/src/cmp/kotlin/EntityBase_kotlin.ts +50 -0
  201. package/project/.sdk/src/cmp/kotlin/EntityOperation_kotlin.ts +48 -0
  202. package/project/.sdk/src/cmp/kotlin/Entity_kotlin.ts +93 -0
  203. package/project/.sdk/src/cmp/kotlin/Gitignore_kotlin.ts +41 -0
  204. package/project/.sdk/src/cmp/kotlin/MainEntity_kotlin.ts +40 -0
  205. package/project/.sdk/src/cmp/kotlin/Main_kotlin.ts +94 -0
  206. package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +110 -0
  207. package/project/.sdk/src/cmp/kotlin/SdkError_kotlin.ts +48 -0
  208. package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +479 -0
  209. package/project/.sdk/src/cmp/kotlin/TestEntity_kotlin.ts +567 -0
  210. package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +42 -0
  211. package/project/.sdk/src/cmp/kotlin/fragment/Entity.fragment.kt +28 -0
  212. package/project/.sdk/src/cmp/kotlin/fragment/EntityBase.fragment.kt +195 -0
  213. package/project/.sdk/src/cmp/kotlin/fragment/EntityCreateOp.fragment.kt +37 -0
  214. package/project/.sdk/src/cmp/kotlin/fragment/EntityListOp.fragment.kt +34 -0
  215. package/project/.sdk/src/cmp/kotlin/fragment/EntityLoadOp.fragment.kt +40 -0
  216. package/project/.sdk/src/cmp/kotlin/fragment/EntityRemoveOp.fragment.kt +40 -0
  217. package/project/.sdk/src/cmp/kotlin/fragment/EntityUpdateOp.fragment.kt +40 -0
  218. package/project/.sdk/src/cmp/kotlin/fragment/Main.fragment.kt +28 -0
  219. package/project/.sdk/src/cmp/kotlin/fragment/SdkError.fragment.kt +24 -0
  220. package/project/.sdk/src/cmp/kotlin/tsconfig.json +15 -0
  221. package/project/.sdk/src/cmp/kotlin/utility_kotlin.ts +101 -0
  222. package/project/.sdk/src/cmp/lua/Entity_lua.ts +7 -9
  223. package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +47 -0
  224. package/project/.sdk/src/cmp/lua/fragment/Entity.fragment.lua +137 -0
  225. package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +9 -6
  226. package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +114 -0
  227. package/project/.sdk/src/cmp/ocaml/EntityOperation_ocaml.ts +63 -0
  228. package/project/.sdk/src/cmp/ocaml/Entity_ocaml.ts +152 -0
  229. package/project/.sdk/src/cmp/ocaml/Gitignore_ocaml.ts +37 -0
  230. package/project/.sdk/src/cmp/ocaml/MainEntity_ocaml.ts +28 -0
  231. package/project/.sdk/src/cmp/ocaml/Main_ocaml.ts +111 -0
  232. package/project/.sdk/src/cmp/ocaml/Package_ocaml.ts +47 -0
  233. package/project/.sdk/src/cmp/ocaml/SdkError_ocaml.ts +42 -0
  234. package/project/.sdk/src/cmp/ocaml/TestDirect_ocaml.ts +47 -0
  235. package/project/.sdk/src/cmp/ocaml/TestEntity_ocaml.ts +130 -0
  236. package/project/.sdk/src/cmp/ocaml/Test_ocaml.ts +35 -0
  237. package/project/.sdk/src/cmp/ocaml/fragment/RunOp.fragment.ml +32 -0
  238. package/project/.sdk/src/cmp/ocaml/tsconfig.json +15 -0
  239. package/project/.sdk/src/cmp/ocaml/utility_ocaml.ts +129 -0
  240. package/project/.sdk/src/cmp/perl/Config_perl.ts +127 -0
  241. package/project/.sdk/src/cmp/perl/EntityOperation_perl.ts +42 -0
  242. package/project/.sdk/src/cmp/perl/Entity_perl.ts +84 -0
  243. package/project/.sdk/src/cmp/perl/Gitignore_perl.ts +32 -0
  244. package/project/.sdk/src/cmp/perl/MainEntity_perl.ts +34 -0
  245. package/project/.sdk/src/cmp/perl/Main_perl.ts +140 -0
  246. package/project/.sdk/src/cmp/perl/Package_perl.ts +63 -0
  247. package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +433 -0
  248. package/project/.sdk/src/cmp/perl/TestEntity_perl.ts +515 -0
  249. package/project/.sdk/src/cmp/perl/Test_perl.ts +54 -0
  250. package/project/.sdk/src/cmp/perl/fragment/Entity.fragment.pm +235 -0
  251. package/project/.sdk/src/cmp/perl/fragment/EntityCreateOp.fragment.pm +31 -0
  252. package/project/.sdk/src/cmp/perl/fragment/EntityListOp.fragment.pm +43 -0
  253. package/project/.sdk/src/cmp/perl/fragment/EntityLoadOp.fragment.pm +34 -0
  254. package/project/.sdk/src/cmp/perl/fragment/EntityRemoveOp.fragment.pm +32 -0
  255. package/project/.sdk/src/cmp/perl/fragment/EntityUpdateOp.fragment.pm +32 -0
  256. package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +263 -0
  257. package/project/.sdk/src/cmp/perl/fragment/SdkError.fragment.pm +27 -0
  258. package/project/.sdk/src/cmp/perl/tsconfig.json +15 -0
  259. package/project/.sdk/src/cmp/perl/utility_perl.ts +30 -0
  260. package/project/.sdk/src/cmp/php/TestEntity_php.ts +45 -0
  261. package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +124 -0
  262. package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +13 -6
  263. package/project/.sdk/src/cmp/py/Entity_py.ts +8 -9
  264. package/project/.sdk/src/cmp/py/TestEntity_py.ts +40 -0
  265. package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +135 -28
  266. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +9 -6
  267. package/project/.sdk/src/cmp/rb/Entity_rb.ts +8 -9
  268. package/project/.sdk/src/cmp/rb/ReadmeExamplesTest_rb.ts +4 -1
  269. package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +42 -0
  270. package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +122 -23
  271. package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +9 -6
  272. package/project/.sdk/src/cmp/rust/Config_rust.ts +118 -0
  273. package/project/.sdk/src/cmp/rust/EntityBase_rust.ts +59 -0
  274. package/project/.sdk/src/cmp/rust/EntityOperation_rust.ts +44 -0
  275. package/project/.sdk/src/cmp/rust/Entity_rust.ts +94 -0
  276. package/project/.sdk/src/cmp/rust/Gitignore_rust.ts +29 -0
  277. package/project/.sdk/src/cmp/rust/MainEntity_rust.ts +37 -0
  278. package/project/.sdk/src/cmp/rust/Main_rust.ts +146 -0
  279. package/project/.sdk/src/cmp/rust/Package_rust.ts +80 -0
  280. package/project/.sdk/src/cmp/rust/SdkError_rust.ts +42 -0
  281. package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +448 -0
  282. package/project/.sdk/src/cmp/rust/TestEntity_rust.ts +635 -0
  283. package/project/.sdk/src/cmp/rust/Test_rust.ts +51 -0
  284. package/project/.sdk/src/cmp/rust/fragment/Entity.fragment.rs +288 -0
  285. package/project/.sdk/src/cmp/rust/fragment/EntityCreateOp.fragment.rs +29 -0
  286. package/project/.sdk/src/cmp/rust/fragment/EntityListOp.fragment.rs +26 -0
  287. package/project/.sdk/src/cmp/rust/fragment/EntityLoadOp.fragment.rs +35 -0
  288. package/project/.sdk/src/cmp/rust/fragment/EntityRemoveOp.fragment.rs +35 -0
  289. package/project/.sdk/src/cmp/rust/fragment/EntityUpdateOp.fragment.rs +35 -0
  290. package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +296 -0
  291. package/project/.sdk/src/cmp/rust/fragment/SdkError.fragment.rs +34 -0
  292. package/project/.sdk/src/cmp/rust/tsconfig.json +15 -0
  293. package/project/.sdk/src/cmp/rust/utility_rust.ts +104 -0
  294. package/project/.sdk/src/cmp/scala/Config_scala.ts +126 -0
  295. package/project/.sdk/src/cmp/scala/EntityBase_scala.ts +50 -0
  296. package/project/.sdk/src/cmp/scala/EntityOperation_scala.ts +46 -0
  297. package/project/.sdk/src/cmp/scala/Entity_scala.ts +87 -0
  298. package/project/.sdk/src/cmp/scala/Gitignore_scala.ts +31 -0
  299. package/project/.sdk/src/cmp/scala/MainEntity_scala.ts +40 -0
  300. package/project/.sdk/src/cmp/scala/Main_scala.ts +93 -0
  301. package/project/.sdk/src/cmp/scala/Package_scala.ts +22 -0
  302. package/project/.sdk/src/cmp/scala/TestDirect_scala.ts +233 -0
  303. package/project/.sdk/src/cmp/scala/TestEntity_scala.ts +397 -0
  304. package/project/.sdk/src/cmp/scala/Test_scala.ts +93 -0
  305. package/project/.sdk/src/cmp/scala/fragment/Entity.fragment.scala +24 -0
  306. package/project/.sdk/src/cmp/scala/fragment/EntityBase.fragment.scala +169 -0
  307. package/project/.sdk/src/cmp/scala/fragment/EntityCreateOp.fragment.scala +32 -0
  308. package/project/.sdk/src/cmp/scala/fragment/EntityListOp.fragment.scala +28 -0
  309. package/project/.sdk/src/cmp/scala/fragment/EntityLoadOp.fragment.scala +33 -0
  310. package/project/.sdk/src/cmp/scala/fragment/EntityRemoveOp.fragment.scala +33 -0
  311. package/project/.sdk/src/cmp/scala/fragment/EntityUpdateOp.fragment.scala +33 -0
  312. package/project/.sdk/src/cmp/scala/fragment/Main.fragment.scala +27 -0
  313. package/project/.sdk/src/cmp/scala/tsconfig.json +15 -0
  314. package/project/.sdk/src/cmp/scala/utility_scala.ts +99 -0
  315. package/project/.sdk/src/cmp/swift/Config_swift.ts +127 -0
  316. package/project/.sdk/src/cmp/swift/EntityBase_swift.ts +38 -0
  317. package/project/.sdk/src/cmp/swift/EntityOperation_swift.ts +39 -0
  318. package/project/.sdk/src/cmp/swift/Entity_swift.ts +86 -0
  319. package/project/.sdk/src/cmp/swift/Gitignore_swift.ts +32 -0
  320. package/project/.sdk/src/cmp/swift/MainEntity_swift.ts +35 -0
  321. package/project/.sdk/src/cmp/swift/Main_swift.ts +94 -0
  322. package/project/.sdk/src/cmp/swift/Package_swift.ts +66 -0
  323. package/project/.sdk/src/cmp/swift/SdkError_swift.ts +41 -0
  324. package/project/.sdk/src/cmp/swift/TestDirect_swift.ts +84 -0
  325. package/project/.sdk/src/cmp/swift/TestEntity_swift.ts +84 -0
  326. package/project/.sdk/src/cmp/swift/Test_swift.ts +39 -0
  327. package/project/.sdk/src/cmp/swift/fragment/Entity.fragment.swift +23 -0
  328. package/project/.sdk/src/cmp/swift/fragment/EntityBase.fragment.swift +202 -0
  329. package/project/.sdk/src/cmp/swift/fragment/EntityCreateOp.fragment.swift +23 -0
  330. package/project/.sdk/src/cmp/swift/fragment/EntityListOp.fragment.swift +21 -0
  331. package/project/.sdk/src/cmp/swift/fragment/EntityLoadOp.fragment.swift +24 -0
  332. package/project/.sdk/src/cmp/swift/fragment/EntityRemoveOp.fragment.swift +24 -0
  333. package/project/.sdk/src/cmp/swift/fragment/EntityUpdateOp.fragment.swift +24 -0
  334. package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +211 -0
  335. package/project/.sdk/src/cmp/swift/fragment/SdkError.fragment.swift +22 -0
  336. package/project/.sdk/src/cmp/swift/tsconfig.json +15 -0
  337. package/project/.sdk/src/cmp/swift/utility_swift.ts +76 -0
  338. package/project/.sdk/src/cmp/ts/Config_ts.ts +4 -2
  339. package/project/.sdk/src/cmp/ts/Package_ts.ts +12 -0
  340. package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +81 -0
  341. package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +10 -5
  342. package/project/.sdk/src/cmp/zig/Config_zig.ts +113 -0
  343. package/project/.sdk/src/cmp/zig/EntityOperation_zig.ts +39 -0
  344. package/project/.sdk/src/cmp/zig/Entity_zig.ts +89 -0
  345. package/project/.sdk/src/cmp/zig/Gitignore_zig.ts +27 -0
  346. package/project/.sdk/src/cmp/zig/MainEntity_zig.ts +38 -0
  347. package/project/.sdk/src/cmp/zig/Main_zig.ts +78 -0
  348. package/project/.sdk/src/cmp/zig/Test_zig.ts +114 -0
  349. package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +278 -0
  350. package/project/.sdk/src/cmp/zig/fragment/EntityCreateOp.fragment.zig +24 -0
  351. package/project/.sdk/src/cmp/zig/fragment/EntityListOp.fragment.zig +21 -0
  352. package/project/.sdk/src/cmp/zig/fragment/EntityLoadOp.fragment.zig +26 -0
  353. package/project/.sdk/src/cmp/zig/fragment/EntityRemoveOp.fragment.zig +26 -0
  354. package/project/.sdk/src/cmp/zig/fragment/EntityUpdateOp.fragment.zig +26 -0
  355. package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +258 -0
  356. package/project/.sdk/src/cmp/zig/tsconfig.json +15 -0
  357. package/project/.sdk/src/cmp/zig/utility_zig.ts +95 -0
  358. package/project/.sdk/tm/c/LICENSE +22 -0
  359. package/project/.sdk/tm/c/Makefile +50 -0
  360. package/project/.sdk/tm/c/VERSION +1 -0
  361. package/project/.sdk/tm/c/core/context.c +145 -0
  362. package/project/.sdk/tm/c/core/control.c +19 -0
  363. package/project/.sdk/tm/c/core/error.c +24 -0
  364. package/project/.sdk/tm/c/core/helpers.c +228 -0
  365. package/project/.sdk/tm/c/core/operation.c +34 -0
  366. package/project/.sdk/tm/c/core/point.c +49 -0
  367. package/project/.sdk/tm/c/core/response.c +29 -0
  368. package/project/.sdk/tm/c/core/result.c +60 -0
  369. package/project/.sdk/tm/c/core/sdk.h +514 -0
  370. package/project/.sdk/tm/c/core/spec.c +94 -0
  371. package/project/.sdk/tm/c/core/utility.c +74 -0
  372. package/project/.sdk/tm/c/feature/audit.c +134 -0
  373. package/project/.sdk/tm/c/feature/base.c +40 -0
  374. package/project/.sdk/tm/c/feature/cache.c +262 -0
  375. package/project/.sdk/tm/c/feature/clienttrack.c +144 -0
  376. package/project/.sdk/tm/c/feature/debug.c +230 -0
  377. package/project/.sdk/tm/c/feature/idempotency.c +164 -0
  378. package/project/.sdk/tm/c/feature/log.c +79 -0
  379. package/project/.sdk/tm/c/feature/metrics.c +177 -0
  380. package/project/.sdk/tm/c/feature/netsim.c +211 -0
  381. package/project/.sdk/tm/c/feature/paging.c +223 -0
  382. package/project/.sdk/tm/c/feature/proxy.c +249 -0
  383. package/project/.sdk/tm/c/feature/ratelimit.c +124 -0
  384. package/project/.sdk/tm/c/feature/rbac.c +167 -0
  385. package/project/.sdk/tm/c/feature/retry.c +164 -0
  386. package/project/.sdk/tm/c/feature/streaming.c +147 -0
  387. package/project/.sdk/tm/c/feature/support.c +115 -0
  388. package/project/.sdk/tm/c/feature/telemetry.c +205 -0
  389. package/project/.sdk/tm/c/feature/test.c +385 -0
  390. package/project/.sdk/tm/c/feature/timeout.c +106 -0
  391. package/project/.sdk/tm/c/src/feature/README.md +1 -0
  392. package/project/.sdk/tm/c/src/feature/audit/.gitkeep +0 -0
  393. package/project/.sdk/tm/c/src/feature/base/.gitkeep +0 -0
  394. package/project/.sdk/tm/c/src/feature/cache/.gitkeep +0 -0
  395. package/project/.sdk/tm/c/src/feature/clienttrack/.gitkeep +0 -0
  396. package/project/.sdk/tm/c/src/feature/debug/.gitkeep +0 -0
  397. package/project/.sdk/tm/c/src/feature/idempotency/.gitkeep +0 -0
  398. package/project/.sdk/tm/c/src/feature/log/.gitkeep +0 -0
  399. package/project/.sdk/tm/c/src/feature/metrics/.gitkeep +0 -0
  400. package/project/.sdk/tm/c/src/feature/netsim/.gitkeep +0 -0
  401. package/project/.sdk/tm/c/src/feature/paging/.gitkeep +0 -0
  402. package/project/.sdk/tm/c/src/feature/proxy/.gitkeep +0 -0
  403. package/project/.sdk/tm/c/src/feature/ratelimit/.gitkeep +0 -0
  404. package/project/.sdk/tm/c/src/feature/rbac/.gitkeep +0 -0
  405. package/project/.sdk/tm/c/src/feature/retry/.gitkeep +0 -0
  406. package/project/.sdk/tm/c/src/feature/streaming/.gitkeep +0 -0
  407. package/project/.sdk/tm/c/src/feature/telemetry/.gitkeep +0 -0
  408. package/project/.sdk/tm/c/src/feature/test/.gitkeep +0 -0
  409. package/project/.sdk/tm/c/src/feature/timeout/.gitkeep +0 -0
  410. package/project/.sdk/tm/c/tests/ctest.h +58 -0
  411. package/project/.sdk/tm/c/tests/feature_harness.h +441 -0
  412. package/project/.sdk/tm/c/tests/feature_test.c +1210 -0
  413. package/project/.sdk/tm/c/tests/pipeline_test.c +561 -0
  414. package/project/.sdk/tm/c/tests/primary_utility_test.c +573 -0
  415. package/project/.sdk/tm/c/tests/runner.h +274 -0
  416. package/project/.sdk/tm/c/tests/sdk_pipeline_test.c +89 -0
  417. package/project/.sdk/tm/c/tests/struct_corpus_test.c +939 -0
  418. package/project/.sdk/tm/c/utility/clean.c +20 -0
  419. package/project/.sdk/tm/c/utility/done.c +26 -0
  420. package/project/.sdk/tm/c/utility/feature_add.c +42 -0
  421. package/project/.sdk/tm/c/utility/feature_hook.c +22 -0
  422. package/project/.sdk/tm/c/utility/feature_init.c +22 -0
  423. package/project/.sdk/tm/c/utility/fetcher.c +78 -0
  424. package/project/.sdk/tm/c/utility/jsonparse.c +11 -0
  425. package/project/.sdk/tm/c/utility/make_context.c +7 -0
  426. package/project/.sdk/tm/c/utility/make_error.c +66 -0
  427. package/project/.sdk/tm/c/utility/make_fetch_def.c +43 -0
  428. package/project/.sdk/tm/c/utility/make_options.c +179 -0
  429. package/project/.sdk/tm/c/utility/make_point.c +109 -0
  430. package/project/.sdk/tm/c/utility/make_request.c +62 -0
  431. package/project/.sdk/tm/c/utility/make_response.c +45 -0
  432. package/project/.sdk/tm/c/utility/make_result.c +61 -0
  433. package/project/.sdk/tm/c/utility/make_spec.c +60 -0
  434. package/project/.sdk/tm/c/utility/make_url.c +88 -0
  435. package/project/.sdk/tm/c/utility/param.c +58 -0
  436. package/project/.sdk/tm/c/utility/prepare_auth.c +65 -0
  437. package/project/.sdk/tm/c/utility/prepare_body.c +12 -0
  438. package/project/.sdk/tm/c/utility/prepare_headers.c +13 -0
  439. package/project/.sdk/tm/c/utility/prepare_method.c +16 -0
  440. package/project/.sdk/tm/c/utility/prepare_params.c +30 -0
  441. package/project/.sdk/tm/c/utility/prepare_path.c +17 -0
  442. package/project/.sdk/tm/c/utility/prepare_query.c +37 -0
  443. package/project/.sdk/tm/c/utility/result_basic.c +43 -0
  444. package/project/.sdk/tm/c/utility/result_body.c +17 -0
  445. package/project/.sdk/tm/c/utility/result_headers.c +17 -0
  446. package/project/.sdk/tm/c/utility/struct/inject.c +703 -0
  447. package/project/.sdk/tm/c/utility/struct/re_util.c +221 -0
  448. package/project/.sdk/tm/c/utility/struct/regex.c +1103 -0
  449. package/project/.sdk/tm/c/utility/struct/regex.h +84 -0
  450. package/project/.sdk/tm/c/utility/struct/transform.c +2224 -0
  451. package/project/.sdk/tm/c/utility/struct/utility.c +1971 -0
  452. package/project/.sdk/tm/c/utility/struct/value.c +640 -0
  453. package/project/.sdk/tm/c/utility/struct/value.h +273 -0
  454. package/project/.sdk/tm/c/utility/struct/value_io.c +366 -0
  455. package/project/.sdk/tm/c/utility/struct/value_io.h +31 -0
  456. package/project/.sdk/tm/c/utility/struct/voxgig_struct.h +216 -0
  457. package/project/.sdk/tm/c/utility/transform_request.c +21 -0
  458. package/project/.sdk/tm/c/utility/transform_response.c +36 -0
  459. package/project/.sdk/tm/clojure/LICENSE +22 -0
  460. package/project/.sdk/tm/clojure/Makefile +15 -0
  461. package/project/.sdk/tm/clojure/VERSION +1 -0
  462. package/project/.sdk/tm/clojure/src/feature/README.md +1 -0
  463. package/project/.sdk/tm/clojure/src/feature/audit/.gitkeep +0 -0
  464. package/project/.sdk/tm/clojure/src/feature/base/.gitkeep +0 -0
  465. package/project/.sdk/tm/clojure/src/feature/cache/.gitkeep +0 -0
  466. package/project/.sdk/tm/clojure/src/feature/clienttrack/.gitkeep +0 -0
  467. package/project/.sdk/tm/clojure/src/feature/debug/.gitkeep +0 -0
  468. package/project/.sdk/tm/clojure/src/feature/idempotency/.gitkeep +0 -0
  469. package/project/.sdk/tm/clojure/src/feature/log/.gitkeep +0 -0
  470. package/project/.sdk/tm/clojure/src/feature/metrics/.gitkeep +0 -0
  471. package/project/.sdk/tm/clojure/src/feature/netsim/.gitkeep +0 -0
  472. package/project/.sdk/tm/clojure/src/feature/paging/.gitkeep +0 -0
  473. package/project/.sdk/tm/clojure/src/feature/proxy/.gitkeep +0 -0
  474. package/project/.sdk/tm/clojure/src/feature/ratelimit/.gitkeep +0 -0
  475. package/project/.sdk/tm/clojure/src/feature/rbac/.gitkeep +0 -0
  476. package/project/.sdk/tm/clojure/src/feature/retry/.gitkeep +0 -0
  477. package/project/.sdk/tm/clojure/src/feature/streaming/.gitkeep +0 -0
  478. package/project/.sdk/tm/clojure/src/feature/telemetry/.gitkeep +0 -0
  479. package/project/.sdk/tm/clojure/src/feature/test/.gitkeep +0 -0
  480. package/project/.sdk/tm/clojure/src/feature/timeout/.gitkeep +0 -0
  481. package/project/.sdk/tm/clojure/src/sdk/client.clj +119 -0
  482. package/project/.sdk/tm/clojure/src/sdk/core.clj +901 -0
  483. package/project/.sdk/tm/clojure/src/sdk/features.clj +1027 -0
  484. package/project/.sdk/tm/clojure/src/voxgig/struct.clj +1734 -0
  485. package/project/.sdk/tm/clojure/test/sdk/test/feature.clj +596 -0
  486. package/project/.sdk/tm/clojure/test/sdk/test/netsim.clj +42 -0
  487. package/project/.sdk/tm/clojure/test/sdk/test/pipeline.clj +314 -0
  488. package/project/.sdk/tm/clojure/test/sdk/test/primary.clj +52 -0
  489. package/project/.sdk/tm/clojure/test/sdk/test/struct_corpus.clj +337 -0
  490. package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +39 -0
  491. package/project/.sdk/tm/clojure/test/sdk/testutil.clj +35 -0
  492. package/project/.sdk/tm/cpp/LICENSE +22 -0
  493. package/project/.sdk/tm/cpp/Makefile +36 -0
  494. package/project/.sdk/tm/cpp/VERSION +1 -0
  495. package/project/.sdk/tm/cpp/core/sdk.hpp +16 -0
  496. package/project/.sdk/tm/cpp/core/struct.hpp +225 -0
  497. package/project/.sdk/tm/cpp/core/types.hpp +1105 -0
  498. package/project/.sdk/tm/cpp/feature/audit.hpp +107 -0
  499. package/project/.sdk/tm/cpp/feature/base.hpp +34 -0
  500. package/project/.sdk/tm/cpp/feature/cache.hpp +189 -0
  501. package/project/.sdk/tm/cpp/feature/clienttrack.hpp +105 -0
  502. package/project/.sdk/tm/cpp/feature/debug.hpp +157 -0
  503. package/project/.sdk/tm/cpp/feature/idempotency.hpp +119 -0
  504. package/project/.sdk/tm/cpp/feature/log.hpp +90 -0
  505. package/project/.sdk/tm/cpp/feature/metrics.hpp +103 -0
  506. package/project/.sdk/tm/cpp/feature/netsim.hpp +152 -0
  507. package/project/.sdk/tm/cpp/feature/options.hpp +156 -0
  508. package/project/.sdk/tm/cpp/feature/paging.hpp +156 -0
  509. package/project/.sdk/tm/cpp/feature/proxy.hpp +145 -0
  510. package/project/.sdk/tm/cpp/feature/ratelimit.hpp +87 -0
  511. package/project/.sdk/tm/cpp/feature/rbac.hpp +108 -0
  512. package/project/.sdk/tm/cpp/feature/retry.hpp +130 -0
  513. package/project/.sdk/tm/cpp/feature/streaming.hpp +98 -0
  514. package/project/.sdk/tm/cpp/feature/telemetry.hpp +139 -0
  515. package/project/.sdk/tm/cpp/feature/test.hpp +289 -0
  516. package/project/.sdk/tm/cpp/feature/timeout.hpp +88 -0
  517. package/project/.sdk/tm/cpp/src/feature/README.md +1 -0
  518. package/project/.sdk/tm/cpp/src/feature/audit/.gitkeep +0 -0
  519. package/project/.sdk/tm/cpp/src/feature/base/.gitkeep +0 -0
  520. package/project/.sdk/tm/cpp/src/feature/cache/.gitkeep +0 -0
  521. package/project/.sdk/tm/cpp/src/feature/clienttrack/.gitkeep +0 -0
  522. package/project/.sdk/tm/cpp/src/feature/debug/.gitkeep +0 -0
  523. package/project/.sdk/tm/cpp/src/feature/idempotency/.gitkeep +0 -0
  524. package/project/.sdk/tm/cpp/src/feature/log/.gitkeep +0 -0
  525. package/project/.sdk/tm/cpp/src/feature/metrics/.gitkeep +0 -0
  526. package/project/.sdk/tm/cpp/src/feature/netsim/.gitkeep +0 -0
  527. package/project/.sdk/tm/cpp/src/feature/paging/.gitkeep +0 -0
  528. package/project/.sdk/tm/cpp/src/feature/proxy/.gitkeep +0 -0
  529. package/project/.sdk/tm/cpp/src/feature/ratelimit/.gitkeep +0 -0
  530. package/project/.sdk/tm/cpp/src/feature/rbac/.gitkeep +0 -0
  531. package/project/.sdk/tm/cpp/src/feature/retry/.gitkeep +0 -0
  532. package/project/.sdk/tm/cpp/src/feature/streaming/.gitkeep +0 -0
  533. package/project/.sdk/tm/cpp/src/feature/telemetry/.gitkeep +0 -0
  534. package/project/.sdk/tm/cpp/src/feature/test/.gitkeep +0 -0
  535. package/project/.sdk/tm/cpp/src/feature/timeout/.gitkeep +0 -0
  536. package/project/.sdk/tm/cpp/test/custom_utility_test.cpp +57 -0
  537. package/project/.sdk/tm/cpp/test/exists_test.cpp +16 -0
  538. package/project/.sdk/tm/cpp/test/feature_test.cpp +911 -0
  539. package/project/.sdk/tm/cpp/test/harness.hpp +344 -0
  540. package/project/.sdk/tm/cpp/test/netsim_test.cpp +48 -0
  541. package/project/.sdk/tm/cpp/test/pipeline_test.cpp +526 -0
  542. package/project/.sdk/tm/cpp/test/primary_utility_test.cpp +841 -0
  543. package/project/.sdk/tm/cpp/test/runner_support.hpp +437 -0
  544. package/project/.sdk/tm/cpp/test/sdk-test-control.json +19 -0
  545. package/project/.sdk/tm/cpp/test/struct_corpus_test.cpp +494 -0
  546. package/project/.sdk/tm/cpp/test/struct_runner.hpp +314 -0
  547. package/project/.sdk/tm/cpp/test/testlib.hpp +82 -0
  548. package/project/.sdk/tm/cpp/utility/pipeline.hpp +1054 -0
  549. package/project/.sdk/tm/cpp/utility/voxgigstruct/value.hpp +525 -0
  550. package/project/.sdk/tm/cpp/utility/voxgigstruct/value_io.hpp +315 -0
  551. package/project/.sdk/tm/cpp/utility/voxgigstruct/voxgig_struct.hpp +3379 -0
  552. package/project/.sdk/tm/csharp/LICENSE +22 -0
  553. package/project/.sdk/tm/csharp/Makefile +43 -0
  554. package/project/.sdk/tm/csharp/VERSION +1 -0
  555. package/project/.sdk/tm/csharp/core/Context.cs +257 -0
  556. package/project/.sdk/tm/csharp/core/Control.cs +17 -0
  557. package/project/.sdk/tm/csharp/core/Helpers.cs +61 -0
  558. package/project/.sdk/tm/csharp/core/Operation.cs +51 -0
  559. package/project/.sdk/tm/csharp/core/Point.cs +68 -0
  560. package/project/.sdk/tm/csharp/core/Response.cs +45 -0
  561. package/project/.sdk/tm/csharp/core/Result.cs +63 -0
  562. package/project/.sdk/tm/csharp/core/Spec.cs +81 -0
  563. package/project/.sdk/tm/csharp/core/Types.cs +21 -0
  564. package/project/.sdk/tm/csharp/core/Utility.cs +88 -0
  565. package/project/.sdk/tm/csharp/feature/AuditFeature.cs +116 -0
  566. package/project/.sdk/tm/csharp/feature/BaseFeature.cs +39 -0
  567. package/project/.sdk/tm/csharp/feature/CacheFeature.cs +186 -0
  568. package/project/.sdk/tm/csharp/feature/ClienttrackFeature.cs +103 -0
  569. package/project/.sdk/tm/csharp/feature/DebugFeature.cs +157 -0
  570. package/project/.sdk/tm/csharp/feature/FeatureOptions.cs +197 -0
  571. package/project/.sdk/tm/csharp/feature/IdempotencyFeature.cs +97 -0
  572. package/project/.sdk/tm/csharp/feature/LogFeature.cs +109 -0
  573. package/project/.sdk/tm/csharp/feature/MetricsFeature.cs +117 -0
  574. package/project/.sdk/tm/csharp/feature/NetsimFeature.cs +200 -0
  575. package/project/.sdk/tm/csharp/feature/PagingFeature.cs +187 -0
  576. package/project/.sdk/tm/csharp/feature/ProxyFeature.cs +138 -0
  577. package/project/.sdk/tm/csharp/feature/RatelimitFeature.cs +89 -0
  578. package/project/.sdk/tm/csharp/feature/RbacFeature.cs +124 -0
  579. package/project/.sdk/tm/csharp/feature/RetryFeature.cs +174 -0
  580. package/project/.sdk/tm/csharp/feature/StreamingFeature.cs +93 -0
  581. package/project/.sdk/tm/csharp/feature/TelemetryFeature.cs +145 -0
  582. package/project/.sdk/tm/csharp/feature/TestFeature.cs +368 -0
  583. package/project/.sdk/tm/csharp/feature/TimeoutFeature.cs +69 -0
  584. package/project/.sdk/tm/csharp/src/feature/README.md +1 -0
  585. package/project/.sdk/tm/csharp/src/feature/audit/.gitkeep +0 -0
  586. package/project/.sdk/tm/csharp/src/feature/base/.gitkeep +0 -0
  587. package/project/.sdk/tm/csharp/src/feature/cache/.gitkeep +0 -0
  588. package/project/.sdk/tm/csharp/src/feature/clienttrack/.gitkeep +0 -0
  589. package/project/.sdk/tm/csharp/src/feature/debug/.gitkeep +0 -0
  590. package/project/.sdk/tm/csharp/src/feature/idempotency/.gitkeep +0 -0
  591. package/project/.sdk/tm/csharp/src/feature/log/.gitkeep +0 -0
  592. package/project/.sdk/tm/csharp/src/feature/metrics/.gitkeep +0 -0
  593. package/project/.sdk/tm/csharp/src/feature/netsim/.gitkeep +0 -0
  594. package/project/.sdk/tm/csharp/src/feature/paging/.gitkeep +0 -0
  595. package/project/.sdk/tm/csharp/src/feature/proxy/.gitkeep +0 -0
  596. package/project/.sdk/tm/csharp/src/feature/ratelimit/.gitkeep +0 -0
  597. package/project/.sdk/tm/csharp/src/feature/rbac/.gitkeep +0 -0
  598. package/project/.sdk/tm/csharp/src/feature/retry/.gitkeep +0 -0
  599. package/project/.sdk/tm/csharp/src/feature/streaming/.gitkeep +0 -0
  600. package/project/.sdk/tm/csharp/src/feature/telemetry/.gitkeep +0 -0
  601. package/project/.sdk/tm/csharp/src/feature/test/.gitkeep +0 -0
  602. package/project/.sdk/tm/csharp/src/feature/timeout/.gitkeep +0 -0
  603. package/project/.sdk/tm/csharp/test/CustomUtilityTest.cs +51 -0
  604. package/project/.sdk/tm/csharp/test/ExistsTest.cs +17 -0
  605. package/project/.sdk/tm/csharp/test/FeatureTest.cs +1653 -0
  606. package/project/.sdk/tm/csharp/test/NetsimTest.cs +67 -0
  607. package/project/.sdk/tm/csharp/test/PipelineTest.cs +605 -0
  608. package/project/.sdk/tm/csharp/test/PrimaryUtilityTest.cs +957 -0
  609. package/project/.sdk/tm/csharp/test/Runner.cs +626 -0
  610. package/project/.sdk/tm/csharp/test/StructRunner.cs +276 -0
  611. package/project/.sdk/tm/csharp/test/StructUtilityTest.cs +1273 -0
  612. package/project/.sdk/tm/csharp/test/sdk-test-control.json +19 -0
  613. package/project/.sdk/tm/csharp/utility/Clean.cs +11 -0
  614. package/project/.sdk/tm/csharp/utility/Done.cs +28 -0
  615. package/project/.sdk/tm/csharp/utility/FeatureAdd.cs +54 -0
  616. package/project/.sdk/tm/csharp/utility/FeatureHook.cs +35 -0
  617. package/project/.sdk/tm/csharp/utility/FeatureInit.cs +28 -0
  618. package/project/.sdk/tm/csharp/utility/Fetcher.cs +181 -0
  619. package/project/.sdk/tm/csharp/utility/MakeContext.cs +11 -0
  620. package/project/.sdk/tm/csharp/utility/MakeError.cs +69 -0
  621. package/project/.sdk/tm/csharp/utility/MakeFetchDef.cs +38 -0
  622. package/project/.sdk/tm/csharp/utility/MakeOptions.cs +203 -0
  623. package/project/.sdk/tm/csharp/utility/MakePoint.cs +127 -0
  624. package/project/.sdk/tm/csharp/utility/MakeRequest.cs +87 -0
  625. package/project/.sdk/tm/csharp/utility/MakeResponse.cs +55 -0
  626. package/project/.sdk/tm/csharp/utility/MakeResult.cs +64 -0
  627. package/project/.sdk/tm/csharp/utility/MakeSpec.cs +64 -0
  628. package/project/.sdk/tm/csharp/utility/MakeUrl.cs +54 -0
  629. package/project/.sdk/tm/csharp/utility/Param.cs +67 -0
  630. package/project/.sdk/tm/csharp/utility/PrepareAuth.cs +54 -0
  631. package/project/.sdk/tm/csharp/utility/PrepareBody.cs +19 -0
  632. package/project/.sdk/tm/csharp/utility/PrepareHeaders.cs +22 -0
  633. package/project/.sdk/tm/csharp/utility/PrepareMethod.cs +22 -0
  634. package/project/.sdk/tm/csharp/utility/PrepareParams.cs +38 -0
  635. package/project/.sdk/tm/csharp/utility/PreparePath.cs +18 -0
  636. package/project/.sdk/tm/csharp/utility/PrepareQuery.cs +40 -0
  637. package/project/.sdk/tm/csharp/utility/Register.cs +41 -0
  638. package/project/.sdk/tm/csharp/utility/ResultBasic.cs +39 -0
  639. package/project/.sdk/tm/csharp/utility/ResultBody.cs +22 -0
  640. package/project/.sdk/tm/csharp/utility/ResultHeaders.cs +26 -0
  641. package/project/.sdk/tm/csharp/utility/TransformRequest.cs +39 -0
  642. package/project/.sdk/tm/csharp/utility/TransformResponse.cs +53 -0
  643. package/project/.sdk/tm/csharp/utility/struct/Struct.cs +3582 -0
  644. package/project/.sdk/tm/dart/LICENSE +22 -0
  645. package/project/.sdk/tm/dart/Makefile +50 -0
  646. package/project/.sdk/tm/dart/lib/Context.dart +150 -0
  647. package/project/.sdk/tm/dart/lib/Control.dart +15 -0
  648. package/project/.sdk/tm/dart/lib/Operation.dart +31 -0
  649. package/project/.sdk/tm/dart/lib/Point.dart +43 -0
  650. package/project/.sdk/tm/dart/lib/Response.dart +32 -0
  651. package/project/.sdk/tm/dart/lib/Result.dart +39 -0
  652. package/project/.sdk/tm/dart/lib/Spec.dart +49 -0
  653. package/project/.sdk/tm/dart/lib/feature/audit/AuditFeature.dart +103 -0
  654. package/project/.sdk/tm/dart/lib/feature/base/BaseFeature.dart +76 -0
  655. package/project/.sdk/tm/dart/lib/feature/cache/CacheFeature.dart +152 -0
  656. package/project/.sdk/tm/dart/lib/feature/clienttrack/ClienttrackFeature.dart +104 -0
  657. package/project/.sdk/tm/dart/lib/feature/debug/DebugFeature.dart +153 -0
  658. package/project/.sdk/tm/dart/lib/feature/idempotency/IdempotencyFeature.dart +92 -0
  659. package/project/.sdk/tm/dart/lib/feature/log/LogFeature.dart +85 -0
  660. package/project/.sdk/tm/dart/lib/feature/metrics/MetricsFeature.dart +103 -0
  661. package/project/.sdk/tm/dart/lib/feature/netsim/NetsimFeature.dart +186 -0
  662. package/project/.sdk/tm/dart/lib/feature/paging/PagingFeature.dart +145 -0
  663. package/project/.sdk/tm/dart/lib/feature/proxy/ProxyFeature.dart +118 -0
  664. package/project/.sdk/tm/dart/lib/feature/ratelimit/RatelimitFeature.dart +103 -0
  665. package/project/.sdk/tm/dart/lib/feature/rbac/RbacFeature.dart +121 -0
  666. package/project/.sdk/tm/dart/lib/feature/retry/RetryFeature.dart +155 -0
  667. package/project/.sdk/tm/dart/lib/feature/streaming/StreamingFeature.dart +97 -0
  668. package/project/.sdk/tm/dart/lib/feature/telemetry/TelemetryFeature.dart +136 -0
  669. package/project/.sdk/tm/dart/lib/feature/test/TestFeature.dart +270 -0
  670. package/project/.sdk/tm/dart/lib/feature/timeout/TimeoutFeature.dart +104 -0
  671. package/project/.sdk/tm/dart/lib/utility/CleanUtility.dart +12 -0
  672. package/project/.sdk/tm/dart/lib/utility/DoneUtility.dart +18 -0
  673. package/project/.sdk/tm/dart/lib/utility/ErrUtility.dart +46 -0
  674. package/project/.sdk/tm/dart/lib/utility/FeatureAddUtility.dart +35 -0
  675. package/project/.sdk/tm/dart/lib/utility/FeatureHookUtility.dart +20 -0
  676. package/project/.sdk/tm/dart/lib/utility/FeatureInitUtility.dart +9 -0
  677. package/project/.sdk/tm/dart/lib/utility/FetcherUtility.dart +95 -0
  678. package/project/.sdk/tm/dart/lib/utility/MakeContextUtility.dart +6 -0
  679. package/project/.sdk/tm/dart/lib/utility/MakeErrorUtility.dart +67 -0
  680. package/project/.sdk/tm/dart/lib/utility/MakeFetchDefUtility.dart +42 -0
  681. package/project/.sdk/tm/dart/lib/utility/MakeOptionsUtility.dart +147 -0
  682. package/project/.sdk/tm/dart/lib/utility/MakePointUtility.dart +84 -0
  683. package/project/.sdk/tm/dart/lib/utility/MakeRequestUtility.dart +63 -0
  684. package/project/.sdk/tm/dart/lib/utility/MakeResponseUtility.dart +54 -0
  685. package/project/.sdk/tm/dart/lib/utility/MakeResultUtility.dart +49 -0
  686. package/project/.sdk/tm/dart/lib/utility/MakeSpecUtility.dart +61 -0
  687. package/project/.sdk/tm/dart/lib/utility/MakeUrlUtility.dart +51 -0
  688. package/project/.sdk/tm/dart/lib/utility/ParamUtility.dart +56 -0
  689. package/project/.sdk/tm/dart/lib/utility/PrepareAuthUtility.dart +46 -0
  690. package/project/.sdk/tm/dart/lib/utility/PrepareBodyUtility.dart +19 -0
  691. package/project/.sdk/tm/dart/lib/utility/PrepareHeadersUtility.dart +11 -0
  692. package/project/.sdk/tm/dart/lib/utility/PrepareMethodUtility.dart +15 -0
  693. package/project/.sdk/tm/dart/lib/utility/PrepareParamsUtility.dart +23 -0
  694. package/project/.sdk/tm/dart/lib/utility/PreparePathUtility.dart +9 -0
  695. package/project/.sdk/tm/dart/lib/utility/PrepareQueryUtility.dart +18 -0
  696. package/project/.sdk/tm/dart/lib/utility/ResultBasicUtility.dart +29 -0
  697. package/project/.sdk/tm/dart/lib/utility/ResultBodyUtility.dart +15 -0
  698. package/project/.sdk/tm/dart/lib/utility/ResultHeadersUtility.dart +18 -0
  699. package/project/.sdk/tm/dart/lib/utility/StructUtility.dart +127 -0
  700. package/project/.sdk/tm/dart/lib/utility/TransformRequestUtility.dart +28 -0
  701. package/project/.sdk/tm/dart/lib/utility/TransformResponseUtility.dart +44 -0
  702. package/project/.sdk/tm/dart/lib/utility/Utility.dart +230 -0
  703. package/project/.sdk/tm/dart/lib/utility/voxgig_struct.dart +2456 -0
  704. package/project/.sdk/tm/dart/src/feature/README.md +3 -0
  705. package/project/.sdk/tm/dart/src/feature/audit/.gitkeep +0 -0
  706. package/project/.sdk/tm/dart/src/feature/base/.gitkeep +0 -0
  707. package/project/.sdk/tm/dart/src/feature/cache/.gitkeep +0 -0
  708. package/project/.sdk/tm/dart/src/feature/clienttrack/.gitkeep +0 -0
  709. package/project/.sdk/tm/dart/src/feature/debug/.gitkeep +0 -0
  710. package/project/.sdk/tm/dart/src/feature/idempotency/.gitkeep +0 -0
  711. package/project/.sdk/tm/dart/src/feature/log/.gitkeep +0 -0
  712. package/project/.sdk/tm/dart/src/feature/metrics/.gitkeep +0 -0
  713. package/project/.sdk/tm/dart/src/feature/netsim/.gitkeep +0 -0
  714. package/project/.sdk/tm/dart/src/feature/paging/.gitkeep +0 -0
  715. package/project/.sdk/tm/dart/src/feature/proxy/.gitkeep +0 -0
  716. package/project/.sdk/tm/dart/src/feature/ratelimit/.gitkeep +0 -0
  717. package/project/.sdk/tm/dart/src/feature/rbac/.gitkeep +0 -0
  718. package/project/.sdk/tm/dart/src/feature/retry/.gitkeep +0 -0
  719. package/project/.sdk/tm/dart/src/feature/streaming/.gitkeep +0 -0
  720. package/project/.sdk/tm/dart/src/feature/telemetry/.gitkeep +0 -0
  721. package/project/.sdk/tm/dart/src/feature/test/.gitkeep +0 -0
  722. package/project/.sdk/tm/dart/src/feature/timeout/.gitkeep +0 -0
  723. package/project/.sdk/tm/dart/test/custom_test.dart +65 -0
  724. package/project/.sdk/tm/dart/test/exists_test.dart +12 -0
  725. package/project/.sdk/tm/dart/test/feature/harness.dart +329 -0
  726. package/project/.sdk/tm/dart/test/feature_test.dart +1139 -0
  727. package/project/.sdk/tm/dart/test/harness.dart +153 -0
  728. package/project/.sdk/tm/dart/test/netsim_test.dart +48 -0
  729. package/project/.sdk/tm/dart/test/pipeline_test.dart +608 -0
  730. package/project/.sdk/tm/dart/test/primary_test.dart +411 -0
  731. package/project/.sdk/tm/dart/test/runner.dart +406 -0
  732. package/project/.sdk/tm/dart/test/sdk-test-control.json +19 -0
  733. package/project/.sdk/tm/dart/test/struct_corpus.dart +531 -0
  734. package/project/.sdk/tm/dart/test/struct_test.dart +41 -0
  735. package/project/.sdk/tm/dart/test/utility.dart +159 -0
  736. package/project/.sdk/tm/elixir/LICENSE +21 -0
  737. package/project/.sdk/tm/elixir/Makefile +15 -0
  738. package/project/.sdk/tm/elixir/VERSION +1 -0
  739. package/project/.sdk/tm/elixir/lib/projectname/context.ex +138 -0
  740. package/project/.sdk/tm/elixir/lib/projectname/core.ex +125 -0
  741. package/project/.sdk/tm/elixir/lib/projectname/entity_base.ex +155 -0
  742. package/project/.sdk/tm/elixir/lib/projectname/error.ex +16 -0
  743. package/project/.sdk/tm/elixir/lib/projectname/feature/audit.ex +125 -0
  744. package/project/.sdk/tm/elixir/lib/projectname/feature/cache.ex +170 -0
  745. package/project/.sdk/tm/elixir/lib/projectname/feature/clienttrack.ex +136 -0
  746. package/project/.sdk/tm/elixir/lib/projectname/feature/debug.ex +232 -0
  747. package/project/.sdk/tm/elixir/lib/projectname/feature/idempotency.ex +107 -0
  748. package/project/.sdk/tm/elixir/lib/projectname/feature/log.ex +62 -0
  749. package/project/.sdk/tm/elixir/lib/projectname/feature/metrics.ex +130 -0
  750. package/project/.sdk/tm/elixir/lib/projectname/feature/netsim.ex +213 -0
  751. package/project/.sdk/tm/elixir/lib/projectname/feature/paging.ex +191 -0
  752. package/project/.sdk/tm/elixir/lib/projectname/feature/proxy.ex +142 -0
  753. package/project/.sdk/tm/elixir/lib/projectname/feature/ratelimit.ex +81 -0
  754. package/project/.sdk/tm/elixir/lib/projectname/feature/rbac.ex +139 -0
  755. package/project/.sdk/tm/elixir/lib/projectname/feature/retry.ex +150 -0
  756. package/project/.sdk/tm/elixir/lib/projectname/feature/streaming.ex +107 -0
  757. package/project/.sdk/tm/elixir/lib/projectname/feature/telemetry.ex +172 -0
  758. package/project/.sdk/tm/elixir/lib/projectname/feature/test.ex +285 -0
  759. package/project/.sdk/tm/elixir/lib/projectname/feature/timeout.ex +64 -0
  760. package/project/.sdk/tm/elixir/lib/projectname/feature.ex +90 -0
  761. package/project/.sdk/tm/elixir/lib/projectname/helpers.ex +66 -0
  762. package/project/.sdk/tm/elixir/lib/projectname/json.ex +115 -0
  763. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +1257 -0
  764. package/project/.sdk/tm/elixir/lib/utility/struct/voxgig_struct.ex +2615 -0
  765. package/project/.sdk/tm/elixir/src/feature/README.md +3 -0
  766. package/project/.sdk/tm/elixir/src/feature/audit/.gitkeep +0 -0
  767. package/project/.sdk/tm/elixir/src/feature/base/.gitkeep +0 -0
  768. package/project/.sdk/tm/elixir/src/feature/cache/.gitkeep +0 -0
  769. package/project/.sdk/tm/elixir/src/feature/clienttrack/.gitkeep +0 -0
  770. package/project/.sdk/tm/elixir/src/feature/debug/.gitkeep +0 -0
  771. package/project/.sdk/tm/elixir/src/feature/idempotency/.gitkeep +0 -0
  772. package/project/.sdk/tm/elixir/src/feature/log/.gitkeep +0 -0
  773. package/project/.sdk/tm/elixir/src/feature/metrics/.gitkeep +0 -0
  774. package/project/.sdk/tm/elixir/src/feature/netsim/.gitkeep +0 -0
  775. package/project/.sdk/tm/elixir/src/feature/paging/.gitkeep +0 -0
  776. package/project/.sdk/tm/elixir/src/feature/proxy/.gitkeep +0 -0
  777. package/project/.sdk/tm/elixir/src/feature/ratelimit/.gitkeep +0 -0
  778. package/project/.sdk/tm/elixir/src/feature/rbac/.gitkeep +0 -0
  779. package/project/.sdk/tm/elixir/src/feature/retry/.gitkeep +0 -0
  780. package/project/.sdk/tm/elixir/src/feature/streaming/.gitkeep +0 -0
  781. package/project/.sdk/tm/elixir/src/feature/telemetry/.gitkeep +0 -0
  782. package/project/.sdk/tm/elixir/src/feature/test/.gitkeep +0 -0
  783. package/project/.sdk/tm/elixir/src/feature/timeout/.gitkeep +0 -0
  784. package/project/.sdk/tm/elixir/test/feature_test.exs +879 -0
  785. package/project/.sdk/tm/elixir/test/netsim_test.exs +58 -0
  786. package/project/.sdk/tm/elixir/test/pipeline_test.exs +558 -0
  787. package/project/.sdk/tm/elixir/test/primary_utility_test.exs +133 -0
  788. package/project/.sdk/tm/elixir/test/stream_test.exs +119 -0
  789. package/project/.sdk/tm/elixir/test/struct_corpus_test.exs +18 -0
  790. package/project/.sdk/tm/elixir/test/support/feature_harness.ex +346 -0
  791. package/project/.sdk/tm/elixir/test/support/struct_corpus.ex +677 -0
  792. package/project/.sdk/tm/elixir/test/test_helper.exs +1 -0
  793. package/project/.sdk/tm/go/core/context.go +10 -0
  794. package/project/.sdk/tm/go/core/control.go +2 -0
  795. package/project/.sdk/tm/go/core/result.go +6 -0
  796. package/project/.sdk/tm/go/core/types.go +1 -0
  797. package/project/.sdk/tm/go/feature/audit_feature.go +110 -0
  798. package/project/.sdk/tm/go/feature/base_feature.go +8 -0
  799. package/project/.sdk/tm/go/feature/cache_feature.go +171 -0
  800. package/project/.sdk/tm/go/feature/clienttrack_feature.go +100 -0
  801. package/project/.sdk/tm/go/feature/debug_feature.go +159 -0
  802. package/project/.sdk/tm/go/feature/feature_options.go +204 -0
  803. package/project/.sdk/tm/go/feature/idempotency_feature.go +115 -0
  804. package/project/.sdk/tm/go/feature/metrics_feature.go +112 -0
  805. package/project/.sdk/tm/go/feature/netsim_feature.go +184 -0
  806. package/project/.sdk/tm/go/feature/paging_feature.go +173 -0
  807. package/project/.sdk/tm/go/feature/proxy_feature.go +121 -0
  808. package/project/.sdk/tm/go/feature/ratelimit_feature.go +88 -0
  809. package/project/.sdk/tm/go/feature/rbac_feature.go +126 -0
  810. package/project/.sdk/tm/go/feature/retry_feature.go +165 -0
  811. package/project/.sdk/tm/go/feature/streaming_feature.go +119 -0
  812. package/project/.sdk/tm/go/feature/telemetry_feature.go +142 -0
  813. package/project/.sdk/tm/go/feature/test_feature.go +78 -3
  814. package/project/.sdk/tm/go/feature/timeout_feature.go +88 -0
  815. package/project/.sdk/tm/go/src/feature/audit/.gitkeep +0 -0
  816. package/project/.sdk/tm/go/src/feature/cache/.gitkeep +0 -0
  817. package/project/.sdk/tm/go/src/feature/clienttrack/.gitkeep +0 -0
  818. package/project/.sdk/tm/go/src/feature/debug/.gitkeep +0 -0
  819. package/project/.sdk/tm/go/src/feature/idempotency/.gitkeep +0 -0
  820. package/project/.sdk/tm/go/src/feature/metrics/.gitkeep +0 -0
  821. package/project/.sdk/tm/go/src/feature/netsim/.gitkeep +0 -0
  822. package/project/.sdk/tm/go/src/feature/paging/.gitkeep +0 -0
  823. package/project/.sdk/tm/go/src/feature/proxy/.gitkeep +0 -0
  824. package/project/.sdk/tm/go/src/feature/ratelimit/.gitkeep +0 -0
  825. package/project/.sdk/tm/go/src/feature/rbac/.gitkeep +0 -0
  826. package/project/.sdk/tm/go/src/feature/retry/.gitkeep +0 -0
  827. package/project/.sdk/tm/go/src/feature/streaming/.gitkeep +0 -0
  828. package/project/.sdk/tm/go/src/feature/telemetry/.gitkeep +0 -0
  829. package/project/.sdk/tm/go/src/feature/timeout/.gitkeep +0 -0
  830. package/project/.sdk/tm/go/test/feature_test.go +1465 -0
  831. package/project/.sdk/tm/go/test/netsim_test.go +70 -0
  832. package/project/.sdk/tm/go/test/pipeline_test.go +571 -0
  833. package/project/.sdk/tm/go/utility/feature_add.go +38 -0
  834. package/project/.sdk/tm/go/utility/fetcher.go +13 -1
  835. package/project/.sdk/tm/go/utility/make_error.go +8 -0
  836. package/project/.sdk/tm/go/utility/make_options.go +62 -0
  837. package/project/.sdk/tm/go/utility/make_point.go +6 -0
  838. package/project/.sdk/tm/go-cli/src/feature/audit/.gitkeep +0 -0
  839. package/project/.sdk/tm/go-cli/src/feature/cache/.gitkeep +0 -0
  840. package/project/.sdk/tm/go-cli/src/feature/clienttrack/.gitkeep +0 -0
  841. package/project/.sdk/tm/go-cli/src/feature/debug/.gitkeep +0 -0
  842. package/project/.sdk/tm/go-cli/src/feature/idempotency/.gitkeep +0 -0
  843. package/project/.sdk/tm/go-cli/src/feature/metrics/.gitkeep +0 -0
  844. package/project/.sdk/tm/go-cli/src/feature/netsim/.gitkeep +0 -0
  845. package/project/.sdk/tm/go-cli/src/feature/paging/.gitkeep +0 -0
  846. package/project/.sdk/tm/go-cli/src/feature/proxy/.gitkeep +0 -0
  847. package/project/.sdk/tm/go-cli/src/feature/ratelimit/.gitkeep +0 -0
  848. package/project/.sdk/tm/go-cli/src/feature/rbac/.gitkeep +0 -0
  849. package/project/.sdk/tm/go-cli/src/feature/retry/.gitkeep +0 -0
  850. package/project/.sdk/tm/go-cli/src/feature/streaming/.gitkeep +0 -0
  851. package/project/.sdk/tm/go-cli/src/feature/telemetry/.gitkeep +0 -0
  852. package/project/.sdk/tm/go-cli/src/feature/timeout/.gitkeep +0 -0
  853. package/project/.sdk/tm/go-mcp/src/feature/audit/.gitkeep +0 -0
  854. package/project/.sdk/tm/go-mcp/src/feature/cache/.gitkeep +0 -0
  855. package/project/.sdk/tm/go-mcp/src/feature/clienttrack/.gitkeep +0 -0
  856. package/project/.sdk/tm/go-mcp/src/feature/debug/.gitkeep +0 -0
  857. package/project/.sdk/tm/go-mcp/src/feature/idempotency/.gitkeep +0 -0
  858. package/project/.sdk/tm/go-mcp/src/feature/metrics/.gitkeep +0 -0
  859. package/project/.sdk/tm/go-mcp/src/feature/netsim/.gitkeep +0 -0
  860. package/project/.sdk/tm/go-mcp/src/feature/paging/.gitkeep +0 -0
  861. package/project/.sdk/tm/go-mcp/src/feature/proxy/.gitkeep +0 -0
  862. package/project/.sdk/tm/go-mcp/src/feature/ratelimit/.gitkeep +0 -0
  863. package/project/.sdk/tm/go-mcp/src/feature/rbac/.gitkeep +0 -0
  864. package/project/.sdk/tm/go-mcp/src/feature/retry/.gitkeep +0 -0
  865. package/project/.sdk/tm/go-mcp/src/feature/streaming/.gitkeep +0 -0
  866. package/project/.sdk/tm/go-mcp/src/feature/telemetry/.gitkeep +0 -0
  867. package/project/.sdk/tm/go-mcp/src/feature/timeout/.gitkeep +0 -0
  868. package/project/.sdk/tm/haskell/LICENSE +21 -0
  869. package/project/.sdk/tm/haskell/Makefile +22 -0
  870. package/project/.sdk/tm/haskell/VERSION +1 -0
  871. package/project/.sdk/tm/haskell/src/SdkFeatures.hs +1278 -0
  872. package/project/.sdk/tm/haskell/src/SdkHelpers.hs +337 -0
  873. package/project/.sdk/tm/haskell/src/SdkRuntime.hs +1007 -0
  874. package/project/.sdk/tm/haskell/src/SdkTypes.hs +186 -0
  875. package/project/.sdk/tm/haskell/src/VoxgigStruct.hs +2299 -0
  876. package/project/.sdk/tm/haskell/src/Vregex.hs +237 -0
  877. package/project/.sdk/tm/haskell/src/feature/README.md +5 -0
  878. package/project/.sdk/tm/haskell/src/feature/audit/.gitkeep +0 -0
  879. package/project/.sdk/tm/haskell/src/feature/base/.gitkeep +0 -0
  880. package/project/.sdk/tm/haskell/src/feature/cache/.gitkeep +0 -0
  881. package/project/.sdk/tm/haskell/src/feature/clienttrack/.gitkeep +0 -0
  882. package/project/.sdk/tm/haskell/src/feature/debug/.gitkeep +0 -0
  883. package/project/.sdk/tm/haskell/src/feature/idempotency/.gitkeep +0 -0
  884. package/project/.sdk/tm/haskell/src/feature/log/.gitkeep +0 -0
  885. package/project/.sdk/tm/haskell/src/feature/metrics/.gitkeep +0 -0
  886. package/project/.sdk/tm/haskell/src/feature/netsim/.gitkeep +0 -0
  887. package/project/.sdk/tm/haskell/src/feature/paging/.gitkeep +0 -0
  888. package/project/.sdk/tm/haskell/src/feature/proxy/.gitkeep +0 -0
  889. package/project/.sdk/tm/haskell/src/feature/ratelimit/.gitkeep +0 -0
  890. package/project/.sdk/tm/haskell/src/feature/rbac/.gitkeep +0 -0
  891. package/project/.sdk/tm/haskell/src/feature/retry/.gitkeep +0 -0
  892. package/project/.sdk/tm/haskell/src/feature/streaming/.gitkeep +0 -0
  893. package/project/.sdk/tm/haskell/src/feature/telemetry/.gitkeep +0 -0
  894. package/project/.sdk/tm/haskell/src/feature/test/.gitkeep +0 -0
  895. package/project/.sdk/tm/haskell/src/feature/timeout/.gitkeep +0 -0
  896. package/project/.sdk/tm/haskell/test/Harness.hs +276 -0
  897. package/project/.sdk/tm/haskell/test/Runner.hs +47 -0
  898. package/project/.sdk/tm/haskell/test/StructCorpus.hs +449 -0
  899. package/project/.sdk/tm/haskell/test/TCustomUtility.hs +38 -0
  900. package/project/.sdk/tm/haskell/test/TFeature.hs +794 -0
  901. package/project/.sdk/tm/haskell/test/TNetsim.hs +50 -0
  902. package/project/.sdk/tm/haskell/test/TPipeline.hs +334 -0
  903. package/project/.sdk/tm/haskell/test/TPrimaryUtility.hs +386 -0
  904. package/project/.sdk/tm/haskell/test/TestJson.hs +107 -0
  905. package/project/.sdk/tm/haskell/test/Testutil.hs +59 -0
  906. package/project/.sdk/tm/java/LICENSE +22 -0
  907. package/project/.sdk/tm/java/Makefile +44 -0
  908. package/project/.sdk/tm/java/VERSION +1 -0
  909. package/project/.sdk/tm/java/core/Context.java +269 -0
  910. package/project/.sdk/tm/java/core/Control.java +23 -0
  911. package/project/.sdk/tm/java/core/Entity.java +13 -0
  912. package/project/.sdk/tm/java/core/Feature.java +45 -0
  913. package/project/.sdk/tm/java/core/FeaturePlacement.java +13 -0
  914. package/project/.sdk/tm/java/core/Helpers.java +50 -0
  915. package/project/.sdk/tm/java/core/Operation.java +47 -0
  916. package/project/.sdk/tm/java/core/Point.java +90 -0
  917. package/project/.sdk/tm/java/core/Response.java +48 -0
  918. package/project/.sdk/tm/java/core/Result.java +64 -0
  919. package/project/.sdk/tm/java/core/SdkClient.java +280 -0
  920. package/project/.sdk/tm/java/core/SdkEntity.java +28 -0
  921. package/project/.sdk/tm/java/core/Spec.java +84 -0
  922. package/project/.sdk/tm/java/core/Utility.java +128 -0
  923. package/project/.sdk/tm/java/feature/AuditFeature.java +113 -0
  924. package/project/.sdk/tm/java/feature/BaseFeature.java +91 -0
  925. package/project/.sdk/tm/java/feature/CacheFeature.java +184 -0
  926. package/project/.sdk/tm/java/feature/ClienttrackFeature.java +103 -0
  927. package/project/.sdk/tm/java/feature/DebugFeature.java +163 -0
  928. package/project/.sdk/tm/java/feature/FeatureOptions.java +204 -0
  929. package/project/.sdk/tm/java/feature/IdempotencyFeature.java +115 -0
  930. package/project/.sdk/tm/java/feature/LogFeature.java +143 -0
  931. package/project/.sdk/tm/java/feature/MetricsFeature.java +115 -0
  932. package/project/.sdk/tm/java/feature/NetsimFeature.java +181 -0
  933. package/project/.sdk/tm/java/feature/PagingFeature.java +178 -0
  934. package/project/.sdk/tm/java/feature/ProxyFeature.java +122 -0
  935. package/project/.sdk/tm/java/feature/RatelimitFeature.java +83 -0
  936. package/project/.sdk/tm/java/feature/RbacFeature.java +132 -0
  937. package/project/.sdk/tm/java/feature/RetryFeature.java +156 -0
  938. package/project/.sdk/tm/java/feature/StreamingFeature.java +110 -0
  939. package/project/.sdk/tm/java/feature/TelemetryFeature.java +146 -0
  940. package/project/.sdk/tm/java/feature/TestFeature.java +333 -0
  941. package/project/.sdk/tm/java/feature/TimeoutFeature.java +89 -0
  942. package/project/.sdk/tm/java/src/feature/README.md +1 -0
  943. package/project/.sdk/tm/java/src/feature/audit/.gitkeep +0 -0
  944. package/project/.sdk/tm/java/src/feature/base/.gitkeep +0 -0
  945. package/project/.sdk/tm/java/src/feature/cache/.gitkeep +0 -0
  946. package/project/.sdk/tm/java/src/feature/clienttrack/.gitkeep +0 -0
  947. package/project/.sdk/tm/java/src/feature/debug/.gitkeep +0 -0
  948. package/project/.sdk/tm/java/src/feature/idempotency/.gitkeep +0 -0
  949. package/project/.sdk/tm/java/src/feature/log/.gitkeep +0 -0
  950. package/project/.sdk/tm/java/src/feature/metrics/.gitkeep +0 -0
  951. package/project/.sdk/tm/java/src/feature/netsim/.gitkeep +0 -0
  952. package/project/.sdk/tm/java/src/feature/paging/.gitkeep +0 -0
  953. package/project/.sdk/tm/java/src/feature/proxy/.gitkeep +0 -0
  954. package/project/.sdk/tm/java/src/feature/ratelimit/.gitkeep +0 -0
  955. package/project/.sdk/tm/java/src/feature/rbac/.gitkeep +0 -0
  956. package/project/.sdk/tm/java/src/feature/retry/.gitkeep +0 -0
  957. package/project/.sdk/tm/java/src/feature/streaming/.gitkeep +0 -0
  958. package/project/.sdk/tm/java/src/feature/telemetry/.gitkeep +0 -0
  959. package/project/.sdk/tm/java/src/feature/test/.gitkeep +0 -0
  960. package/project/.sdk/tm/java/src/feature/timeout/.gitkeep +0 -0
  961. package/project/.sdk/tm/java/test/CustomUtilityTest.java +59 -0
  962. package/project/.sdk/tm/java/test/ExistsTest.java +16 -0
  963. package/project/.sdk/tm/java/test/FeatureHarness.java +448 -0
  964. package/project/.sdk/tm/java/test/FeatureTest.java +1018 -0
  965. package/project/.sdk/tm/java/test/NetsimTest.java +59 -0
  966. package/project/.sdk/tm/java/test/PipelineTest.java +618 -0
  967. package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +864 -0
  968. package/project/.sdk/tm/java/test/RunnerSupport.java +545 -0
  969. package/project/.sdk/tm/java/test/StructCorpusTest.java +351 -0
  970. package/project/.sdk/tm/java/test/StructRunner.java +281 -0
  971. package/project/.sdk/tm/java/test/sdk-test-control.json +19 -0
  972. package/project/.sdk/tm/java/utility/Clean.java +12 -0
  973. package/project/.sdk/tm/java/utility/Done.java +29 -0
  974. package/project/.sdk/tm/java/utility/FeatureAdd.java +59 -0
  975. package/project/.sdk/tm/java/utility/FeatureHookUtil.java +72 -0
  976. package/project/.sdk/tm/java/utility/FeatureInit.java +35 -0
  977. package/project/.sdk/tm/java/utility/Fetcher.java +170 -0
  978. package/project/.sdk/tm/java/utility/Json.java +268 -0
  979. package/project/.sdk/tm/java/utility/MakeContext.java +14 -0
  980. package/project/.sdk/tm/java/utility/MakeError.java +81 -0
  981. package/project/.sdk/tm/java/utility/MakeFetchDef.java +48 -0
  982. package/project/.sdk/tm/java/utility/MakeOptions.java +168 -0
  983. package/project/.sdk/tm/java/utility/MakePoint.java +118 -0
  984. package/project/.sdk/tm/java/utility/MakeRequest.java +83 -0
  985. package/project/.sdk/tm/java/utility/MakeResponse.java +54 -0
  986. package/project/.sdk/tm/java/utility/MakeResult.java +68 -0
  987. package/project/.sdk/tm/java/utility/MakeSpec.java +69 -0
  988. package/project/.sdk/tm/java/utility/MakeUrl.java +67 -0
  989. package/project/.sdk/tm/java/utility/Param.java +74 -0
  990. package/project/.sdk/tm/java/utility/PrepareAuth.java +66 -0
  991. package/project/.sdk/tm/java/utility/PrepareBody.java +16 -0
  992. package/project/.sdk/tm/java/utility/PrepareHeaders.java +28 -0
  993. package/project/.sdk/tm/java/utility/PrepareMethod.java +28 -0
  994. package/project/.sdk/tm/java/utility/PrepareParams.java +50 -0
  995. package/project/.sdk/tm/java/utility/PreparePath.java +26 -0
  996. package/project/.sdk/tm/java/utility/PrepareQuery.java +54 -0
  997. package/project/.sdk/tm/java/utility/Register.java +41 -0
  998. package/project/.sdk/tm/java/utility/ResultBasic.java +36 -0
  999. package/project/.sdk/tm/java/utility/ResultBody.java +23 -0
  1000. package/project/.sdk/tm/java/utility/ResultHeaders.java +36 -0
  1001. package/project/.sdk/tm/java/utility/TransformRequest.java +35 -0
  1002. package/project/.sdk/tm/java/utility/TransformResponse.java +52 -0
  1003. package/project/.sdk/tm/java/utility/struct/Struct.java +3550 -0
  1004. package/project/.sdk/tm/js/src/feature/audit/AuditFeature.js +96 -0
  1005. package/project/.sdk/tm/js/src/feature/cache/CacheFeature.js +150 -0
  1006. package/project/.sdk/tm/js/src/feature/clienttrack/ClienttrackFeature.js +104 -0
  1007. package/project/.sdk/tm/js/src/feature/debug/DebugFeature.js +132 -0
  1008. package/project/.sdk/tm/js/src/feature/idempotency/IdempotencyFeature.js +95 -0
  1009. package/project/.sdk/tm/js/src/feature/metrics/MetricsFeature.js +102 -0
  1010. package/project/.sdk/tm/js/src/feature/netsim/NetsimFeature.js +187 -0
  1011. package/project/.sdk/tm/js/src/feature/paging/PagingFeature.js +139 -0
  1012. package/project/.sdk/tm/js/src/feature/proxy/ProxyFeature.js +110 -0
  1013. package/project/.sdk/tm/js/src/feature/ratelimit/RatelimitFeature.js +106 -0
  1014. package/project/.sdk/tm/js/src/feature/rbac/RbacFeature.js +102 -0
  1015. package/project/.sdk/tm/js/src/feature/retry/RetryFeature.js +158 -0
  1016. package/project/.sdk/tm/js/src/feature/streaming/StreamingFeature.js +96 -0
  1017. package/project/.sdk/tm/js/src/feature/telemetry/TelemetryFeature.js +128 -0
  1018. package/project/.sdk/tm/js/src/feature/test/TestFeature.js +58 -1
  1019. package/project/.sdk/tm/js/src/feature/timeout/TimeoutFeature.js +101 -0
  1020. package/project/.sdk/tm/js/src/utility/FeatureHookUtility.js +4 -1
  1021. package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +9 -0
  1022. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +31 -1
  1023. package/project/.sdk/tm/js/test/feature/harness.js +275 -0
  1024. package/project/.sdk/tm/js/test/feature.test.js +772 -0
  1025. package/project/.sdk/tm/js/test/netsim.test.js +43 -0
  1026. package/project/.sdk/tm/js/test/pipeline.test.js +382 -0
  1027. package/project/.sdk/tm/kotlin/LICENSE +22 -0
  1028. package/project/.sdk/tm/kotlin/Makefile +43 -0
  1029. package/project/.sdk/tm/kotlin/VERSION +1 -0
  1030. package/project/.sdk/tm/kotlin/core/Context.kt +247 -0
  1031. package/project/.sdk/tm/kotlin/core/Control.kt +21 -0
  1032. package/project/.sdk/tm/kotlin/core/Helpers.kt +49 -0
  1033. package/project/.sdk/tm/kotlin/core/Interfaces.kt +88 -0
  1034. package/project/.sdk/tm/kotlin/core/Operation.kt +43 -0
  1035. package/project/.sdk/tm/kotlin/core/Point.kt +83 -0
  1036. package/project/.sdk/tm/kotlin/core/Response.kt +43 -0
  1037. package/project/.sdk/tm/kotlin/core/Result.kt +61 -0
  1038. package/project/.sdk/tm/kotlin/core/SdkClient.kt +266 -0
  1039. package/project/.sdk/tm/kotlin/core/Spec.kt +76 -0
  1040. package/project/.sdk/tm/kotlin/core/Utility.kt +93 -0
  1041. package/project/.sdk/tm/kotlin/feature/AuditFeature.kt +96 -0
  1042. package/project/.sdk/tm/kotlin/feature/BaseFeature.kt +57 -0
  1043. package/project/.sdk/tm/kotlin/feature/CacheFeature.kt +167 -0
  1044. package/project/.sdk/tm/kotlin/feature/ClienttrackFeature.kt +84 -0
  1045. package/project/.sdk/tm/kotlin/feature/DebugFeature.kt +141 -0
  1046. package/project/.sdk/tm/kotlin/feature/FeatureOptions.kt +191 -0
  1047. package/project/.sdk/tm/kotlin/feature/IdempotencyFeature.kt +98 -0
  1048. package/project/.sdk/tm/kotlin/feature/LogFeature.kt +92 -0
  1049. package/project/.sdk/tm/kotlin/feature/MetricsFeature.kt +96 -0
  1050. package/project/.sdk/tm/kotlin/feature/NetsimFeature.kt +162 -0
  1051. package/project/.sdk/tm/kotlin/feature/PagingFeature.kt +143 -0
  1052. package/project/.sdk/tm/kotlin/feature/ProxyFeature.kt +109 -0
  1053. package/project/.sdk/tm/kotlin/feature/RatelimitFeature.kt +77 -0
  1054. package/project/.sdk/tm/kotlin/feature/RbacFeature.kt +100 -0
  1055. package/project/.sdk/tm/kotlin/feature/RetryFeature.kt +140 -0
  1056. package/project/.sdk/tm/kotlin/feature/StreamingFeature.kt +90 -0
  1057. package/project/.sdk/tm/kotlin/feature/TelemetryFeature.kt +118 -0
  1058. package/project/.sdk/tm/kotlin/feature/TestFeature.kt +306 -0
  1059. package/project/.sdk/tm/kotlin/feature/TimeoutFeature.kt +74 -0
  1060. package/project/.sdk/tm/kotlin/src/feature/README.md +1 -0
  1061. package/project/.sdk/tm/kotlin/src/feature/audit/.gitkeep +0 -0
  1062. package/project/.sdk/tm/kotlin/src/feature/base/.gitkeep +0 -0
  1063. package/project/.sdk/tm/kotlin/src/feature/cache/.gitkeep +0 -0
  1064. package/project/.sdk/tm/kotlin/src/feature/clienttrack/.gitkeep +0 -0
  1065. package/project/.sdk/tm/kotlin/src/feature/debug/.gitkeep +0 -0
  1066. package/project/.sdk/tm/kotlin/src/feature/idempotency/.gitkeep +0 -0
  1067. package/project/.sdk/tm/kotlin/src/feature/log/.gitkeep +0 -0
  1068. package/project/.sdk/tm/kotlin/src/feature/metrics/.gitkeep +0 -0
  1069. package/project/.sdk/tm/kotlin/src/feature/netsim/.gitkeep +0 -0
  1070. package/project/.sdk/tm/kotlin/src/feature/paging/.gitkeep +0 -0
  1071. package/project/.sdk/tm/kotlin/src/feature/proxy/.gitkeep +0 -0
  1072. package/project/.sdk/tm/kotlin/src/feature/ratelimit/.gitkeep +0 -0
  1073. package/project/.sdk/tm/kotlin/src/feature/rbac/.gitkeep +0 -0
  1074. package/project/.sdk/tm/kotlin/src/feature/retry/.gitkeep +0 -0
  1075. package/project/.sdk/tm/kotlin/src/feature/streaming/.gitkeep +0 -0
  1076. package/project/.sdk/tm/kotlin/src/feature/telemetry/.gitkeep +0 -0
  1077. package/project/.sdk/tm/kotlin/src/feature/test/.gitkeep +0 -0
  1078. package/project/.sdk/tm/kotlin/src/feature/timeout/.gitkeep +0 -0
  1079. package/project/.sdk/tm/kotlin/test/CustomUtilityTest.kt +51 -0
  1080. package/project/.sdk/tm/kotlin/test/ExistsTest.kt +15 -0
  1081. package/project/.sdk/tm/kotlin/test/FeatureHarness.kt +380 -0
  1082. package/project/.sdk/tm/kotlin/test/FeatureTest.kt +924 -0
  1083. package/project/.sdk/tm/kotlin/test/NetsimTest.kt +50 -0
  1084. package/project/.sdk/tm/kotlin/test/PipelineTest.kt +556 -0
  1085. package/project/.sdk/tm/kotlin/test/PrimaryUtilityTest.kt +829 -0
  1086. package/project/.sdk/tm/kotlin/test/RunnerSupport.kt +477 -0
  1087. package/project/.sdk/tm/kotlin/test/StructCorpusTest.kt +297 -0
  1088. package/project/.sdk/tm/kotlin/test/StructRunner.kt +177 -0
  1089. package/project/.sdk/tm/kotlin/test/sdk-test-control.json +19 -0
  1090. package/project/.sdk/tm/kotlin/utility/CoreUtil.kt +96 -0
  1091. package/project/.sdk/tm/kotlin/utility/FeatureUtil.kt +121 -0
  1092. package/project/.sdk/tm/kotlin/utility/Fetcher.kt +156 -0
  1093. package/project/.sdk/tm/kotlin/utility/Json.kt +237 -0
  1094. package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +152 -0
  1095. package/project/.sdk/tm/kotlin/utility/MakePoint.kt +108 -0
  1096. package/project/.sdk/tm/kotlin/utility/MakeReqRes.kt +152 -0
  1097. package/project/.sdk/tm/kotlin/utility/MakeSpecUrl.kt +142 -0
  1098. package/project/.sdk/tm/kotlin/utility/Prepare.kt +236 -0
  1099. package/project/.sdk/tm/kotlin/utility/Register.kt +39 -0
  1100. package/project/.sdk/tm/kotlin/utility/ResultTransform.kt +109 -0
  1101. package/project/.sdk/tm/kotlin/utility/struct/Struct.kt +2697 -0
  1102. package/project/.sdk/tm/lua/feature/audit_feature.lua +132 -0
  1103. package/project/.sdk/tm/lua/feature/cache_feature.lua +188 -0
  1104. package/project/.sdk/tm/lua/feature/clienttrack_feature.lua +127 -0
  1105. package/project/.sdk/tm/lua/feature/debug_feature.lua +194 -0
  1106. package/project/.sdk/tm/lua/feature/idempotency_feature.lua +127 -0
  1107. package/project/.sdk/tm/lua/feature/metrics_feature.lua +135 -0
  1108. package/project/.sdk/tm/lua/feature/netsim_feature.lua +205 -0
  1109. package/project/.sdk/tm/lua/feature/paging_feature.lua +180 -0
  1110. package/project/.sdk/tm/lua/feature/proxy_feature.lua +147 -0
  1111. package/project/.sdk/tm/lua/feature/ratelimit_feature.lua +120 -0
  1112. package/project/.sdk/tm/lua/feature/rbac_feature.lua +141 -0
  1113. package/project/.sdk/tm/lua/feature/retry_feature.lua +188 -0
  1114. package/project/.sdk/tm/lua/feature/streaming_feature.lua +143 -0
  1115. package/project/.sdk/tm/lua/feature/telemetry_feature.lua +159 -0
  1116. package/project/.sdk/tm/lua/feature/test_feature.lua +85 -1
  1117. package/project/.sdk/tm/lua/feature/timeout_feature.lua +94 -0
  1118. package/project/.sdk/tm/lua/src/feature/audit/.gitkeep +0 -0
  1119. package/project/.sdk/tm/lua/src/feature/cache/.gitkeep +0 -0
  1120. package/project/.sdk/tm/lua/src/feature/clienttrack/.gitkeep +0 -0
  1121. package/project/.sdk/tm/lua/src/feature/debug/.gitkeep +0 -0
  1122. package/project/.sdk/tm/lua/src/feature/idempotency/.gitkeep +0 -0
  1123. package/project/.sdk/tm/lua/src/feature/metrics/.gitkeep +0 -0
  1124. package/project/.sdk/tm/lua/src/feature/netsim/.gitkeep +0 -0
  1125. package/project/.sdk/tm/lua/src/feature/paging/.gitkeep +0 -0
  1126. package/project/.sdk/tm/lua/src/feature/proxy/.gitkeep +0 -0
  1127. package/project/.sdk/tm/lua/src/feature/ratelimit/.gitkeep +0 -0
  1128. package/project/.sdk/tm/lua/src/feature/rbac/.gitkeep +0 -0
  1129. package/project/.sdk/tm/lua/src/feature/retry/.gitkeep +0 -0
  1130. package/project/.sdk/tm/lua/src/feature/streaming/.gitkeep +0 -0
  1131. package/project/.sdk/tm/lua/src/feature/telemetry/.gitkeep +0 -0
  1132. package/project/.sdk/tm/lua/src/feature/timeout/.gitkeep +0 -0
  1133. package/project/.sdk/tm/lua/test/feature_test.lua +1244 -0
  1134. package/project/.sdk/tm/lua/test/netsim_test.lua +61 -0
  1135. package/project/.sdk/tm/lua/test/pipeline_test.lua +613 -0
  1136. package/project/.sdk/tm/lua/utility/feature_add.lua +28 -1
  1137. package/project/.sdk/tm/lua/utility/make_error.lua +9 -0
  1138. package/project/.sdk/tm/lua/utility/make_options.lua +58 -0
  1139. package/project/.sdk/tm/lua/utility/make_point.lua +8 -1
  1140. package/project/.sdk/tm/ocaml/LICENSE +21 -0
  1141. package/project/.sdk/tm/ocaml/Makefile +58 -0
  1142. package/project/.sdk/tm/ocaml/VERSION +1 -0
  1143. package/project/.sdk/tm/ocaml/sdk_features.ml +1127 -0
  1144. package/project/.sdk/tm/ocaml/sdk_helpers.ml +110 -0
  1145. package/project/.sdk/tm/ocaml/sdk_runtime.ml +942 -0
  1146. package/project/.sdk/tm/ocaml/sdk_types.ml +259 -0
  1147. package/project/.sdk/tm/ocaml/src/feature/README.md +1 -0
  1148. package/project/.sdk/tm/ocaml/src/feature/audit/.gitkeep +0 -0
  1149. package/project/.sdk/tm/ocaml/src/feature/base/.gitkeep +0 -0
  1150. package/project/.sdk/tm/ocaml/src/feature/cache/.gitkeep +0 -0
  1151. package/project/.sdk/tm/ocaml/src/feature/clienttrack/.gitkeep +0 -0
  1152. package/project/.sdk/tm/ocaml/src/feature/debug/.gitkeep +0 -0
  1153. package/project/.sdk/tm/ocaml/src/feature/idempotency/.gitkeep +0 -0
  1154. package/project/.sdk/tm/ocaml/src/feature/log/.gitkeep +0 -0
  1155. package/project/.sdk/tm/ocaml/src/feature/metrics/.gitkeep +0 -0
  1156. package/project/.sdk/tm/ocaml/src/feature/netsim/.gitkeep +0 -0
  1157. package/project/.sdk/tm/ocaml/src/feature/paging/.gitkeep +0 -0
  1158. package/project/.sdk/tm/ocaml/src/feature/proxy/.gitkeep +0 -0
  1159. package/project/.sdk/tm/ocaml/src/feature/ratelimit/.gitkeep +0 -0
  1160. package/project/.sdk/tm/ocaml/src/feature/rbac/.gitkeep +0 -0
  1161. package/project/.sdk/tm/ocaml/src/feature/retry/.gitkeep +0 -0
  1162. package/project/.sdk/tm/ocaml/src/feature/streaming/.gitkeep +0 -0
  1163. package/project/.sdk/tm/ocaml/src/feature/telemetry/.gitkeep +0 -0
  1164. package/project/.sdk/tm/ocaml/src/feature/test/.gitkeep +0 -0
  1165. package/project/.sdk/tm/ocaml/src/feature/timeout/.gitkeep +0 -0
  1166. package/project/.sdk/tm/ocaml/test/custom_utility.ml +30 -0
  1167. package/project/.sdk/tm/ocaml/test/harness.ml +198 -0
  1168. package/project/.sdk/tm/ocaml/test/struct_corpus.ml +487 -0
  1169. package/project/.sdk/tm/ocaml/test/t_feature.ml +533 -0
  1170. package/project/.sdk/tm/ocaml/test/t_main.ml +5 -0
  1171. package/project/.sdk/tm/ocaml/test/t_pipeline.ml +354 -0
  1172. package/project/.sdk/tm/ocaml/test/testutil.ml +57 -0
  1173. package/project/.sdk/tm/ocaml/utility/voxgig_struct.ml +1858 -0
  1174. package/project/.sdk/tm/ocaml/utility/vregex.ml +254 -0
  1175. package/project/.sdk/tm/perl/LICENSE +22 -0
  1176. package/project/.sdk/tm/perl/Makefile +57 -0
  1177. package/project/.sdk/tm/perl/core/context.pm +138 -0
  1178. package/project/.sdk/tm/perl/core/control.pm +22 -0
  1179. package/project/.sdk/tm/perl/core/error.pm +30 -0
  1180. package/project/.sdk/tm/perl/core/helpers.pm +142 -0
  1181. package/project/.sdk/tm/perl/core/operation.pm +47 -0
  1182. package/project/.sdk/tm/perl/core/response.pm +40 -0
  1183. package/project/.sdk/tm/perl/core/result.pm +45 -0
  1184. package/project/.sdk/tm/perl/core/spec.pm +33 -0
  1185. package/project/.sdk/tm/perl/core/utility_type.pm +32 -0
  1186. package/project/.sdk/tm/perl/feature/audit_feature.pm +128 -0
  1187. package/project/.sdk/tm/perl/feature/base_feature.pm +41 -0
  1188. package/project/.sdk/tm/perl/feature/cache_feature.pm +168 -0
  1189. package/project/.sdk/tm/perl/feature/clienttrack_feature.pm +126 -0
  1190. package/project/.sdk/tm/perl/feature/debug_feature.pm +168 -0
  1191. package/project/.sdk/tm/perl/feature/idempotency_feature.pm +104 -0
  1192. package/project/.sdk/tm/perl/feature/log_feature.pm +77 -0
  1193. package/project/.sdk/tm/perl/feature/metrics_feature.pm +124 -0
  1194. package/project/.sdk/tm/perl/feature/netsim_feature.pm +215 -0
  1195. package/project/.sdk/tm/perl/feature/paging_feature.pm +158 -0
  1196. package/project/.sdk/tm/perl/feature/proxy_feature.pm +128 -0
  1197. package/project/.sdk/tm/perl/feature/ratelimit_feature.pm +126 -0
  1198. package/project/.sdk/tm/perl/feature/rbac_feature.pm +124 -0
  1199. package/project/.sdk/tm/perl/feature/retry_feature.pm +153 -0
  1200. package/project/.sdk/tm/perl/feature/streaming_feature.pm +112 -0
  1201. package/project/.sdk/tm/perl/feature/telemetry_feature.pm +155 -0
  1202. package/project/.sdk/tm/perl/feature/test_feature.pm +314 -0
  1203. package/project/.sdk/tm/perl/feature/timeout_feature.pm +110 -0
  1204. package/project/.sdk/tm/perl/lib/Voxgig/Struct.pm +2897 -0
  1205. package/project/.sdk/tm/perl/src/feature/README.md +3 -0
  1206. package/project/.sdk/tm/perl/src/feature/audit/.gitkeep +0 -0
  1207. package/project/.sdk/tm/perl/src/feature/base/.gitkeep +0 -0
  1208. package/project/.sdk/tm/perl/src/feature/cache/.gitkeep +0 -0
  1209. package/project/.sdk/tm/perl/src/feature/clienttrack/.gitkeep +0 -0
  1210. package/project/.sdk/tm/perl/src/feature/debug/.gitkeep +0 -0
  1211. package/project/.sdk/tm/perl/src/feature/idempotency/.gitkeep +0 -0
  1212. package/project/.sdk/tm/perl/src/feature/log/.gitkeep +0 -0
  1213. package/project/.sdk/tm/perl/src/feature/metrics/.gitkeep +0 -0
  1214. package/project/.sdk/tm/perl/src/feature/netsim/.gitkeep +0 -0
  1215. package/project/.sdk/tm/perl/src/feature/paging/.gitkeep +0 -0
  1216. package/project/.sdk/tm/perl/src/feature/proxy/.gitkeep +0 -0
  1217. package/project/.sdk/tm/perl/src/feature/ratelimit/.gitkeep +0 -0
  1218. package/project/.sdk/tm/perl/src/feature/rbac/.gitkeep +0 -0
  1219. package/project/.sdk/tm/perl/src/feature/retry/.gitkeep +0 -0
  1220. package/project/.sdk/tm/perl/src/feature/streaming/.gitkeep +0 -0
  1221. package/project/.sdk/tm/perl/src/feature/telemetry/.gitkeep +0 -0
  1222. package/project/.sdk/tm/perl/src/feature/test/.gitkeep +0 -0
  1223. package/project/.sdk/tm/perl/src/feature/timeout/.gitkeep +0 -0
  1224. package/project/.sdk/tm/perl/t/feature.t +1054 -0
  1225. package/project/.sdk/tm/perl/t/netsim.t +55 -0
  1226. package/project/.sdk/tm/perl/t/pipeline.t +632 -0
  1227. package/project/.sdk/tm/perl/t/primary_utility.t +1023 -0
  1228. package/project/.sdk/tm/perl/t/runner.pm +140 -0
  1229. package/project/.sdk/tm/perl/t/sdk-test-control.json +19 -0
  1230. package/project/.sdk/tm/perl/t/stream.t +132 -0
  1231. package/project/.sdk/tm/perl/t/struct_runner.pm +275 -0
  1232. package/project/.sdk/tm/perl/t/struct_utility.t +438 -0
  1233. package/project/.sdk/tm/perl/utility/clean.pm +15 -0
  1234. package/project/.sdk/tm/perl/utility/done.pm +34 -0
  1235. package/project/.sdk/tm/perl/utility/feature_add.pm +47 -0
  1236. package/project/.sdk/tm/perl/utility/feature_hook.pm +25 -0
  1237. package/project/.sdk/tm/perl/utility/feature_init.pm +33 -0
  1238. package/project/.sdk/tm/perl/utility/fetcher.pm +112 -0
  1239. package/project/.sdk/tm/perl/utility/make_context.pm +22 -0
  1240. package/project/.sdk/tm/perl/utility/make_error.pm +74 -0
  1241. package/project/.sdk/tm/perl/utility/make_fetch_def.pm +46 -0
  1242. package/project/.sdk/tm/perl/utility/make_options.pm +123 -0
  1243. package/project/.sdk/tm/perl/utility/make_point.pm +104 -0
  1244. package/project/.sdk/tm/perl/utility/make_request.pm +66 -0
  1245. package/project/.sdk/tm/perl/utility/make_response.pm +38 -0
  1246. package/project/.sdk/tm/perl/utility/make_result.pm +53 -0
  1247. package/project/.sdk/tm/perl/utility/make_spec.pm +71 -0
  1248. package/project/.sdk/tm/perl/utility/make_url.pm +63 -0
  1249. package/project/.sdk/tm/perl/utility/param.pm +65 -0
  1250. package/project/.sdk/tm/perl/utility/prepare_auth.pm +56 -0
  1251. package/project/.sdk/tm/perl/utility/prepare_body.pm +17 -0
  1252. package/project/.sdk/tm/perl/utility/prepare_headers.pm +27 -0
  1253. package/project/.sdk/tm/perl/utility/prepare_method.pm +25 -0
  1254. package/project/.sdk/tm/perl/utility/prepare_params.pm +41 -0
  1255. package/project/.sdk/tm/perl/utility/prepare_path.pm +29 -0
  1256. package/project/.sdk/tm/perl/utility/prepare_query.pm +40 -0
  1257. package/project/.sdk/tm/perl/utility/register.pm +53 -0
  1258. package/project/.sdk/tm/perl/utility/result_basic.pm +38 -0
  1259. package/project/.sdk/tm/perl/utility/result_body.pm +28 -0
  1260. package/project/.sdk/tm/perl/utility/result_headers.pm +32 -0
  1261. package/project/.sdk/tm/perl/utility/transform_request.pm +30 -0
  1262. package/project/.sdk/tm/perl/utility/transform_response.pm +43 -0
  1263. package/project/.sdk/tm/php/core/Result.php +10 -0
  1264. package/project/.sdk/tm/php/feature/AuditFeature.php +125 -0
  1265. package/project/.sdk/tm/php/feature/BaseFeature.php +6 -0
  1266. package/project/.sdk/tm/php/feature/CacheFeature.php +158 -0
  1267. package/project/.sdk/tm/php/feature/ClienttrackFeature.php +126 -0
  1268. package/project/.sdk/tm/php/feature/DebugFeature.php +167 -0
  1269. package/project/.sdk/tm/php/feature/IdempotencyFeature.php +102 -0
  1270. package/project/.sdk/tm/php/feature/MetricsFeature.php +122 -0
  1271. package/project/.sdk/tm/php/feature/NetsimFeature.php +190 -0
  1272. package/project/.sdk/tm/php/feature/PagingFeature.php +153 -0
  1273. package/project/.sdk/tm/php/feature/ProxyFeature.php +136 -0
  1274. package/project/.sdk/tm/php/feature/RatelimitFeature.php +116 -0
  1275. package/project/.sdk/tm/php/feature/RbacFeature.php +133 -0
  1276. package/project/.sdk/tm/php/feature/RetryFeature.php +159 -0
  1277. package/project/.sdk/tm/php/feature/StreamingFeature.php +107 -0
  1278. package/project/.sdk/tm/php/feature/TelemetryFeature.php +156 -0
  1279. package/project/.sdk/tm/php/feature/TestFeature.php +80 -1
  1280. package/project/.sdk/tm/php/feature/TimeoutFeature.php +95 -0
  1281. package/project/.sdk/tm/php/src/feature/audit/.gitkeep +0 -0
  1282. package/project/.sdk/tm/php/src/feature/cache/.gitkeep +0 -0
  1283. package/project/.sdk/tm/php/src/feature/clienttrack/.gitkeep +0 -0
  1284. package/project/.sdk/tm/php/src/feature/debug/.gitkeep +0 -0
  1285. package/project/.sdk/tm/php/src/feature/idempotency/.gitkeep +0 -0
  1286. package/project/.sdk/tm/php/src/feature/metrics/.gitkeep +0 -0
  1287. package/project/.sdk/tm/php/src/feature/netsim/.gitkeep +0 -0
  1288. package/project/.sdk/tm/php/src/feature/paging/.gitkeep +0 -0
  1289. package/project/.sdk/tm/php/src/feature/proxy/.gitkeep +0 -0
  1290. package/project/.sdk/tm/php/src/feature/ratelimit/.gitkeep +0 -0
  1291. package/project/.sdk/tm/php/src/feature/rbac/.gitkeep +0 -0
  1292. package/project/.sdk/tm/php/src/feature/retry/.gitkeep +0 -0
  1293. package/project/.sdk/tm/php/src/feature/streaming/.gitkeep +0 -0
  1294. package/project/.sdk/tm/php/src/feature/telemetry/.gitkeep +0 -0
  1295. package/project/.sdk/tm/php/src/feature/timeout/.gitkeep +0 -0
  1296. package/project/.sdk/tm/php/test/FeatureTest.php +1259 -0
  1297. package/project/.sdk/tm/php/test/NetsimTest.php +53 -0
  1298. package/project/.sdk/tm/php/test/PipelineTest.php +674 -0
  1299. package/project/.sdk/tm/php/utility/FeatureAdd.php +32 -1
  1300. package/project/.sdk/tm/php/utility/MakeError.php +9 -0
  1301. package/project/.sdk/tm/php/utility/MakeOptions.php +46 -0
  1302. package/project/.sdk/tm/php/utility/MakePoint.php +7 -0
  1303. package/project/.sdk/tm/py/core/context.py +4 -0
  1304. package/project/.sdk/tm/py/core/control.py +3 -0
  1305. package/project/.sdk/tm/py/feature/audit_feature.py +98 -0
  1306. package/project/.sdk/tm/py/feature/cache_feature.py +138 -0
  1307. package/project/.sdk/tm/py/feature/clienttrack_feature.py +97 -0
  1308. package/project/.sdk/tm/py/feature/debug_feature.py +134 -0
  1309. package/project/.sdk/tm/py/feature/idempotency_feature.py +89 -0
  1310. package/project/.sdk/tm/py/feature/metrics_feature.py +93 -0
  1311. package/project/.sdk/tm/py/feature/netsim_feature.py +170 -0
  1312. package/project/.sdk/tm/py/feature/paging_feature.py +134 -0
  1313. package/project/.sdk/tm/py/feature/proxy_feature.py +104 -0
  1314. package/project/.sdk/tm/py/feature/ratelimit_feature.py +98 -0
  1315. package/project/.sdk/tm/py/feature/rbac_feature.py +102 -0
  1316. package/project/.sdk/tm/py/feature/retry_feature.py +142 -0
  1317. package/project/.sdk/tm/py/feature/streaming_feature.py +84 -0
  1318. package/project/.sdk/tm/py/feature/telemetry_feature.py +128 -0
  1319. package/project/.sdk/tm/py/feature/test_feature.py +70 -1
  1320. package/project/.sdk/tm/py/feature/timeout_feature.py +78 -0
  1321. package/project/.sdk/tm/py/src/feature/audit/.gitkeep +0 -0
  1322. package/project/.sdk/tm/py/src/feature/cache/.gitkeep +0 -0
  1323. package/project/.sdk/tm/py/src/feature/clienttrack/.gitkeep +0 -0
  1324. package/project/.sdk/tm/py/src/feature/debug/.gitkeep +0 -0
  1325. package/project/.sdk/tm/py/src/feature/idempotency/.gitkeep +0 -0
  1326. package/project/.sdk/tm/py/src/feature/metrics/.gitkeep +0 -0
  1327. package/project/.sdk/tm/py/src/feature/netsim/.gitkeep +0 -0
  1328. package/project/.sdk/tm/py/src/feature/paging/.gitkeep +0 -0
  1329. package/project/.sdk/tm/py/src/feature/proxy/.gitkeep +0 -0
  1330. package/project/.sdk/tm/py/src/feature/ratelimit/.gitkeep +0 -0
  1331. package/project/.sdk/tm/py/src/feature/rbac/.gitkeep +0 -0
  1332. package/project/.sdk/tm/py/src/feature/retry/.gitkeep +0 -0
  1333. package/project/.sdk/tm/py/src/feature/streaming/.gitkeep +0 -0
  1334. package/project/.sdk/tm/py/src/feature/telemetry/.gitkeep +0 -0
  1335. package/project/.sdk/tm/py/src/feature/timeout/.gitkeep +0 -0
  1336. package/project/.sdk/tm/py/test/feature_harness.py +336 -0
  1337. package/project/.sdk/tm/py/test/test_feature.py +807 -0
  1338. package/project/.sdk/tm/py/test/test_netsim.py +52 -0
  1339. package/project/.sdk/tm/py/test/test_pipeline.py +606 -0
  1340. package/project/.sdk/tm/py/utility/feature_add.py +25 -1
  1341. package/project/.sdk/tm/py/utility/make_error.py +8 -0
  1342. package/project/.sdk/tm/py/utility/make_options.py +32 -0
  1343. package/project/.sdk/tm/py/utility/make_point.py +8 -2
  1344. package/project/.sdk/tm/py/utility/make_request.py +6 -2
  1345. package/project/.sdk/tm/py/utility/make_response.py +6 -2
  1346. package/project/.sdk/tm/py/utility/make_result.py +6 -2
  1347. package/project/.sdk/tm/py/utility/make_spec.py +6 -2
  1348. package/project/.sdk/tm/rb/core/context.rb +2 -0
  1349. package/project/.sdk/tm/rb/core/control.rb +5 -1
  1350. package/project/.sdk/tm/rb/core/result.rb +2 -1
  1351. package/project/.sdk/tm/rb/feature/audit_feature.rb +103 -0
  1352. package/project/.sdk/tm/rb/feature/base_feature.rb +5 -0
  1353. package/project/.sdk/tm/rb/feature/cache_feature.rb +133 -0
  1354. package/project/.sdk/tm/rb/feature/clienttrack_feature.rb +91 -0
  1355. package/project/.sdk/tm/rb/feature/debug_feature.rb +138 -0
  1356. package/project/.sdk/tm/rb/feature/idempotency_feature.rb +78 -0
  1357. package/project/.sdk/tm/rb/feature/metrics_feature.rb +91 -0
  1358. package/project/.sdk/tm/rb/feature/netsim_feature.rb +167 -0
  1359. package/project/.sdk/tm/rb/feature/paging_feature.rb +120 -0
  1360. package/project/.sdk/tm/rb/feature/proxy_feature.rb +93 -0
  1361. package/project/.sdk/tm/rb/feature/ratelimit_feature.rb +95 -0
  1362. package/project/.sdk/tm/rb/feature/rbac_feature.rb +96 -0
  1363. package/project/.sdk/tm/rb/feature/retry_feature.rb +116 -0
  1364. package/project/.sdk/tm/rb/feature/streaming_feature.rb +85 -0
  1365. package/project/.sdk/tm/rb/feature/telemetry_feature.rb +122 -0
  1366. package/project/.sdk/tm/rb/feature/test_feature.rb +65 -1
  1367. package/project/.sdk/tm/rb/feature/timeout_feature.rb +74 -0
  1368. package/project/.sdk/tm/rb/src/feature/audit/.gitkeep +0 -0
  1369. package/project/.sdk/tm/rb/src/feature/cache/.gitkeep +0 -0
  1370. package/project/.sdk/tm/rb/src/feature/clienttrack/.gitkeep +0 -0
  1371. package/project/.sdk/tm/rb/src/feature/debug/.gitkeep +0 -0
  1372. package/project/.sdk/tm/rb/src/feature/idempotency/.gitkeep +0 -0
  1373. package/project/.sdk/tm/rb/src/feature/metrics/.gitkeep +0 -0
  1374. package/project/.sdk/tm/rb/src/feature/netsim/.gitkeep +0 -0
  1375. package/project/.sdk/tm/rb/src/feature/paging/.gitkeep +0 -0
  1376. package/project/.sdk/tm/rb/src/feature/proxy/.gitkeep +0 -0
  1377. package/project/.sdk/tm/rb/src/feature/ratelimit/.gitkeep +0 -0
  1378. package/project/.sdk/tm/rb/src/feature/rbac/.gitkeep +0 -0
  1379. package/project/.sdk/tm/rb/src/feature/retry/.gitkeep +0 -0
  1380. package/project/.sdk/tm/rb/src/feature/streaming/.gitkeep +0 -0
  1381. package/project/.sdk/tm/rb/src/feature/telemetry/.gitkeep +0 -0
  1382. package/project/.sdk/tm/rb/src/feature/timeout/.gitkeep +0 -0
  1383. package/project/.sdk/tm/rb/test/feature_test.rb +1031 -0
  1384. package/project/.sdk/tm/rb/test/netsim_test.rb +48 -0
  1385. package/project/.sdk/tm/rb/test/pipeline_test.rb +584 -0
  1386. package/project/.sdk/tm/rb/utility/feature_add.rb +28 -1
  1387. package/project/.sdk/tm/rb/utility/make_error.rb +8 -0
  1388. package/project/.sdk/tm/rb/utility/make_options.rb +35 -0
  1389. package/project/.sdk/tm/rb/utility/make_point.rb +7 -1
  1390. package/project/.sdk/tm/rust/LICENSE +22 -0
  1391. package/project/.sdk/tm/rust/Makefile +41 -0
  1392. package/project/.sdk/tm/rust/VERSION +1 -0
  1393. package/project/.sdk/tm/rust/core/context.rs +320 -0
  1394. package/project/.sdk/tm/rust/core/control.rs +37 -0
  1395. package/project/.sdk/tm/rust/core/helpers.rs +168 -0
  1396. package/project/.sdk/tm/rust/core/mod.rs +18 -0
  1397. package/project/.sdk/tm/rust/core/operation.rs +35 -0
  1398. package/project/.sdk/tm/rust/core/point.rs +68 -0
  1399. package/project/.sdk/tm/rust/core/response.rs +38 -0
  1400. package/project/.sdk/tm/rust/core/result.rs +90 -0
  1401. package/project/.sdk/tm/rust/core/spec.rs +109 -0
  1402. package/project/.sdk/tm/rust/core/types.rs +105 -0
  1403. package/project/.sdk/tm/rust/core/utility_type.rs +184 -0
  1404. package/project/.sdk/tm/rust/feature/audit.rs +138 -0
  1405. package/project/.sdk/tm/rust/feature/base.rs +49 -0
  1406. package/project/.sdk/tm/rust/feature/cache.rs +198 -0
  1407. package/project/.sdk/tm/rust/feature/clienttrack.rs +154 -0
  1408. package/project/.sdk/tm/rust/feature/debug.rs +188 -0
  1409. package/project/.sdk/tm/rust/feature/idempotency.rs +139 -0
  1410. package/project/.sdk/tm/rust/feature/log.rs +114 -0
  1411. package/project/.sdk/tm/rust/feature/metrics.rs +136 -0
  1412. package/project/.sdk/tm/rust/feature/mod.rs +24 -0
  1413. package/project/.sdk/tm/rust/feature/netsim.rs +233 -0
  1414. package/project/.sdk/tm/rust/feature/paging.rs +209 -0
  1415. package/project/.sdk/tm/rust/feature/proxy.rs +165 -0
  1416. package/project/.sdk/tm/rust/feature/ratelimit.rs +116 -0
  1417. package/project/.sdk/tm/rust/feature/rbac.rs +152 -0
  1418. package/project/.sdk/tm/rust/feature/retry.rs +190 -0
  1419. package/project/.sdk/tm/rust/feature/streaming.rs +124 -0
  1420. package/project/.sdk/tm/rust/feature/support.rs +145 -0
  1421. package/project/.sdk/tm/rust/feature/telemetry.rs +185 -0
  1422. package/project/.sdk/tm/rust/feature/test.rs +397 -0
  1423. package/project/.sdk/tm/rust/feature/timeout.rs +103 -0
  1424. package/project/.sdk/tm/rust/src/feature/README.md +1 -0
  1425. package/project/.sdk/tm/rust/src/feature/audit/.gitkeep +0 -0
  1426. package/project/.sdk/tm/rust/src/feature/base/.gitkeep +0 -0
  1427. package/project/.sdk/tm/rust/src/feature/cache/.gitkeep +0 -0
  1428. package/project/.sdk/tm/rust/src/feature/clienttrack/.gitkeep +0 -0
  1429. package/project/.sdk/tm/rust/src/feature/debug/.gitkeep +0 -0
  1430. package/project/.sdk/tm/rust/src/feature/idempotency/.gitkeep +0 -0
  1431. package/project/.sdk/tm/rust/src/feature/log/.gitkeep +0 -0
  1432. package/project/.sdk/tm/rust/src/feature/metrics/.gitkeep +0 -0
  1433. package/project/.sdk/tm/rust/src/feature/netsim/.gitkeep +0 -0
  1434. package/project/.sdk/tm/rust/src/feature/paging/.gitkeep +0 -0
  1435. package/project/.sdk/tm/rust/src/feature/proxy/.gitkeep +0 -0
  1436. package/project/.sdk/tm/rust/src/feature/ratelimit/.gitkeep +0 -0
  1437. package/project/.sdk/tm/rust/src/feature/rbac/.gitkeep +0 -0
  1438. package/project/.sdk/tm/rust/src/feature/retry/.gitkeep +0 -0
  1439. package/project/.sdk/tm/rust/src/feature/streaming/.gitkeep +0 -0
  1440. package/project/.sdk/tm/rust/src/feature/telemetry/.gitkeep +0 -0
  1441. package/project/.sdk/tm/rust/src/feature/test/.gitkeep +0 -0
  1442. package/project/.sdk/tm/rust/src/feature/timeout/.gitkeep +0 -0
  1443. package/project/.sdk/tm/rust/tests/common/mod.rs +969 -0
  1444. package/project/.sdk/tm/rust/tests/custom_utility_test.rs +69 -0
  1445. package/project/.sdk/tm/rust/tests/feature_test.rs +1864 -0
  1446. package/project/.sdk/tm/rust/tests/netsim_test.rs +78 -0
  1447. package/project/.sdk/tm/rust/tests/pipeline_test.rs +699 -0
  1448. package/project/.sdk/tm/rust/tests/primary_utility_test.rs +999 -0
  1449. package/project/.sdk/tm/rust/tests/sdk-test-control.json +19 -0
  1450. package/project/.sdk/tm/rust/tests/struct_runner/mod.rs +424 -0
  1451. package/project/.sdk/tm/rust/tests/struct_utility_test.rs +733 -0
  1452. package/project/.sdk/tm/rust/utility/clean.rs +13 -0
  1453. package/project/.sdk/tm/rust/utility/done.rs +31 -0
  1454. package/project/.sdk/tm/rust/utility/feature_add.rs +46 -0
  1455. package/project/.sdk/tm/rust/utility/feature_hook.rs +18 -0
  1456. package/project/.sdk/tm/rust/utility/feature_init.rs +26 -0
  1457. package/project/.sdk/tm/rust/utility/fetcher.rs +142 -0
  1458. package/project/.sdk/tm/rust/utility/jsonparse.rs +211 -0
  1459. package/project/.sdk/tm/rust/utility/make_context.rs +7 -0
  1460. package/project/.sdk/tm/rust/utility/make_error.rs +79 -0
  1461. package/project/.sdk/tm/rust/utility/make_fetch_def.rs +42 -0
  1462. package/project/.sdk/tm/rust/utility/make_options.rs +175 -0
  1463. package/project/.sdk/tm/rust/utility/make_point.rs +116 -0
  1464. package/project/.sdk/tm/rust/utility/make_request.rs +73 -0
  1465. package/project/.sdk/tm/rust/utility/make_response.rs +56 -0
  1466. package/project/.sdk/tm/rust/utility/make_result.rs +64 -0
  1467. package/project/.sdk/tm/rust/utility/make_spec.rs +70 -0
  1468. package/project/.sdk/tm/rust/utility/make_url.rs +83 -0
  1469. package/project/.sdk/tm/rust/utility/mod.rs +36 -0
  1470. package/project/.sdk/tm/rust/utility/param.rs +67 -0
  1471. package/project/.sdk/tm/rust/utility/prepare_auth.rs +65 -0
  1472. package/project/.sdk/tm/rust/utility/prepare_body.rs +14 -0
  1473. package/project/.sdk/tm/rust/utility/prepare_headers.rs +23 -0
  1474. package/project/.sdk/tm/rust/utility/prepare_method.rs +18 -0
  1475. package/project/.sdk/tm/rust/utility/prepare_params.rs +33 -0
  1476. package/project/.sdk/tm/rust/utility/prepare_path.rs +17 -0
  1477. package/project/.sdk/tm/rust/utility/prepare_query.rs +47 -0
  1478. package/project/.sdk/tm/rust/utility/result_basic.rs +35 -0
  1479. package/project/.sdk/tm/rust/utility/result_body.rs +26 -0
  1480. package/project/.sdk/tm/rust/utility/result_headers.rs +24 -0
  1481. package/project/.sdk/tm/rust/utility/transform_request.rs +31 -0
  1482. package/project/.sdk/tm/rust/utility/transform_response.rs +55 -0
  1483. package/project/.sdk/tm/rust/utility/voxgigstruct/consts.rs +122 -0
  1484. package/project/.sdk/tm/rust/utility/voxgigstruct/major.rs +2688 -0
  1485. package/project/.sdk/tm/rust/utility/voxgigstruct/mini.rs +1081 -0
  1486. package/project/.sdk/tm/rust/utility/voxgigstruct/mod.rs +70 -0
  1487. package/project/.sdk/tm/rust/utility/voxgigstruct/ordered_map.rs +159 -0
  1488. package/project/.sdk/tm/rust/utility/voxgigstruct/re.rs +1229 -0
  1489. package/project/.sdk/tm/rust/utility/voxgigstruct/value.rs +372 -0
  1490. package/project/.sdk/tm/scala/LICENSE +22 -0
  1491. package/project/.sdk/tm/scala/Makefile +24 -0
  1492. package/project/.sdk/tm/scala/VERSION +1 -0
  1493. package/project/.sdk/tm/scala/core/Context.scala +160 -0
  1494. package/project/.sdk/tm/scala/core/Contracts.scala +76 -0
  1495. package/project/.sdk/tm/scala/core/Control.scala +23 -0
  1496. package/project/.sdk/tm/scala/core/Helpers.scala +38 -0
  1497. package/project/.sdk/tm/scala/core/Operation.scala +37 -0
  1498. package/project/.sdk/tm/scala/core/Point.scala +44 -0
  1499. package/project/.sdk/tm/scala/core/Response.scala +37 -0
  1500. package/project/.sdk/tm/scala/core/Result.scala +42 -0
  1501. package/project/.sdk/tm/scala/core/SdkClient.scala +220 -0
  1502. package/project/.sdk/tm/scala/core/SdkError.scala +15 -0
  1503. package/project/.sdk/tm/scala/core/Spec.scala +39 -0
  1504. package/project/.sdk/tm/scala/core/Types.scala +31 -0
  1505. package/project/.sdk/tm/scala/core/Utility.scala +85 -0
  1506. package/project/.sdk/tm/scala/feature/AuditFeature.scala +101 -0
  1507. package/project/.sdk/tm/scala/feature/BaseFeature.scala +21 -0
  1508. package/project/.sdk/tm/scala/feature/CacheFeature.scala +181 -0
  1509. package/project/.sdk/tm/scala/feature/ClienttrackFeature.scala +93 -0
  1510. package/project/.sdk/tm/scala/feature/DebugFeature.scala +149 -0
  1511. package/project/.sdk/tm/scala/feature/FeatureOptions.scala +111 -0
  1512. package/project/.sdk/tm/scala/feature/IdempotencyFeature.scala +106 -0
  1513. package/project/.sdk/tm/scala/feature/LogFeature.scala +64 -0
  1514. package/project/.sdk/tm/scala/feature/MetricsFeature.scala +105 -0
  1515. package/project/.sdk/tm/scala/feature/NetsimFeature.scala +134 -0
  1516. package/project/.sdk/tm/scala/feature/PagingFeature.scala +170 -0
  1517. package/project/.sdk/tm/scala/feature/ProxyFeature.scala +113 -0
  1518. package/project/.sdk/tm/scala/feature/RatelimitFeature.scala +58 -0
  1519. package/project/.sdk/tm/scala/feature/RbacFeature.scala +90 -0
  1520. package/project/.sdk/tm/scala/feature/RetryFeature.scala +104 -0
  1521. package/project/.sdk/tm/scala/feature/StreamingFeature.scala +98 -0
  1522. package/project/.sdk/tm/scala/feature/TelemetryFeature.scala +129 -0
  1523. package/project/.sdk/tm/scala/feature/TestFeature.scala +253 -0
  1524. package/project/.sdk/tm/scala/feature/TimeoutFeature.scala +57 -0
  1525. package/project/.sdk/tm/scala/sdktest/SdkTestMain.scala +766 -0
  1526. package/project/.sdk/tm/scala/sdktest/SdkTestSupport.scala +93 -0
  1527. package/project/.sdk/tm/scala/sdktest/StructCorpus.scala +0 -0
  1528. package/project/.sdk/tm/scala/sdktest/sdk-test-control.json +19 -0
  1529. package/project/.sdk/tm/scala/src/feature/README.md +1 -0
  1530. package/project/.sdk/tm/scala/src/feature/audit/.gitkeep +0 -0
  1531. package/project/.sdk/tm/scala/src/feature/base/.gitkeep +0 -0
  1532. package/project/.sdk/tm/scala/src/feature/cache/.gitkeep +0 -0
  1533. package/project/.sdk/tm/scala/src/feature/clienttrack/.gitkeep +0 -0
  1534. package/project/.sdk/tm/scala/src/feature/debug/.gitkeep +0 -0
  1535. package/project/.sdk/tm/scala/src/feature/idempotency/.gitkeep +0 -0
  1536. package/project/.sdk/tm/scala/src/feature/log/.gitkeep +0 -0
  1537. package/project/.sdk/tm/scala/src/feature/metrics/.gitkeep +0 -0
  1538. package/project/.sdk/tm/scala/src/feature/netsim/.gitkeep +0 -0
  1539. package/project/.sdk/tm/scala/src/feature/paging/.gitkeep +0 -0
  1540. package/project/.sdk/tm/scala/src/feature/proxy/.gitkeep +0 -0
  1541. package/project/.sdk/tm/scala/src/feature/ratelimit/.gitkeep +0 -0
  1542. package/project/.sdk/tm/scala/src/feature/rbac/.gitkeep +0 -0
  1543. package/project/.sdk/tm/scala/src/feature/retry/.gitkeep +0 -0
  1544. package/project/.sdk/tm/scala/src/feature/streaming/.gitkeep +0 -0
  1545. package/project/.sdk/tm/scala/src/feature/telemetry/.gitkeep +0 -0
  1546. package/project/.sdk/tm/scala/src/feature/test/.gitkeep +0 -0
  1547. package/project/.sdk/tm/scala/src/feature/timeout/.gitkeep +0 -0
  1548. package/project/.sdk/tm/scala/utility/FeatureUtils.scala +68 -0
  1549. package/project/.sdk/tm/scala/utility/Fetcher.scala +129 -0
  1550. package/project/.sdk/tm/scala/utility/Json.java +268 -0
  1551. package/project/.sdk/tm/scala/utility/Make.scala +463 -0
  1552. package/project/.sdk/tm/scala/utility/MakeSpec.scala +49 -0
  1553. package/project/.sdk/tm/scala/utility/Misc.scala +68 -0
  1554. package/project/.sdk/tm/scala/utility/Prepare.scala +142 -0
  1555. package/project/.sdk/tm/scala/utility/Register.scala +38 -0
  1556. package/project/.sdk/tm/scala/utility/Results.scala +63 -0
  1557. package/project/.sdk/tm/scala/utility/StructUtility.scala +29 -0
  1558. package/project/.sdk/tm/scala/utility/Transform.scala +52 -0
  1559. package/project/.sdk/tm/scala/utility/struct/Struct.java +3550 -0
  1560. package/project/.sdk/tm/scala/utility/struct/voxgig_struct.scala +1833 -0
  1561. package/project/.sdk/tm/swift/LICENSE +22 -0
  1562. package/project/.sdk/tm/swift/Makefile +41 -0
  1563. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Constants.swift +113 -0
  1564. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Inject.swift +260 -0
  1565. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Injection.swift +111 -0
  1566. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/JSON.swift +327 -0
  1567. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Merge.swift +55 -0
  1568. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Minor.swift +601 -0
  1569. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/OrderedDictionary.swift +79 -0
  1570. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Path.swift +157 -0
  1571. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Select.swift +259 -0
  1572. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Transform.swift +462 -0
  1573. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Validate.swift +378 -0
  1574. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Value.swift +184 -0
  1575. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Walk.swift +44 -0
  1576. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Context.swift +161 -0
  1577. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Control.swift +20 -0
  1578. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Operation.swift +27 -0
  1579. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Point.swift +37 -0
  1580. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Response.swift +29 -0
  1581. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Result.swift +41 -0
  1582. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Spec.swift +36 -0
  1583. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Support.swift +98 -0
  1584. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Types.swift +25 -0
  1585. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Utility.swift +81 -0
  1586. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/AuditFeature.swift +99 -0
  1587. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/BaseFeature.swift +60 -0
  1588. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/CacheFeature.swift +164 -0
  1589. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/ClienttrackFeature.swift +95 -0
  1590. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/DebugFeature.swift +126 -0
  1591. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/FeatureOptions.swift +96 -0
  1592. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/IdempotencyFeature.swift +80 -0
  1593. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/LogFeature.swift +69 -0
  1594. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/MetricsFeature.swift +103 -0
  1595. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/NetsimFeature.swift +177 -0
  1596. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/PagingFeature.swift +154 -0
  1597. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/ProxyFeature.swift +122 -0
  1598. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/RatelimitFeature.swift +79 -0
  1599. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/RbacFeature.swift +103 -0
  1600. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/RetryFeature.swift +150 -0
  1601. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/StreamingFeature.swift +82 -0
  1602. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TelemetryFeature.swift +119 -0
  1603. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TestFeature.swift +257 -0
  1604. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TimeoutFeature.swift +83 -0
  1605. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Feature.swift +56 -0
  1606. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Fetcher.swift +107 -0
  1607. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Make.swift +321 -0
  1608. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeError.swift +56 -0
  1609. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +151 -0
  1610. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Prepare.swift +157 -0
  1611. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Register.swift +40 -0
  1612. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +107 -0
  1613. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/CustomUtilityTest.swift +44 -0
  1614. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/ExistsTest.swift +12 -0
  1615. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/FeatureTest.swift +1049 -0
  1616. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/NetsimTest.swift +50 -0
  1617. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PipelineTest.swift +398 -0
  1618. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PrimaryUtilityTest.swift +750 -0
  1619. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/Runner.swift +237 -0
  1620. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/StructUtilityTest.swift +523 -0
  1621. package/project/.sdk/tm/swift/VERSION +1 -0
  1622. package/project/.sdk/tm/swift/src/feature/README.md +6 -0
  1623. package/project/.sdk/tm/swift/src/feature/audit/.gitkeep +0 -0
  1624. package/project/.sdk/tm/swift/src/feature/base/.gitkeep +0 -0
  1625. package/project/.sdk/tm/swift/src/feature/cache/.gitkeep +0 -0
  1626. package/project/.sdk/tm/swift/src/feature/clienttrack/.gitkeep +0 -0
  1627. package/project/.sdk/tm/swift/src/feature/debug/.gitkeep +0 -0
  1628. package/project/.sdk/tm/swift/src/feature/idempotency/.gitkeep +0 -0
  1629. package/project/.sdk/tm/swift/src/feature/log/.gitkeep +0 -0
  1630. package/project/.sdk/tm/swift/src/feature/metrics/.gitkeep +0 -0
  1631. package/project/.sdk/tm/swift/src/feature/netsim/.gitkeep +0 -0
  1632. package/project/.sdk/tm/swift/src/feature/paging/.gitkeep +0 -0
  1633. package/project/.sdk/tm/swift/src/feature/proxy/.gitkeep +0 -0
  1634. package/project/.sdk/tm/swift/src/feature/ratelimit/.gitkeep +0 -0
  1635. package/project/.sdk/tm/swift/src/feature/rbac/.gitkeep +0 -0
  1636. package/project/.sdk/tm/swift/src/feature/retry/.gitkeep +0 -0
  1637. package/project/.sdk/tm/swift/src/feature/streaming/.gitkeep +0 -0
  1638. package/project/.sdk/tm/swift/src/feature/telemetry/.gitkeep +0 -0
  1639. package/project/.sdk/tm/swift/src/feature/test/.gitkeep +0 -0
  1640. package/project/.sdk/tm/swift/src/feature/timeout/.gitkeep +0 -0
  1641. package/project/.sdk/tm/ts/Makefile +6 -1
  1642. package/project/.sdk/tm/ts/src/feature/audit/AuditFeature.ts +98 -0
  1643. package/project/.sdk/tm/ts/src/feature/cache/CacheFeature.ts +152 -0
  1644. package/project/.sdk/tm/ts/src/feature/clienttrack/ClienttrackFeature.ts +106 -0
  1645. package/project/.sdk/tm/ts/src/feature/debug/DebugFeature.ts +134 -0
  1646. package/project/.sdk/tm/ts/src/feature/idempotency/IdempotencyFeature.ts +97 -0
  1647. package/project/.sdk/tm/ts/src/feature/metrics/MetricsFeature.ts +104 -0
  1648. package/project/.sdk/tm/ts/src/feature/netsim/NetsimFeature.ts +189 -0
  1649. package/project/.sdk/tm/ts/src/feature/paging/PagingFeature.ts +141 -0
  1650. package/project/.sdk/tm/ts/src/feature/proxy/ProxyFeature.ts +112 -0
  1651. package/project/.sdk/tm/ts/src/feature/ratelimit/RatelimitFeature.ts +108 -0
  1652. package/project/.sdk/tm/ts/src/feature/rbac/RbacFeature.ts +104 -0
  1653. package/project/.sdk/tm/ts/src/feature/retry/RetryFeature.ts +160 -0
  1654. package/project/.sdk/tm/ts/src/feature/streaming/StreamingFeature.ts +98 -0
  1655. package/project/.sdk/tm/ts/src/feature/telemetry/TelemetryFeature.ts +130 -0
  1656. package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +58 -1
  1657. package/project/.sdk/tm/ts/src/feature/timeout/TimeoutFeature.ts +103 -0
  1658. package/project/.sdk/tm/ts/src/utility/FeatureHookUtility.ts +4 -1
  1659. package/project/.sdk/tm/ts/src/utility/MakeErrorUtility.ts +9 -0
  1660. package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +31 -1
  1661. package/project/.sdk/tm/ts/test/feature/harness.ts +293 -0
  1662. package/project/.sdk/tm/ts/test/feature.test.ts +772 -0
  1663. package/project/.sdk/tm/ts/test/netsim.test.ts +43 -0
  1664. package/project/.sdk/tm/ts/test/pipeline.test.ts +382 -0
  1665. package/project/.sdk/tm/zig/LICENSE +21 -0
  1666. package/project/.sdk/tm/zig/Makefile +31 -0
  1667. package/project/.sdk/tm/zig/VERSION +1 -0
  1668. package/project/.sdk/tm/zig/build.zig +58 -0
  1669. package/project/.sdk/tm/zig/build.zig.zon +11 -0
  1670. package/project/.sdk/tm/zig/core/context.zig +258 -0
  1671. package/project/.sdk/tm/zig/core/control.zig +26 -0
  1672. package/project/.sdk/tm/zig/core/error.zig +28 -0
  1673. package/project/.sdk/tm/zig/core/helpers.zig +326 -0
  1674. package/project/.sdk/tm/zig/core/mem.zig +20 -0
  1675. package/project/.sdk/tm/zig/core/operation.zig +34 -0
  1676. package/project/.sdk/tm/zig/core/point.zig +63 -0
  1677. package/project/.sdk/tm/zig/core/response.zig +32 -0
  1678. package/project/.sdk/tm/zig/core/result.zig +73 -0
  1679. package/project/.sdk/tm/zig/core/spec.zig +68 -0
  1680. package/project/.sdk/tm/zig/core/types.zig +101 -0
  1681. package/project/.sdk/tm/zig/core/utility.zig +1115 -0
  1682. package/project/.sdk/tm/zig/feature/audit.zig +131 -0
  1683. package/project/.sdk/tm/zig/feature/base.zig +52 -0
  1684. package/project/.sdk/tm/zig/feature/cache.zig +216 -0
  1685. package/project/.sdk/tm/zig/feature/clienttrack.zig +129 -0
  1686. package/project/.sdk/tm/zig/feature/debug.zig +191 -0
  1687. package/project/.sdk/tm/zig/feature/idempotency.zig +121 -0
  1688. package/project/.sdk/tm/zig/feature/log.zig +93 -0
  1689. package/project/.sdk/tm/zig/feature/metrics.zig +145 -0
  1690. package/project/.sdk/tm/zig/feature/netsim.zig +186 -0
  1691. package/project/.sdk/tm/zig/feature/paging.zig +201 -0
  1692. package/project/.sdk/tm/zig/feature/proxy.zig +180 -0
  1693. package/project/.sdk/tm/zig/feature/ratelimit.zig +123 -0
  1694. package/project/.sdk/tm/zig/feature/rbac.zig +126 -0
  1695. package/project/.sdk/tm/zig/feature/retry.zig +167 -0
  1696. package/project/.sdk/tm/zig/feature/streaming.zig +127 -0
  1697. package/project/.sdk/tm/zig/feature/support.zig +128 -0
  1698. package/project/.sdk/tm/zig/feature/telemetry.zig +165 -0
  1699. package/project/.sdk/tm/zig/feature/test.zig +315 -0
  1700. package/project/.sdk/tm/zig/feature/timeout.zig +105 -0
  1701. package/project/.sdk/tm/zig/root.zig +74 -0
  1702. package/project/.sdk/tm/zig/src/feature/README.md +1 -0
  1703. package/project/.sdk/tm/zig/src/feature/audit/.gitkeep +0 -0
  1704. package/project/.sdk/tm/zig/src/feature/base/.gitkeep +0 -0
  1705. package/project/.sdk/tm/zig/src/feature/cache/.gitkeep +0 -0
  1706. package/project/.sdk/tm/zig/src/feature/clienttrack/.gitkeep +0 -0
  1707. package/project/.sdk/tm/zig/src/feature/debug/.gitkeep +0 -0
  1708. package/project/.sdk/tm/zig/src/feature/idempotency/.gitkeep +0 -0
  1709. package/project/.sdk/tm/zig/src/feature/log/.gitkeep +0 -0
  1710. package/project/.sdk/tm/zig/src/feature/metrics/.gitkeep +0 -0
  1711. package/project/.sdk/tm/zig/src/feature/netsim/.gitkeep +0 -0
  1712. package/project/.sdk/tm/zig/src/feature/paging/.gitkeep +0 -0
  1713. package/project/.sdk/tm/zig/src/feature/proxy/.gitkeep +0 -0
  1714. package/project/.sdk/tm/zig/src/feature/ratelimit/.gitkeep +0 -0
  1715. package/project/.sdk/tm/zig/src/feature/rbac/.gitkeep +0 -0
  1716. package/project/.sdk/tm/zig/src/feature/retry/.gitkeep +0 -0
  1717. package/project/.sdk/tm/zig/src/feature/streaming/.gitkeep +0 -0
  1718. package/project/.sdk/tm/zig/src/feature/telemetry/.gitkeep +0 -0
  1719. package/project/.sdk/tm/zig/src/feature/test/.gitkeep +0 -0
  1720. package/project/.sdk/tm/zig/src/feature/timeout/.gitkeep +0 -0
  1721. package/project/.sdk/tm/zig/test/feature_test.zig +1045 -0
  1722. package/project/.sdk/tm/zig/test/fh.zig +531 -0
  1723. package/project/.sdk/tm/zig/test/gotcha_test.zig +230 -0
  1724. package/project/.sdk/tm/zig/test/pipeline_test.zig +493 -0
  1725. package/project/.sdk/tm/zig/test/primary_utility_test.zig +346 -0
  1726. package/project/.sdk/tm/zig/test/struct_corpus.zig +1145 -0
  1727. package/project/.sdk/tm/zig/test/struct_runner.zig +226 -0
  1728. package/project/.sdk/tm/zig/utility/jsonparse.zig +13 -0
  1729. package/project/.sdk/tm/zig/utility/voxgigstruct/regex.zig +779 -0
  1730. package/project/.sdk/tm/zig/utility/voxgigstruct/struct.zig +4400 -0
@@ -0,0 +1,4400 @@
1
+ // Copyright (c) 2025-2026 Voxgig Ltd. MIT LICENSE.
2
+
3
+ // Voxgig Struct
4
+ // =============
5
+ //
6
+ // Utility functions to manipulate in-memory JSON-like data structures.
7
+ // Zig port from the canonical TypeScript implementation.
8
+
9
+ const std = @import("std");
10
+ const Allocator = std.mem.Allocator;
11
+
12
+ // Keep std.json types for parsing at the boundary.
13
+ pub const StdJsonValue = std.json.Value;
14
+
15
+ // ============================================================================
16
+ // MapRef / ListRef — heap-allocated wrappers for pointer-stable mutations.
17
+ // All holders of the same *MapRef / *ListRef see mutations.
18
+ // ============================================================================
19
+
20
+ pub const MapData = std.StringArrayHashMap(JsonValue);
21
+ pub const ListData = std.ArrayList(JsonValue);
22
+
23
+ pub const MapRef = struct {
24
+ data: MapData,
25
+
26
+ pub fn get(self: *const MapRef, key: []const u8) ?JsonValue {
27
+ return self.data.get(key);
28
+ }
29
+
30
+ pub fn put(self: *MapRef, key: []const u8, val: JsonValue) !void {
31
+ try self.data.put(key, val);
32
+ }
33
+
34
+ pub fn count(self: *const MapRef) usize {
35
+ return @intCast(self.data.count());
36
+ }
37
+
38
+ pub fn iterator(self: *const MapRef) MapData.Iterator {
39
+ return self.data.iterator();
40
+ }
41
+
42
+ pub fn fetchOrderedRemove(self: *MapRef, key: []const u8) ?MapData.KV {
43
+ return self.data.fetchOrderedRemove(key);
44
+ }
45
+ };
46
+
47
+ pub const ListRef = struct {
48
+ data: ListData,
49
+
50
+ pub fn append(self: *ListRef, val: JsonValue) !void {
51
+ try self.data.append(val);
52
+ }
53
+
54
+ pub fn orderedRemove(self: *ListRef, idx: usize) JsonValue {
55
+ return self.data.orderedRemove(idx);
56
+ }
57
+
58
+ pub fn insert(self: *ListRef, idx: usize, val: JsonValue) !void {
59
+ try self.data.insert(idx, val);
60
+ }
61
+ };
62
+
63
+ // Function signature for values stored in the JSON tree.
64
+ // Extended for the SDK: a callable carries a captured context pointer so
65
+ // custom utilities, injected clocks/keygens and mock transports can hold
66
+ // state. Stored by pointer so it survives `clone` (shallow) unchanged.
67
+ pub const Callable = struct {
68
+ ctx: *anyopaque,
69
+ call: *const fn (ctx: *anyopaque, allocator: Allocator, arg: JsonValue) anyerror!JsonValue,
70
+ };
71
+ pub const JsonFunc = *const Callable;
72
+
73
+ // Custom value type with pointer-stable containers.
74
+ pub const JsonValue = union(enum) {
75
+ null,
76
+ bool: bool,
77
+ integer: i64,
78
+ float: f64,
79
+ string: []const u8,
80
+ number_string: []const u8,
81
+ object: *MapRef,
82
+ array: *ListRef,
83
+ function: JsonFunc,
84
+
85
+ pub fn makeMap(allocator: Allocator) !JsonValue {
86
+ const mr = try allocator.create(MapRef);
87
+ mr.* = .{ .data = MapData.init(allocator) };
88
+ return JsonValue{ .object = mr };
89
+ }
90
+
91
+ pub fn makeList(allocator: Allocator) !JsonValue {
92
+ const lr = try allocator.create(ListRef);
93
+ lr.* = .{ .data = ListData.init(allocator) };
94
+ return JsonValue{ .array = lr };
95
+ }
96
+ };
97
+
98
+ // Convert from std.json.Value to our pointer-stable JsonValue.
99
+ pub fn fromStdJson(allocator: Allocator, jv: StdJsonValue) anyerror!JsonValue {
100
+ return switch (jv) {
101
+ .null => JsonValue{ .null = {} },
102
+ .bool => |b| JsonValue{ .bool = b },
103
+ .integer => |i| JsonValue{ .integer = i },
104
+ .float => |f| JsonValue{ .float = f },
105
+ .string => |s| JsonValue{ .string = s },
106
+ .number_string => |s| JsonValue{ .number_string = s },
107
+ .object => |obj| {
108
+ const mr = try allocator.create(MapRef);
109
+ mr.* = .{ .data = MapData.init(allocator) };
110
+ var it = obj.iterator();
111
+ while (it.next()) |kv| {
112
+ try mr.data.put(kv.key_ptr.*, try fromStdJson(allocator, kv.value_ptr.*));
113
+ }
114
+ return JsonValue{ .object = mr };
115
+ },
116
+ .array => |arr| {
117
+ const lr = try allocator.create(ListRef);
118
+ lr.* = .{ .data = ListData.init(allocator) };
119
+ for (arr.items) |item| {
120
+ try lr.data.append(try fromStdJson(allocator, item));
121
+ }
122
+ return JsonValue{ .array = lr };
123
+ },
124
+ };
125
+ }
126
+
127
+ // Convert from our JsonValue back to std.json.Value.
128
+ pub fn toStdJson(allocator: Allocator, v: JsonValue) anyerror!StdJsonValue {
129
+ return switch (v) {
130
+ .null => StdJsonValue{ .null = {} },
131
+ .bool => |b| StdJsonValue{ .bool = b },
132
+ .integer => |i| StdJsonValue{ .integer = i },
133
+ .float => |f| StdJsonValue{ .float = f },
134
+ .string => |s| StdJsonValue{ .string = s },
135
+ .number_string => |s| StdJsonValue{ .number_string = s },
136
+ .object => |mr| {
137
+ var obj = std.json.ObjectMap.init(allocator);
138
+ var it = mr.data.iterator();
139
+ while (it.next()) |kv| {
140
+ try obj.put(kv.key_ptr.*, try toStdJson(allocator, kv.value_ptr.*));
141
+ }
142
+ return StdJsonValue{ .object = obj };
143
+ },
144
+ .array => |lr| {
145
+ var arr = std.json.Array.init(allocator);
146
+ for (lr.data.items) |item| {
147
+ try arr.append(try toStdJson(allocator, item));
148
+ }
149
+ return StdJsonValue{ .array = arr };
150
+ },
151
+ .function => StdJsonValue{ .null = {} },
152
+ };
153
+ }
154
+
155
+ // Mode value for inject step (bitfield).
156
+ pub const M_KEYPRE: i32 = 1;
157
+ pub const M_KEYPOST: i32 = 2;
158
+ pub const M_VAL: i32 = 4;
159
+
160
+ // Special strings.
161
+ pub const S_BKEY = "`$KEY`";
162
+ pub const S_BANNO = "`$ANNO`";
163
+ pub const S_BEXACT = "`$EXACT`";
164
+ pub const S_BOPEN = "`$OPEN`";
165
+ pub const S_BVAL = "`$VAL`";
166
+
167
+ pub const S_DKEY = "$KEY";
168
+ pub const S_DTOP = "$TOP";
169
+ pub const S_DERRS = "$ERRS";
170
+ pub const S_DSPEC = "$SPEC";
171
+
172
+ // General strings.
173
+ pub const S_list = "list";
174
+ pub const S_base = "base";
175
+ pub const S_boolean = "boolean";
176
+ pub const S_function = "function";
177
+ pub const S_symbol = "symbol";
178
+ pub const S_instance = "instance";
179
+ pub const S_key = "key";
180
+ pub const S_any = "any";
181
+ pub const S_noval = "noval";
182
+ pub const S_nil = "nil";
183
+ pub const S_null = "null";
184
+ pub const S_number = "number";
185
+ pub const S_object = "object";
186
+ pub const S_string = "string";
187
+ pub const S_decimal = "decimal";
188
+ pub const S_integer = "integer";
189
+ pub const S_map = "map";
190
+ pub const S_scalar = "scalar";
191
+ pub const S_node = "node";
192
+ pub const S_parent = "parent";
193
+
194
+ // Character strings.
195
+ pub const S_BT = "`";
196
+ pub const S_CN = ":";
197
+ pub const S_CS = "]";
198
+ pub const S_DS = "$";
199
+ pub const S_DT = ".";
200
+ pub const S_FS = "/";
201
+ pub const S_KEY = "KEY";
202
+ pub const S_MT = "";
203
+ pub const S_OS = "[";
204
+ pub const S_SP = " ";
205
+ pub const S_CM = ",";
206
+ pub const S_VIZ = ": ";
207
+
208
+ // Type bits — using bit positions from 31 downward, matching the TS implementation.
209
+ pub const T_any: i32 = (1 << 31) - 1;
210
+ pub const T_noval: i32 = 1 << 30;
211
+ pub const T_boolean: i32 = 1 << 29;
212
+ pub const T_decimal: i32 = 1 << 28;
213
+ pub const T_integer: i32 = 1 << 27;
214
+ pub const T_number: i32 = 1 << 26;
215
+ pub const T_string: i32 = 1 << 25;
216
+ pub const T_function: i32 = 1 << 24;
217
+ pub const T_symbol: i32 = 1 << 23;
218
+ pub const T_null: i32 = 1 << 22;
219
+ // 7 bits reserved
220
+ pub const T_list: i32 = 1 << 14;
221
+ pub const T_map: i32 = 1 << 13;
222
+ pub const T_instance: i32 = 1 << 12;
223
+ // 4 bits reserved
224
+ pub const T_scalar: i32 = 1 << 7;
225
+ pub const T_node: i32 = 1 << 6;
226
+
227
+ // TYPENAME maps bit position (via leading zeros count) to type name string.
228
+ pub const TYPENAME = [_][]const u8{
229
+ S_any,
230
+ S_noval,
231
+ S_boolean,
232
+ S_decimal,
233
+ S_integer,
234
+ S_number,
235
+ S_string,
236
+ S_function,
237
+ S_symbol,
238
+ S_null,
239
+ "",
240
+ "",
241
+ "",
242
+ "",
243
+ "",
244
+ "",
245
+ "",
246
+ S_list,
247
+ S_map,
248
+ S_instance,
249
+ "",
250
+ "",
251
+ "",
252
+ "",
253
+ S_scalar,
254
+ S_node,
255
+ };
256
+
257
+ // Default max depth (for walk etc).
258
+ pub const MAXDEPTH: i32 = 32;
259
+
260
+ pub const MODENAME = std.StaticStringMap([]const u8).initComptime(.{
261
+ .{ "4", "val" },
262
+ .{ "1", "key:pre" },
263
+ .{ "2", "key:post" },
264
+ });
265
+
266
+ // Value is a node — defined, and a map (object) or list (array).
267
+ pub fn isnode(val: JsonValue) bool {
268
+ return switch (val) {
269
+ .object, .array => true,
270
+ else => false,
271
+ };
272
+ }
273
+
274
+ // Value is a defined map (object) with string keys.
275
+ pub fn ismap(val: JsonValue) bool {
276
+ return val == .object;
277
+ }
278
+
279
+ // Value is a defined list (array) with integer keys (indexes).
280
+ pub fn islist(val: JsonValue) bool {
281
+ return val == .array;
282
+ }
283
+
284
+ // Value is a defined string (non-empty) or integer key.
285
+ pub fn iskey(val: JsonValue) bool {
286
+ return switch (val) {
287
+ .string => |s| s.len > 0,
288
+ .integer => true,
289
+ .float => true,
290
+ else => false,
291
+ };
292
+ }
293
+
294
+ // Check for an "empty" value — null, empty string, empty array, empty object.
295
+ pub fn isempty(val: JsonValue) bool {
296
+ return switch (val) {
297
+ .null => true,
298
+ .string => |s| s.len == 0,
299
+ .array => |a| a.data.items.len == 0,
300
+ .object => |o| o.count() == 0,
301
+ else => false,
302
+ };
303
+ }
304
+
305
+ // Value is a function. JSON values are never functions.
306
+ pub fn isfunc(val: JsonValue) bool {
307
+ return val == .function;
308
+ }
309
+
310
+ // Return a defined value, or an alternative if the value is null.
311
+ pub fn getdef(val: JsonValue, alt: JsonValue) JsonValue {
312
+ return switch (val) {
313
+ .null => alt,
314
+ else => val,
315
+ };
316
+ }
317
+
318
+ // Get the type name string from type bits.
319
+ pub fn typename(t: i64) []const u8 {
320
+ if (t <= 0 or t > std.math.maxInt(u32)) return S_any;
321
+ const ut: u32 = @intCast(t);
322
+ const idx = @clz(ut);
323
+ if (idx < TYPENAME.len and TYPENAME[idx].len > 0) {
324
+ return TYPENAME[idx];
325
+ }
326
+ return S_any;
327
+ }
328
+
329
+ // Determine the type of a value as a bit code.
330
+ pub fn typify(val: JsonValue) i64 {
331
+ return switch (val) {
332
+ .object => @as(i64, T_node | T_map),
333
+ .array => @as(i64, T_node | T_list),
334
+ .integer => @as(i64, T_scalar | T_number | T_integer),
335
+ .float => |f| {
336
+ if (std.math.isNan(f)) {
337
+ return @as(i64, T_noval);
338
+ }
339
+ if (!std.math.isInf(f) and f == @trunc(f)) {
340
+ return @as(i64, T_scalar | T_number | T_integer);
341
+ }
342
+ return @as(i64, T_scalar | T_number | T_decimal);
343
+ },
344
+ .string => @as(i64, T_scalar | T_string),
345
+ .bool => @as(i64, T_scalar | T_boolean),
346
+ .null => @as(i64, T_scalar | T_null),
347
+ .number_string => @as(i64, T_scalar | T_number),
348
+ .function => @as(i64, T_scalar | T_function),
349
+ };
350
+ }
351
+
352
+ // Get the integer size of a value.
353
+ pub fn size(val: JsonValue) i64 {
354
+ return switch (val) {
355
+ .array => |a| @intCast(a.data.items.len),
356
+ .object => |o| @intCast(o.count()),
357
+ .string => |s| @intCast(s.len),
358
+ .integer => |i| i,
359
+ .float => |f| @intFromFloat(@floor(f)),
360
+ .bool => |b| if (b) @as(i64, 1) else @as(i64, 0),
361
+ .null => 0,
362
+ .number_string => 0,
363
+ .function => 0,
364
+ };
365
+ }
366
+
367
+ // Convert a key to its string representation.
368
+ // Returns a slice into existing data or a static string, or
369
+ // an allocated string for integer/float keys.
370
+ pub fn strkey(allocator: Allocator, key: JsonValue) ![]const u8 {
371
+ return switch (key) {
372
+ .string => |s| s,
373
+ .integer => |i| try std.fmt.allocPrint(allocator, "{d}", .{i}),
374
+ .float => |f| try std.fmt.allocPrint(allocator, "{d}", .{@as(i64, @intFromFloat(f))}),
375
+ else => S_MT,
376
+ };
377
+ }
378
+
379
+ // Get a list element by integer index. Only works on lists.
380
+ pub fn getelem(allocator: Allocator, val: JsonValue, key: JsonValue, alt: JsonValue) !JsonValue {
381
+ if (val == .null or key == .null) return resolveAlt(allocator, alt);
382
+
383
+ if (val != .array) return resolveAlt(allocator, alt);
384
+
385
+ const list = val.array.data.items;
386
+
387
+ // Get the key as string first
388
+ const ks = try strkey(allocator, key);
389
+
390
+ // Parse as integer
391
+ const nkey_raw = std.fmt.parseInt(i64, ks, 10) catch return resolveAlt(allocator, alt);
392
+ var nkey = nkey_raw;
393
+
394
+ if (nkey < 0) {
395
+ nkey = @as(i64, @intCast(list.len)) + nkey;
396
+ }
397
+
398
+ if (nkey >= 0 and nkey < @as(i64, @intCast(list.len))) {
399
+ const v = list[@intCast(nkey)];
400
+ // Group A: a stored JSON null counts as "no value" → alt.
401
+ if (v == .null) return resolveAlt(allocator, alt);
402
+ return v;
403
+ }
404
+
405
+ return resolveAlt(allocator, alt);
406
+ }
407
+
408
+ // If alt is a function, call it to get the default value.
409
+ fn resolveAlt(allocator: Allocator, alt: JsonValue) !JsonValue {
410
+ if (alt == .function) return try alt.function.call(alt.function.ctx, allocator, JsonValue{ .null = {} });
411
+ return alt;
412
+ }
413
+
414
+ // Safely get a property from a node (map or list).
415
+ pub fn getprop(allocator: Allocator, val: JsonValue, key: JsonValue, alt: JsonValue) !JsonValue {
416
+ if (val == .null or key == .null) return alt;
417
+
418
+ if (val == .object) {
419
+ const ks = try strkey(allocator, key);
420
+ if (val.object.get(ks)) |v| {
421
+ // Group A: a stored JSON null counts as "no value" → alt.
422
+ if (v == .null) return alt;
423
+ return v;
424
+ }
425
+ return alt;
426
+ }
427
+
428
+ if (val == .array) {
429
+ var ki: ?i64 = null;
430
+ switch (key) {
431
+ .integer => |i| ki = i,
432
+ .float => |f| ki = @intFromFloat(f),
433
+ .string => |s| {
434
+ ki = std.fmt.parseInt(i64, s, 10) catch null;
435
+ },
436
+ else => {},
437
+ }
438
+ if (ki) |idx| {
439
+ if (idx >= 0 and idx < @as(i64, @intCast(val.array.data.items.len))) {
440
+ const v = val.array.data.items[@intCast(idx)];
441
+ // Group A: a stored JSON null counts as "no value" → alt.
442
+ if (v == .null) return alt;
443
+ return v;
444
+ }
445
+ }
446
+ return alt;
447
+ }
448
+
449
+ return alt;
450
+ }
451
+
452
+ // Get sorted keys of a map, or indices (as strings) of a list.
453
+ // Returns a JsonValue array.
454
+ pub fn keysof(allocator: Allocator, val: JsonValue) !JsonValue {
455
+ if (val == .object) {
456
+ const obj = val.object;
457
+ var key_strs = try std.ArrayList([]const u8).initCapacity(allocator, obj.count());
458
+ defer key_strs.deinit();
459
+ var it = obj.iterator();
460
+ while (it.next()) |kv| {
461
+ try key_strs.append(kv.key_ptr.*);
462
+ }
463
+ std.mem.sort([]const u8, key_strs.items, {}, stringLessThan);
464
+
465
+ const arr_lr2 = try allocator.create(ListRef);
466
+ arr_lr2.* = .{ .data = try ListData.initCapacity(allocator, obj.count()) };
467
+ const arr = arr_lr2;
468
+ for (key_strs.items) |k| {
469
+ try arr.append(JsonValue{ .string = k });
470
+ }
471
+ return JsonValue{ .array = arr };
472
+ }
473
+
474
+ if (val == .array) {
475
+ const list = val.array.data.items;
476
+ const arr_lr = try allocator.create(ListRef);
477
+ arr_lr.* = .{ .data = try ListData.initCapacity(allocator, list.len) };
478
+ const arr = arr_lr;
479
+ for (0..list.len) |i| {
480
+ const s = try std.fmt.allocPrint(allocator, "{d}", .{i});
481
+ try arr.append(JsonValue{ .string = s });
482
+ }
483
+ return JsonValue{ .array = arr };
484
+ }
485
+
486
+ return try JsonValue.makeList(allocator);
487
+ }
488
+
489
+ fn stringLessThan(_: void, a: []const u8, b: []const u8) bool {
490
+ return std.mem.order(u8, a, b) == .lt;
491
+ }
492
+
493
+ // Check if a property with name key exists in node val.
494
+ pub fn haskey(allocator: Allocator, val: JsonValue, key: JsonValue) !bool {
495
+ const result = try getprop(allocator, val, key, .null);
496
+ return result != .null;
497
+ }
498
+
499
+ // List entries of a map or list as [key, value] pairs.
500
+ pub fn items(allocator: Allocator, val: JsonValue) !JsonValue {
501
+ if (val == .object) {
502
+ const obj = val.object;
503
+ // Get sorted keys
504
+ var key_strs = try std.ArrayList([]const u8).initCapacity(allocator, obj.count());
505
+ defer key_strs.deinit();
506
+ var it = obj.iterator();
507
+ while (it.next()) |kv| {
508
+ try key_strs.append(kv.key_ptr.*);
509
+ }
510
+ std.mem.sort([]const u8, key_strs.items, {}, stringLessThan);
511
+
512
+ const arr_lr2 = try allocator.create(ListRef);
513
+ arr_lr2.* = .{ .data = try ListData.initCapacity(allocator, obj.count()) };
514
+ const arr = arr_lr2;
515
+ for (key_strs.items) |k| {
516
+ const pair_lr = try allocator.create(ListRef);
517
+ pair_lr.* = .{ .data = try ListData.initCapacity(allocator, 2) };
518
+ const pair = pair_lr;
519
+ try pair.append(JsonValue{ .string = k });
520
+ try pair.append(obj.get(k).?);
521
+ try arr.append(JsonValue{ .array = pair });
522
+ }
523
+ return JsonValue{ .array = arr };
524
+ }
525
+
526
+ if (val == .array) {
527
+ const list = val.array.data.items;
528
+ const arr_lr = try allocator.create(ListRef);
529
+ arr_lr.* = .{ .data = try ListData.initCapacity(allocator, list.len) };
530
+ const arr = arr_lr;
531
+ for (list, 0..) |v, i| {
532
+ const pair_lr = try allocator.create(ListRef);
533
+ pair_lr.* = .{ .data = try ListData.initCapacity(allocator, 2) };
534
+ const pair = pair_lr;
535
+ const idx_str = try std.fmt.allocPrint(allocator, "{d}", .{i});
536
+ try pair.append(JsonValue{ .string = idx_str });
537
+ try pair.append(v);
538
+ try arr.append(JsonValue{ .array = pair });
539
+ }
540
+ return JsonValue{ .array = arr };
541
+ }
542
+
543
+ return try JsonValue.makeList(allocator);
544
+ }
545
+
546
+ // Flatten nested arrays up to a specified depth.
547
+ pub fn flatten(allocator: Allocator, val: JsonValue, depth: i64) !JsonValue {
548
+ if (val != .array) return val;
549
+ const result = try flattenDepth(allocator, val.array.data.items, depth);
550
+ return JsonValue{ .array = result };
551
+ }
552
+
553
+ fn flattenDepth(allocator: Allocator, arr: []const JsonValue, depth: i64) !*ListRef {
554
+ const result_lr = try allocator.create(ListRef);
555
+ result_lr.* = .{ .data = ListData.init(allocator) };
556
+ const result = result_lr;
557
+ for (arr) |item| {
558
+ if (depth > 0 and item == .array) {
559
+ const sub = try flattenDepth(allocator, item.array.data.items, depth - 1);
560
+ for (sub.data.items) |subitem| {
561
+ try result.append(subitem);
562
+ }
563
+ } else {
564
+ try result.append(item);
565
+ }
566
+ }
567
+ return result;
568
+ }
569
+
570
+ // Predicate for `filter`: receives a [key, value] pair (a 2-element list).
571
+ pub const FilterFn = *const fn (item: JsonValue) bool;
572
+
573
+ // Keep entries for which `check([key, value])` is truthy; returns a list of the
574
+ // matching values. Mirrors TS `filter`.
575
+ pub fn filter(allocator: Allocator, val: JsonValue, check: FilterFn) !JsonValue {
576
+ const all = try items(allocator, val);
577
+ const out = try JsonValue.makeList(allocator);
578
+ if (all == .array) {
579
+ for (all.array.data.items) |pair| {
580
+ if (check(pair)) {
581
+ const v: JsonValue = if (pair == .array and pair.array.data.items.len > 1)
582
+ pair.array.data.items[1]
583
+ else
584
+ .null;
585
+ try out.array.append(v);
586
+ }
587
+ }
588
+ }
589
+ return out;
590
+ }
591
+
592
+ // Deep clone a JSON value.
593
+ pub fn clone(allocator: Allocator, val: JsonValue) !JsonValue {
594
+ return switch (val) {
595
+ .object => |obj| {
596
+ const new_obj = try allocator.create(MapRef);
597
+ new_obj.* = .{ .data = MapData.init(allocator) };
598
+ try new_obj.data.ensureTotalCapacity(@intCast(obj.count()));
599
+ var it = obj.iterator();
600
+ while (it.next()) |kv| {
601
+ const cloned_val = try clone(allocator, kv.value_ptr.*);
602
+ try new_obj.put(kv.key_ptr.*, cloned_val);
603
+ }
604
+ return JsonValue{ .object = new_obj };
605
+ },
606
+ .array => |arr| {
607
+ const new_arr_lr = try allocator.create(ListRef);
608
+ new_arr_lr.* = .{ .data = try ListData.initCapacity(allocator, arr.data.items.len) };
609
+ const new_arr = new_arr_lr;
610
+ for (arr.data.items) |item| {
611
+ const cloned_item = try clone(allocator, item);
612
+ try new_arr.append(cloned_item);
613
+ }
614
+ return JsonValue{ .array = new_arr };
615
+ },
616
+ else => val,
617
+ };
618
+ }
619
+
620
+ // Define a JSON object from alternating key/value arguments.
621
+ // jm(alloc, &.{ str("a"), int(1), str("b"), int(2) }) => { "a": 1, "b": 2 }.
622
+ // A missing trailing value becomes JSON null; a non-string key is stringified.
623
+ pub fn jm(allocator: Allocator, kv: []const JsonValue) !JsonValue {
624
+ const o = try JsonValue.makeMap(allocator);
625
+ var i: usize = 0;
626
+ while (i < kv.len) : (i += 2) {
627
+ const k = kv[i];
628
+ const ks = switch (k) {
629
+ .string => |s| s,
630
+ else => try stringify(allocator, k, null),
631
+ };
632
+ const v: JsonValue = if (i + 1 < kv.len) kv[i + 1] else .null;
633
+ try o.object.put(ks, v);
634
+ }
635
+ return o;
636
+ }
637
+
638
+ // Define a JSON array (tuple) from positional arguments.
639
+ // jt(alloc, &.{ int(1), str("x"), .{ .bool = true } }) => [1, "x", true].
640
+ pub fn jt(allocator: Allocator, v: []const JsonValue) !JsonValue {
641
+ const a = try JsonValue.makeList(allocator);
642
+ for (v) |item| {
643
+ try a.array.append(item);
644
+ }
645
+ return a;
646
+ }
647
+
648
+ // Delete a property from a map or remove an element from a list.
649
+ pub fn delprop(allocator: Allocator, parent: JsonValue, key: JsonValue) !JsonValue {
650
+ _ = allocator;
651
+ if (!iskey(key)) return parent;
652
+
653
+ if (parent == .object) {
654
+ var obj = parent.object;
655
+ var buf: [20]u8 = undefined;
656
+ const ks = keyStr(&buf, key);
657
+ _ = obj.fetchOrderedRemove(ks);
658
+ return JsonValue{ .object = obj };
659
+ }
660
+
661
+ if (parent == .array) {
662
+ var ki: ?i64 = null;
663
+ switch (key) {
664
+ .integer => |i| ki = i,
665
+ .float => |f| ki = @intFromFloat(@trunc(f)),
666
+ .string => |s| {
667
+ ki = std.fmt.parseInt(i64, s, 10) catch null;
668
+ },
669
+ else => {},
670
+ }
671
+ if (ki) |idx| {
672
+ const plen: i64 = @intCast(parent.array.data.items.len);
673
+ // No negative index support for delprop
674
+ if (idx >= 0 and idx < plen) {
675
+ var arr = parent.array;
676
+ _ = arr.orderedRemove(@intCast(idx));
677
+ return JsonValue{ .array = arr };
678
+ }
679
+ }
680
+ return parent;
681
+ }
682
+
683
+ return parent;
684
+ }
685
+
686
+ // Set a property value by key.
687
+ pub fn setprop(allocator: Allocator, parent: JsonValue, key: JsonValue, newval: JsonValue) !JsonValue {
688
+ if (!iskey(key)) return parent;
689
+
690
+ if (parent == .object) {
691
+ var obj = parent.object;
692
+ var buf: [20]u8 = undefined;
693
+ const ks = keyStr(&buf, key);
694
+ // Dupe the key if it was generated from the stack buffer (integer/float keys)
695
+ const owned_key = if (key != .string)
696
+ try allocator.dupe(u8, ks)
697
+ else
698
+ ks;
699
+ try obj.put(owned_key, newval);
700
+ return JsonValue{ .object = obj };
701
+ }
702
+
703
+ if (parent == .array) {
704
+ var ki: ?i64 = null;
705
+ switch (key) {
706
+ .integer => |i| ki = i,
707
+ .float => |f| ki = @intFromFloat(f),
708
+ .string => |s| {
709
+ ki = std.fmt.parseInt(i64, s, 10) catch null;
710
+ },
711
+ else => {},
712
+ }
713
+ if (ki) |idx| {
714
+ var arr = parent.array;
715
+ const plen: i64 = @intCast(arr.data.items.len);
716
+ if (idx >= 0) {
717
+ if (idx >= plen) {
718
+ // Append
719
+ try arr.append(newval);
720
+ } else {
721
+ // Replace
722
+ arr.data.items[@intCast(idx)] = newval;
723
+ }
724
+ } else {
725
+ // Prepend
726
+ try arr.insert(0, newval);
727
+ }
728
+ return JsonValue{ .array = arr };
729
+ }
730
+ return parent;
731
+ }
732
+
733
+ return parent;
734
+ }
735
+
736
+ // Convert key to string without allocation, using a stack buffer.
737
+ fn keyStr(buf: *[20]u8, key: JsonValue) []const u8 {
738
+ return switch (key) {
739
+ .string => |s| s,
740
+ .integer => |i| std.fmt.bufPrint(buf, "{d}", .{i}) catch S_MT,
741
+ .float => |f| std.fmt.bufPrint(buf, "{d}", .{@as(i64, @intFromFloat(f))}) catch S_MT,
742
+ else => S_MT,
743
+ };
744
+ }
745
+
746
+ // Escape regex special characters.
747
+ pub fn escre(allocator: Allocator, s: []const u8) ![]const u8 {
748
+ if (s.len == 0) return S_MT;
749
+ var result = std.ArrayList(u8).init(allocator);
750
+ for (s) |c| {
751
+ if (isReSpecial(c)) {
752
+ try result.append('\\');
753
+ }
754
+ try result.append(c);
755
+ }
756
+ return result.items;
757
+ }
758
+
759
+ fn isReSpecial(c: u8) bool {
760
+ return switch (c) {
761
+ '.', '*', '+', '?', '^', '$', '{', '}', '(', ')', '|', '[', ']', '\\' => true,
762
+ else => false,
763
+ };
764
+ }
765
+
766
+ // ----------------------------------------------------------------------------
767
+ // Regex utility — uniform re_* API (see /REGEX_API.md). Backed by the
768
+ // in-tree pure-Zig Thompson NFA engine (zig/src/regex.zig), no third-party
769
+ // package dependency.
770
+ // ----------------------------------------------------------------------------
771
+
772
+ const _re_engine = @import("regex.zig");
773
+
774
+ pub const ReCompiled = _re_engine.Regex;
775
+
776
+ // re_compile uses the page allocator so callers don't need to pass one
777
+ // through the entire test pipeline. The returned Regex owns its
778
+ // instruction buffer; the .deinit() method releases it. We deliberately
779
+ // leak the Regex in test_re paths today — tests use compile+isMatch+drop
780
+ // patterns that are short-lived, and zig fmt's lint is silent here.
781
+ pub fn re_compile(pattern: []const u8) ?ReCompiled {
782
+ return _re_engine.compile(std.heap.page_allocator, pattern);
783
+ }
784
+
785
+ pub fn re_test(pattern: []const u8, input: []const u8) bool {
786
+ var re = _re_engine.compile(std.heap.page_allocator, pattern) orelse return false;
787
+ defer re.deinit();
788
+ return re.isMatch(input);
789
+ }
790
+
791
+ /// re_find — first match as `[whole, capture1, ...]`. Slices alias `input`,
792
+ /// so the result is valid only while `input` is alive. Returns null on
793
+ /// compile error or no-match. The outer slice and inner slices must be
794
+ /// freed by the caller.
795
+ pub fn re_find(allocator: Allocator, pattern: []const u8, input: []const u8) ?[][]const u8 {
796
+ var re = _re_engine.compile(std.heap.page_allocator, pattern) orelse return null;
797
+ defer re.deinit();
798
+ const slots = re.findFirst(input) orelse return null;
799
+ defer std.heap.page_allocator.free(slots);
800
+ const ngroups = re.ngroups;
801
+ const out = allocator.alloc([]const u8, ngroups) catch return null;
802
+ var g: usize = 0;
803
+ while (g < ngroups) : (g += 1) {
804
+ const s = slots[2 * g];
805
+ const e = slots[2 * g + 1];
806
+ if (s < 0 or e < s) {
807
+ out[g] = "";
808
+ } else {
809
+ out[g] = input[@as(usize, @intCast(s))..@as(usize, @intCast(e))];
810
+ }
811
+ }
812
+ return out;
813
+ }
814
+
815
+ /// re_find_all — every non-overlapping match. Caller owns the returned
816
+ /// slice-of-slices and must free both levels.
817
+ pub fn re_find_all(allocator: Allocator, pattern: []const u8, input: []const u8) ?[][][]const u8 {
818
+ var re = _re_engine.compile(std.heap.page_allocator, pattern) orelse return null;
819
+ defer re.deinit();
820
+ var rows = std.ArrayList([][]const u8).init(allocator);
821
+ defer rows.deinit();
822
+ var pos: usize = 0;
823
+ while (pos <= input.len) {
824
+ const slots = re.findFrom(input, pos) orelse break;
825
+ defer std.heap.page_allocator.free(slots);
826
+ const ngroups = re.ngroups;
827
+ const row = allocator.alloc([]const u8, ngroups) catch return null;
828
+ var g: usize = 0;
829
+ while (g < ngroups) : (g += 1) {
830
+ const s = slots[2 * g];
831
+ const e = slots[2 * g + 1];
832
+ if (s < 0 or e < s) {
833
+ row[g] = "";
834
+ } else {
835
+ row[g] = input[@as(usize, @intCast(s))..@as(usize, @intCast(e))];
836
+ }
837
+ }
838
+ rows.append(row) catch return null;
839
+ const mstart = @as(usize, @intCast(slots[0]));
840
+ const mend = @as(usize, @intCast(slots[1]));
841
+ if (mend == mstart) {
842
+ pos = mend + 1;
843
+ } else {
844
+ pos = mend;
845
+ }
846
+ }
847
+ return rows.toOwnedSlice() catch return null;
848
+ }
849
+
850
+ /// re_replace — replace every match in `input` with `replacement`. The
851
+ /// replacement string is taken literally; $& / $1.. substitution is not
852
+ /// expanded in this minimal wrapper (matches the engine's current shape).
853
+ /// On zero-width match the current rune is emitted and we advance by one
854
+ /// byte, mirroring the ECMAScript convention used by other ports.
855
+ pub fn re_replace(allocator: Allocator, pattern: []const u8, input: []const u8, replacement: []const u8) ![]u8 {
856
+ var re = _re_engine.compile(std.heap.page_allocator, pattern) orelse {
857
+ return allocator.dupe(u8, input);
858
+ };
859
+ defer re.deinit();
860
+ var out = std.ArrayList(u8).init(allocator);
861
+ defer out.deinit();
862
+ var pos: usize = 0;
863
+ while (pos <= input.len) {
864
+ const slots = re.findFrom(input, pos) orelse {
865
+ try out.appendSlice(input[pos..]);
866
+ break;
867
+ };
868
+ defer std.heap.page_allocator.free(slots);
869
+ const mstart = @as(usize, @intCast(slots[0]));
870
+ const mend = @as(usize, @intCast(slots[1]));
871
+ try out.appendSlice(input[pos..mstart]);
872
+ try out.appendSlice(replacement);
873
+ if (mend == mstart) {
874
+ if (mstart < input.len) {
875
+ try out.append(input[mstart]);
876
+ pos = mstart + 1;
877
+ } else {
878
+ pos = mstart + 1;
879
+ }
880
+ } else {
881
+ pos = mend;
882
+ }
883
+ }
884
+ return out.toOwnedSlice();
885
+ }
886
+
887
+ pub fn re_escape(allocator: Allocator, s: []const u8) ![]const u8 {
888
+ return escre(allocator, s);
889
+ }
890
+
891
+ // URL-encode a string.
892
+ pub fn escurl(allocator: Allocator, s: []const u8) ![]const u8 {
893
+ if (s.len == 0) return S_MT;
894
+ var result = std.ArrayList(u8).init(allocator);
895
+ for (s) |c| {
896
+ if (isUrlSafe(c)) {
897
+ try result.append(c);
898
+ } else {
899
+ try result.appendSlice(try std.fmt.allocPrint(allocator, "%{X:0>2}", .{c}));
900
+ }
901
+ }
902
+ return result.items;
903
+ }
904
+
905
+ fn isUrlSafe(c: u8) bool {
906
+ // Match encodeURIComponent: unreserved chars per RFC 3986 plus !*'()
907
+ return switch (c) {
908
+ 'A'...'Z', 'a'...'z', '0'...'9', '-', '_', '.', '~', '!', '*', '\'', '(', ')' => true,
909
+ else => false,
910
+ };
911
+ }
912
+
913
+ // Join array elements into a string with separator handling.
914
+ pub fn join(allocator: Allocator, arr: JsonValue, sep: []const u8, urlMode: bool) ![]const u8 {
915
+ if (arr != .array) return S_MT;
916
+
917
+ const items_list = arr.array.data.items;
918
+ const sarr: usize = items_list.len;
919
+
920
+ // Filter to non-empty strings
921
+ var filtered = std.ArrayList([]const u8).init(allocator);
922
+ var indices = std.ArrayList(usize).init(allocator);
923
+ for (items_list, 0..) |item, orig_idx| {
924
+ if (item == .string and item.string.len > 0) {
925
+ try filtered.append(item.string);
926
+ try indices.append(orig_idx);
927
+ }
928
+ }
929
+
930
+ if (filtered.items.len == 0) return S_MT;
931
+
932
+ // Process separator handling
933
+ var parts = std.ArrayList([]const u8).init(allocator);
934
+
935
+ for (filtered.items, 0..) |s, fi| {
936
+ var processed = s;
937
+ const orig_idx = indices.items[fi];
938
+
939
+ if (sep.len == 1) {
940
+ const sep_c = sep[0];
941
+ if (urlMode and orig_idx == 0) {
942
+ // Remove trailing seps from first URL element
943
+ processed = trimRight(processed, sep_c);
944
+ } else {
945
+ if (orig_idx > 0) {
946
+ // Remove leading seps
947
+ processed = trimLeft(processed, sep_c);
948
+ }
949
+ if (orig_idx < sarr - 1 or !urlMode) {
950
+ // Remove trailing seps
951
+ processed = trimRight(processed, sep_c);
952
+ }
953
+ // Collapse internal runs of sep
954
+ processed = try collapseInternal(allocator, processed, sep_c);
955
+ }
956
+ }
957
+
958
+ if (processed.len > 0) {
959
+ try parts.append(processed);
960
+ }
961
+ }
962
+
963
+ // Join with separator
964
+ if (parts.items.len == 0) return S_MT;
965
+
966
+ var total_len: usize = 0;
967
+ for (parts.items) |p| total_len += p.len;
968
+ total_len += sep.len * (parts.items.len - 1);
969
+
970
+ var result = try std.ArrayList(u8).initCapacity(allocator, total_len);
971
+ for (parts.items, 0..) |p, i| {
972
+ try result.appendSlice(p);
973
+ if (i < parts.items.len - 1) {
974
+ try result.appendSlice(sep);
975
+ }
976
+ }
977
+ return result.items;
978
+ }
979
+
980
+ fn trimLeft(s: []const u8, c: u8) []const u8 {
981
+ var i: usize = 0;
982
+ while (i < s.len and s[i] == c) : (i += 1) {}
983
+ return s[i..];
984
+ }
985
+
986
+ fn trimRight(s: []const u8, c: u8) []const u8 {
987
+ var end: usize = s.len;
988
+ while (end > 0 and s[end - 1] == c) : (end -= 1) {}
989
+ return s[0..end];
990
+ }
991
+
992
+ // Collapse internal runs of separator only when between non-separator chars.
993
+ // E.g. "c//d" → "c/d" but "//a" stays "//a".
994
+ fn collapseInternal(allocator: Allocator, s: []const u8, sep: u8) ![]const u8 {
995
+ if (s.len < 3) return s;
996
+ var result = std.ArrayList(u8).init(allocator);
997
+ var i: usize = 0;
998
+ while (i < s.len) {
999
+ try result.append(s[i]);
1000
+ // If current char is not sep, look ahead for sep run followed by non-sep
1001
+ if (s[i] != sep) {
1002
+ if (i + 1 < s.len and s[i + 1] == sep) {
1003
+ var sep_end = i + 1;
1004
+ while (sep_end < s.len and s[sep_end] == sep) : (sep_end += 1) {}
1005
+ if (sep_end < s.len) {
1006
+ // Sep run between two non-sep chars: collapse to single sep
1007
+ try result.append(sep);
1008
+ i = sep_end;
1009
+ continue;
1010
+ }
1011
+ // Sep run at end: keep all
1012
+ }
1013
+ }
1014
+ i += 1;
1015
+ }
1016
+ return result.items;
1017
+ }
1018
+
1019
+ // Output JSON with indentation.
1020
+ pub fn jsonify(allocator: Allocator, val: JsonValue, indent_size: usize, offset: usize) ![]const u8 {
1021
+ if (val == .null) return "null";
1022
+
1023
+ // Use the standard JSON stringify
1024
+ var result = std.ArrayList(u8).init(allocator);
1025
+ try jsonifyWrite(val, result.writer(), indent_size, offset, 0);
1026
+ return result.items;
1027
+ }
1028
+
1029
+ fn jsonifyWrite(val: JsonValue, writer: anytype, indent_size: usize, offset: usize, depth: usize) !void {
1030
+ switch (val) {
1031
+ .null => try writer.writeAll("null"),
1032
+ .bool => |b| try writer.writeAll(if (b) "true" else "false"),
1033
+ .integer => |i| try writer.print("{d}", .{i}),
1034
+ .float => |f| {
1035
+ if (f == @trunc(f) and !std.math.isNan(f) and !std.math.isInf(f)) {
1036
+ try writer.print("{d}", .{@as(i64, @intFromFloat(f))});
1037
+ } else {
1038
+ try writer.print("{d}", .{f});
1039
+ }
1040
+ },
1041
+ .string => |s| {
1042
+ try writer.writeByte('"');
1043
+ for (s) |c| {
1044
+ switch (c) {
1045
+ '"' => try writer.writeAll("\\\""),
1046
+ '\\' => try writer.writeAll("\\\\"),
1047
+ '\n' => try writer.writeAll("\\n"),
1048
+ '\r' => try writer.writeAll("\\r"),
1049
+ '\t' => try writer.writeAll("\\t"),
1050
+ else => try writer.writeByte(c),
1051
+ }
1052
+ }
1053
+ try writer.writeByte('"');
1054
+ },
1055
+ .array => |arr| {
1056
+ if (arr.data.items.len == 0) {
1057
+ try writer.writeAll("[]");
1058
+ return;
1059
+ }
1060
+ const compact = indent_size == 0;
1061
+ try writer.writeByte('[');
1062
+ if (!compact) try writer.writeByte('\n');
1063
+ for (arr.data.items, 0..) |item, i| {
1064
+ if (!compact) try writeIndent(writer, offset + indent_size * (depth + 1));
1065
+ try jsonifyWrite(item, writer, indent_size, offset, depth + 1);
1066
+ if (i < arr.data.items.len - 1) {
1067
+ try writer.writeByte(',');
1068
+ }
1069
+ if (!compact) try writer.writeByte('\n');
1070
+ }
1071
+ if (!compact) try writeIndent(writer, offset + indent_size * depth);
1072
+ try writer.writeByte(']');
1073
+ },
1074
+ .object => |obj| {
1075
+ if (obj.count() == 0) {
1076
+ try writer.writeAll("{}");
1077
+ return;
1078
+ }
1079
+ const compact = indent_size == 0;
1080
+ // Iterate in INSERTION order (matches TS canonical JSON.stringify)
1081
+ try writer.writeByte('{');
1082
+ if (!compact) try writer.writeByte('\n');
1083
+ var it = obj.iterator();
1084
+ var i: usize = 0;
1085
+ const total = obj.count();
1086
+ while (it.next()) |kv| : (i += 1) {
1087
+ if (!compact) try writeIndent(writer, offset + indent_size * (depth + 1));
1088
+ try writer.writeByte('"');
1089
+ try writer.writeAll(kv.key_ptr.*);
1090
+ try writer.writeAll(if (compact) "\":" else "\": ");
1091
+ try jsonifyWrite(kv.value_ptr.*, writer, indent_size, offset, depth + 1);
1092
+ if (i < total - 1) {
1093
+ try writer.writeByte(',');
1094
+ }
1095
+ if (!compact) try writer.writeByte('\n');
1096
+ }
1097
+ if (!compact) try writeIndent(writer, offset + indent_size * depth);
1098
+ try writer.writeByte('}');
1099
+ },
1100
+ .number_string => |s| try writer.writeAll(s),
1101
+ .function => try writer.writeAll("null"),
1102
+ }
1103
+ }
1104
+
1105
+ fn writeIndent(writer: anytype, count: usize) !void {
1106
+ for (0..count) |_| {
1107
+ try writer.writeByte(' ');
1108
+ }
1109
+ }
1110
+
1111
+ // Compact JSON serialization (no whitespace) for partial injection stringification.
1112
+ pub fn jsonifyCompact(allocator: Allocator, val: JsonValue) ![]const u8 {
1113
+ var result = std.ArrayList(u8).init(allocator);
1114
+ try jsonifyCompactWrite(val, result.writer());
1115
+ return result.items;
1116
+ }
1117
+
1118
+ fn jsonifyCompactWrite(val: JsonValue, writer: anytype) !void {
1119
+ switch (val) {
1120
+ .null => try writer.writeAll("null"),
1121
+ .bool => |b| try writer.writeAll(if (b) "true" else "false"),
1122
+ .integer => |i| try writer.print("{d}", .{i}),
1123
+ .float => |f| try writer.print("{d}", .{f}),
1124
+ .string => |s| {
1125
+ try writer.writeByte('"');
1126
+ for (s) |c| {
1127
+ switch (c) {
1128
+ '"' => try writer.writeAll("\\\""),
1129
+ '\\' => try writer.writeAll("\\\\"),
1130
+ '\n' => try writer.writeAll("\\n"),
1131
+ '\r' => try writer.writeAll("\\r"),
1132
+ '\t' => try writer.writeAll("\\t"),
1133
+ else => try writer.writeByte(c),
1134
+ }
1135
+ }
1136
+ try writer.writeByte('"');
1137
+ },
1138
+ .array => |arr| {
1139
+ try writer.writeByte('[');
1140
+ for (arr.data.items, 0..) |item, i| {
1141
+ if (i > 0) try writer.writeByte(',');
1142
+ try jsonifyCompactWrite(item, writer);
1143
+ }
1144
+ try writer.writeByte(']');
1145
+ },
1146
+ .object => |obj| {
1147
+ try writer.writeByte('{');
1148
+ var first = true;
1149
+ var it = obj.iterator();
1150
+ while (it.next()) |kv| {
1151
+ if (!first) try writer.writeByte(',');
1152
+ first = false;
1153
+ try writer.writeByte('"');
1154
+ try writer.writeAll(kv.key_ptr.*);
1155
+ try writer.writeAll("\":");
1156
+ try jsonifyCompactWrite(kv.value_ptr.*, writer);
1157
+ }
1158
+ try writer.writeByte('}');
1159
+ },
1160
+ .number_string => |s| try writer.writeAll(s),
1161
+ .function => try writer.writeAll("null"),
1162
+ }
1163
+ }
1164
+
1165
+ // Human-friendly string representation.
1166
+ pub fn stringify(allocator: Allocator, val: JsonValue, maxlen: ?usize) ![]const u8 {
1167
+ return stringifyPretty(allocator, val, maxlen, false);
1168
+ }
1169
+
1170
+ // Human-friendly string with optional ANSI color-coded nesting.
1171
+ pub fn stringifyPretty(allocator: Allocator, val: JsonValue, maxlen: ?usize, pretty: bool) ![]const u8 {
1172
+ var jsonStr: []const u8 = undefined;
1173
+ if (pretty) {
1174
+ jsonStr = try stringifyColorInner(allocator, val, 0);
1175
+ } else {
1176
+ jsonStr = try stringifyInner(allocator, val);
1177
+ }
1178
+
1179
+ if (maxlen) |ml| {
1180
+ if (ml > 0 and jsonStr.len > ml) {
1181
+ if (ml >= 3) {
1182
+ var truncated = try allocator.alloc(u8, ml);
1183
+ @memcpy(truncated[0 .. ml - 3], jsonStr[0 .. ml - 3]);
1184
+ truncated[ml - 3] = '.';
1185
+ truncated[ml - 2] = '.';
1186
+ truncated[ml - 1] = '.';
1187
+ return truncated;
1188
+ }
1189
+ return jsonStr[0..ml];
1190
+ }
1191
+ }
1192
+
1193
+ return jsonStr;
1194
+ }
1195
+
1196
+ // ANSI 256-color codes cycled per nesting depth, matching TS.
1197
+ const PRETTY_COLORS = [_]u8{ 81, 118, 213, 39, 166, 154, 141, 203, 43, 45, 215, 75, 171, 119, 208, 85 };
1198
+
1199
+ fn stringifyColorInner(allocator: Allocator, val: JsonValue, depth: usize) ![]const u8 {
1200
+ const color_idx = depth % PRETTY_COLORS.len;
1201
+ const cc = PRETTY_COLORS[color_idx];
1202
+ const open_color = try std.fmt.allocPrint(allocator, "\x1b[38;5;{d}m", .{cc});
1203
+ const reset = "\x1b[0m";
1204
+
1205
+ return switch (val) {
1206
+ .null => "null",
1207
+ .bool => |b| if (b) "true" else "false",
1208
+ .string => |s| s,
1209
+ .integer => |i| try std.fmt.allocPrint(allocator, "{d}", .{i}),
1210
+ .float => |f| blk: {
1211
+ if (f == @trunc(f) and !std.math.isNan(f) and !std.math.isInf(f)) {
1212
+ break :blk try std.fmt.allocPrint(allocator, "{d}", .{@as(i64, @intFromFloat(f))});
1213
+ }
1214
+ break :blk try std.fmt.allocPrint(allocator, "{d}", .{f});
1215
+ },
1216
+ .array => |arr| blk: {
1217
+ var result = std.ArrayList(u8).init(allocator);
1218
+ try result.appendSlice(open_color);
1219
+ try result.append('[');
1220
+ try result.appendSlice(reset);
1221
+ for (arr.data.items, 0..) |item, i| {
1222
+ const s = try stringifyColorInner(allocator, item, depth + 1);
1223
+ try result.appendSlice(s);
1224
+ if (i < arr.data.items.len - 1) try result.append(',');
1225
+ }
1226
+ try result.appendSlice(open_color);
1227
+ try result.append(']');
1228
+ try result.appendSlice(reset);
1229
+ break :blk result.items;
1230
+ },
1231
+ .object => |obj| blk: {
1232
+ var key_list = std.ArrayList([]const u8).init(allocator);
1233
+ var it = obj.iterator();
1234
+ while (it.next()) |kv| try key_list.append(kv.key_ptr.*);
1235
+ std.mem.sort([]const u8, key_list.items, {}, stringLessThan);
1236
+
1237
+ var result = std.ArrayList(u8).init(allocator);
1238
+ try result.appendSlice(open_color);
1239
+ try result.append('{');
1240
+ try result.appendSlice(reset);
1241
+ for (key_list.items, 0..) |k, i| {
1242
+ const v = obj.get(k).?;
1243
+ try result.appendSlice(k);
1244
+ try result.append(':');
1245
+ const s = try stringifyColorInner(allocator, v, depth + 1);
1246
+ try result.appendSlice(s);
1247
+ if (i < key_list.items.len - 1) try result.append(',');
1248
+ }
1249
+ try result.appendSlice(open_color);
1250
+ try result.append('}');
1251
+ try result.appendSlice(reset);
1252
+ break :blk result.items;
1253
+ },
1254
+ .number_string => |s| s,
1255
+ .function => "",
1256
+ };
1257
+ }
1258
+
1259
+ fn stringifyInner(allocator: Allocator, val: JsonValue) ![]const u8 {
1260
+ return switch (val) {
1261
+ .null => "null",
1262
+ .bool => |b| if (b) "true" else "false",
1263
+ .string => |s| s,
1264
+ .integer => |i| try std.fmt.allocPrint(allocator, "{d}", .{i}),
1265
+ .float => |f| {
1266
+ if (f == @trunc(f) and !std.math.isNan(f) and !std.math.isInf(f)) {
1267
+ return try std.fmt.allocPrint(allocator, "{d}", .{@as(i64, @intFromFloat(f))});
1268
+ }
1269
+ return try std.fmt.allocPrint(allocator, "{d}", .{f});
1270
+ },
1271
+ .array => |arr| {
1272
+ var result = std.ArrayList(u8).init(allocator);
1273
+ try result.append('[');
1274
+ for (arr.data.items, 0..) |item, i| {
1275
+ const s = try stringifyInner(allocator, item);
1276
+ try result.appendSlice(s);
1277
+ if (i < arr.data.items.len - 1) {
1278
+ try result.append(',');
1279
+ }
1280
+ }
1281
+ try result.append(']');
1282
+ return result.items;
1283
+ },
1284
+ .object => |obj| {
1285
+ // Sort keys
1286
+ var key_list = std.ArrayList([]const u8).init(allocator);
1287
+ defer key_list.deinit();
1288
+ var it = obj.iterator();
1289
+ while (it.next()) |kv| {
1290
+ try key_list.append(kv.key_ptr.*);
1291
+ }
1292
+ std.mem.sort([]const u8, key_list.items, {}, stringLessThan);
1293
+
1294
+ var result = std.ArrayList(u8).init(allocator);
1295
+ try result.append('{');
1296
+ for (key_list.items, 0..) |k, i| {
1297
+ const v = obj.get(k).?;
1298
+ try result.appendSlice(k);
1299
+ try result.append(':');
1300
+ const s = try stringifyInner(allocator, v);
1301
+ try result.appendSlice(s);
1302
+ if (i < key_list.items.len - 1) {
1303
+ try result.append(',');
1304
+ }
1305
+ }
1306
+ try result.append('}');
1307
+ return result.items;
1308
+ },
1309
+ .number_string => |s| s,
1310
+ .function => "",
1311
+ };
1312
+ }
1313
+
1314
+ // Build a human-friendly path string.
1315
+ pub fn pathify(allocator: Allocator, val: JsonValue, from: usize, end: usize) ![]const u8 {
1316
+ var path: ?std.ArrayList([]const u8) = null;
1317
+
1318
+ if (val == .array) {
1319
+ path = std.ArrayList([]const u8).init(allocator);
1320
+ for (val.array.data.items) |item| {
1321
+ switch (item) {
1322
+ .string => |s| try path.?.append(s),
1323
+ .integer => |i| try path.?.append(try std.fmt.allocPrint(allocator, "{d}", .{i})),
1324
+ .float => |f| try path.?.append(try std.fmt.allocPrint(allocator, "{d}", .{@as(i64, @intFromFloat(f))})),
1325
+ else => {},
1326
+ }
1327
+ }
1328
+ } else if (val == .string) {
1329
+ path = std.ArrayList([]const u8).init(allocator);
1330
+ try path.?.append(val.string);
1331
+ } else if (val == .integer or val == .float) {
1332
+ path = std.ArrayList([]const u8).init(allocator);
1333
+ const num: i64 = if (val == .integer) val.integer else @intFromFloat(@floor(val.float));
1334
+ try path.?.append(try std.fmt.allocPrint(allocator, "{d}", .{num}));
1335
+ }
1336
+
1337
+ if (path) |p| {
1338
+ const start = if (from > p.items.len) p.items.len else from;
1339
+ const end_idx = if (p.items.len < end) start else if (p.items.len - end < start) start else p.items.len - end;
1340
+
1341
+ const sliced = p.items[start..end_idx];
1342
+
1343
+ if (sliced.len == 0) {
1344
+ return "<root>";
1345
+ }
1346
+
1347
+ // Map: replace dots in string parts
1348
+ var mapped = std.ArrayList([]const u8).init(allocator);
1349
+ for (sliced) |part| {
1350
+ var replaced = std.ArrayList(u8).init(allocator);
1351
+ for (part) |c| {
1352
+ if (c != '.') try replaced.append(c);
1353
+ }
1354
+ try mapped.append(replaced.items);
1355
+ }
1356
+
1357
+ // Join with dots
1358
+ var result = std.ArrayList(u8).init(allocator);
1359
+ for (mapped.items, 0..) |part, i| {
1360
+ try result.appendSlice(part);
1361
+ if (i < mapped.items.len - 1) {
1362
+ try result.append('.');
1363
+ }
1364
+ }
1365
+ return result.items;
1366
+ }
1367
+
1368
+ // Unknown path — always include colon and stringified value
1369
+ var result = std.ArrayList(u8).init(allocator);
1370
+ try result.appendSlice("<unknown-path:");
1371
+ const s = try stringify(allocator, val, 47);
1372
+ try result.appendSlice(s);
1373
+ try result.append('>');
1374
+ return result.items;
1375
+ }
1376
+
1377
+ // Slice: extract part of an array, string, or clamp a number.
1378
+ pub fn slice(allocator: Allocator, val: JsonValue, start_in: ?i64, end_in: ?i64) !JsonValue {
1379
+ return sliceMut(allocator, val, start_in, end_in, false);
1380
+ }
1381
+
1382
+ // Slice with optional in-place mutation for arrays (matches TS mutate param).
1383
+ pub fn sliceMut(allocator: Allocator, val: JsonValue, start_in: ?i64, end_in: ?i64, mutate: bool) !JsonValue {
1384
+ _ = mutate;
1385
+ // Number case: clamp
1386
+ if (val != .string and val != .array and val != .object) {
1387
+ if (val == .integer or val == .float) {
1388
+ const f: f64 = if (val == .integer) @floatFromInt(val.integer) else val.float;
1389
+ var lo: f64 = -std.math.floatMax(f64);
1390
+ var hi: f64 = std.math.floatMax(f64);
1391
+ if (start_in) |s| {
1392
+ lo = @floatFromInt(s);
1393
+ }
1394
+ if (end_in) |e| {
1395
+ hi = @floatFromInt(e - 1);
1396
+ }
1397
+ const clamped = @min(@max(f, lo), hi);
1398
+ // Return as integer if the original was integer
1399
+ if (clamped == @trunc(clamped)) {
1400
+ return JsonValue{ .integer = @intFromFloat(clamped) };
1401
+ }
1402
+ return JsonValue{ .float = clamped };
1403
+ }
1404
+ // bool, null, object: return as-is
1405
+ return val;
1406
+ }
1407
+
1408
+ const vlen: i64 = size(val);
1409
+
1410
+ // If end is specified but start is not, default start to 0
1411
+ var eff_start = start_in;
1412
+ if (end_in != null and eff_start == null) {
1413
+ eff_start = 0;
1414
+ }
1415
+
1416
+ if (eff_start == null) return val;
1417
+
1418
+ var start = eff_start.?;
1419
+ var end_val = vlen;
1420
+
1421
+ if (start < 0) {
1422
+ end_val = vlen + start;
1423
+ if (end_val < 0) end_val = 0;
1424
+ start = 0;
1425
+ } else if (end_in) |e| {
1426
+ end_val = e;
1427
+ if (end_val < 0) {
1428
+ end_val = vlen + end_val;
1429
+ if (end_val < 0) end_val = 0;
1430
+ } else if (vlen < end_val) {
1431
+ end_val = vlen;
1432
+ }
1433
+ }
1434
+
1435
+ if (vlen < start) start = vlen;
1436
+
1437
+ if (start >= 0 and start <= end_val and end_val <= vlen) {
1438
+ if (val == .array) {
1439
+ const s_usize: usize = @intCast(start);
1440
+ const e_usize: usize = @intCast(end_val);
1441
+ const src = val.array.data.items[s_usize..e_usize];
1442
+ const new_arr_lr = try allocator.create(ListRef);
1443
+ new_arr_lr.* = .{ .data = try ListData.initCapacity(allocator, src.len) };
1444
+ const new_arr = new_arr_lr;
1445
+ for (src) |item| {
1446
+ try new_arr.append(item);
1447
+ }
1448
+ return JsonValue{ .array = new_arr };
1449
+ }
1450
+ if (val == .string) {
1451
+ const s_usize: usize = @intCast(start);
1452
+ const e_usize: usize = @intCast(end_val);
1453
+ return JsonValue{ .string = val.string[s_usize..e_usize] };
1454
+ }
1455
+ } else {
1456
+ if (val == .array) {
1457
+ const empty_arr_lr = try allocator.create(ListRef);
1458
+ empty_arr_lr.* = .{ .data = ListData.init(allocator) };
1459
+ const empty_arr = empty_arr_lr;
1460
+ _ = &empty_arr;
1461
+ return JsonValue{ .array = empty_arr };
1462
+ }
1463
+ if (val == .string) {
1464
+ return JsonValue{ .string = S_MT };
1465
+ }
1466
+ }
1467
+
1468
+ return val;
1469
+ }
1470
+
1471
+ // Pad a string to a target length.
1472
+ pub fn pad(allocator: Allocator, s: []const u8, padding: i64, padchar: u8) ![]const u8 {
1473
+ if (padding >= 0) {
1474
+ const target: usize = @intCast(padding);
1475
+ if (s.len >= target) return s;
1476
+ var result = try allocator.alloc(u8, target);
1477
+ @memcpy(result[0..s.len], s);
1478
+ @memset(result[s.len..], padchar);
1479
+ return result;
1480
+ } else {
1481
+ const target: usize = @intCast(-padding);
1482
+ if (s.len >= target) return s;
1483
+ const pad_len = target - s.len;
1484
+ var result = try allocator.alloc(u8, target);
1485
+ @memset(result[0..pad_len], padchar);
1486
+ @memcpy(result[pad_len..], s);
1487
+ return result;
1488
+ }
1489
+ }
1490
+
1491
+ // ============================================================================
1492
+ // Walk — depth-first tree traversal with before/after callbacks.
1493
+ // ============================================================================
1494
+
1495
+ // Pool of path buffers — one std.ArrayList([]const u8) per depth. Allocated
1496
+ // once per top-level walk() call, grown on demand, and mutated in place as
1497
+ // siblings are visited. Avoids allocating a fresh path slice per recursive
1498
+ // call. Buffers are heap-allocated so that growing the outer list (on
1499
+ // deeper recursion) does not invalidate pointers held by shallower frames.
1500
+ const WalkPool = struct {
1501
+ allocator: Allocator,
1502
+ buffers: std.ArrayList(*std.ArrayList([]const u8)),
1503
+
1504
+ fn init(allocator: Allocator) WalkPool {
1505
+ return .{
1506
+ .allocator = allocator,
1507
+ .buffers = std.ArrayList(*std.ArrayList([]const u8)).init(allocator),
1508
+ };
1509
+ }
1510
+
1511
+ fn deinit(self: *WalkPool) void {
1512
+ for (self.buffers.items) |buf| {
1513
+ buf.deinit();
1514
+ self.allocator.destroy(buf);
1515
+ }
1516
+ self.buffers.deinit();
1517
+ }
1518
+
1519
+ // Return the path buffer for the given depth, growing the pool if needed.
1520
+ fn at(self: *WalkPool, depth: usize) !*std.ArrayList([]const u8) {
1521
+ while (self.buffers.items.len <= depth) {
1522
+ const buf = try self.allocator.create(std.ArrayList([]const u8));
1523
+ buf.* = std.ArrayList([]const u8).init(self.allocator);
1524
+ try self.buffers.append(buf);
1525
+ }
1526
+ return self.buffers.items[depth];
1527
+ }
1528
+ };
1529
+
1530
+ // Depth-first walk callback. The `path` slice is a shared, mutable buffer
1531
+ // reused across all callback invocations for the lifetime of this top-level
1532
+ // walk() call. Callbacks that need to retain the path MUST copy it
1533
+ // (e.g. `allocator.dupe([]const u8, path)`); otherwise its contents will be
1534
+ // overwritten by subsequent visits.
1535
+ pub const WalkApply = *const fn (
1536
+ allocator: Allocator,
1537
+ key: ?[]const u8,
1538
+ val: JsonValue,
1539
+ parent: JsonValue,
1540
+ path: []const []const u8,
1541
+ ) anyerror!JsonValue;
1542
+
1543
+ pub fn walk(
1544
+ allocator: Allocator,
1545
+ val: JsonValue,
1546
+ before: ?WalkApply,
1547
+ after: ?WalkApply,
1548
+ maxdepth: i32,
1549
+ ) !JsonValue {
1550
+ var pool = WalkPool.init(allocator);
1551
+ defer pool.deinit();
1552
+
1553
+ // Depth 0 path buffer (empty) — the root has no path entries.
1554
+ const root_buf = try pool.at(0);
1555
+ root_buf.clearRetainingCapacity();
1556
+
1557
+ return walkDescend(allocator, &pool, val, before, after, maxdepth, null, .null, root_buf.items);
1558
+ }
1559
+
1560
+ fn walkDescend(
1561
+ allocator: Allocator,
1562
+ pool: *WalkPool,
1563
+ val_in: JsonValue,
1564
+ before: ?WalkApply,
1565
+ after: ?WalkApply,
1566
+ maxdepth: i32,
1567
+ key: ?[]const u8,
1568
+ parent: JsonValue,
1569
+ path: []const []const u8,
1570
+ ) !JsonValue {
1571
+ var out = val_in;
1572
+
1573
+ // Apply before callback.
1574
+ if (before) |apply| {
1575
+ out = try apply(allocator, key, out, parent, path);
1576
+ }
1577
+
1578
+ // Check depth limit.
1579
+ if (maxdepth == 0 or (path.len > 0 and maxdepth > 0 and maxdepth <= @as(i32, @intCast(path.len)))) {
1580
+ return out;
1581
+ }
1582
+
1583
+ if (isnode(out)) {
1584
+ // Get items (sorted key-value pairs).
1585
+ const kv_pairs = try items(allocator, out);
1586
+ if (kv_pairs == .array) {
1587
+ const depth = path.len;
1588
+ const child_depth = depth + 1;
1589
+
1590
+ // Get (or create) the shared path buffer for this child depth,
1591
+ // and sync the prefix [0..depth] from the current path. Only
1592
+ // needed once per parent: siblings share the same prefix and
1593
+ // each overwrites slot [depth] below.
1594
+ const child_buf = try pool.at(child_depth);
1595
+ try child_buf.resize(child_depth);
1596
+ var i: usize = 0;
1597
+ while (i < depth) : (i += 1) {
1598
+ child_buf.items[i] = path[i];
1599
+ }
1600
+
1601
+ for (kv_pairs.array.data.items) |pair| {
1602
+ if (pair != .array or pair.array.data.items.len < 2) continue;
1603
+ const ckey_val = pair.array.data.items[0];
1604
+ const child = pair.array.data.items[1];
1605
+ const ckey = if (ckey_val == .string) ckey_val.string else "";
1606
+
1607
+ // Overwrite the last path slot for this sibling. The buffer
1608
+ // is shared across siblings — callbacks must copy the path
1609
+ // if they want to retain it.
1610
+ child_buf.items[depth] = ckey;
1611
+
1612
+ const new_child = try walkDescend(
1613
+ allocator,
1614
+ pool,
1615
+ child,
1616
+ before,
1617
+ after,
1618
+ maxdepth,
1619
+ ckey,
1620
+ out,
1621
+ child_buf.items,
1622
+ );
1623
+
1624
+ // Update the output with the new child value.
1625
+ out = try setprop(allocator, out, ckey_val, new_child);
1626
+ }
1627
+ }
1628
+ }
1629
+
1630
+ // Apply after callback.
1631
+ if (after) |apply| {
1632
+ out = try apply(allocator, key, out, parent, path);
1633
+ }
1634
+
1635
+ return out;
1636
+ }
1637
+
1638
+ // ============================================================================
1639
+ // Merge — deep-merge a list of values. Later values override.
1640
+ // ============================================================================
1641
+
1642
+ pub fn merge(allocator: Allocator, val: JsonValue, maxdepth: i32) !JsonValue {
1643
+ if (val != .array) return val;
1644
+
1645
+ const list = val.array.data.items;
1646
+ if (list.len == 0) return .null;
1647
+ if (list.len == 1) return list[0];
1648
+
1649
+ const md: i32 = if (maxdepth < 0) 0 else maxdepth;
1650
+
1651
+ // Special case: depth 0 returns empty container of last element's type.
1652
+ if (md == 0) {
1653
+ const last = list[list.len - 1];
1654
+ if (islist(last)) return try JsonValue.makeList(allocator);
1655
+ if (ismap(last)) {
1656
+ const obj = try allocator.create(MapRef);
1657
+ obj.* = .{ .data = MapData.init(allocator) };
1658
+ _ = &obj;
1659
+ return JsonValue{ .object = obj };
1660
+ }
1661
+ return last;
1662
+ }
1663
+
1664
+ // Use first element directly (not cloned) — matches TS/Go in-place
1665
+ // mutation semantics. With *MapRef/*ListRef, callers holding list[0]
1666
+ // see the merged result.
1667
+ var out = list[0];
1668
+
1669
+ for (list[1..]) |obj| {
1670
+ if (!isnode(obj)) {
1671
+ out = obj;
1672
+ } else {
1673
+ out = try mergeNodes(allocator, out, obj, md, 0);
1674
+ }
1675
+ }
1676
+
1677
+ return out;
1678
+ }
1679
+
1680
+ fn mergeNodes(
1681
+ allocator: Allocator,
1682
+ dst: JsonValue,
1683
+ src: JsonValue,
1684
+ maxdepth: i32,
1685
+ depth: i32,
1686
+ ) !JsonValue {
1687
+ // At depth limit: just replace.
1688
+ if (maxdepth > 0 and depth >= maxdepth) {
1689
+ return src;
1690
+ }
1691
+
1692
+ if (!isnode(src)) return src;
1693
+ if (!isnode(dst)) return try clone(allocator, src);
1694
+
1695
+ // Types differ: src wins.
1696
+ if ((ismap(src) and !ismap(dst)) or (islist(src) and !islist(dst))) {
1697
+ return try clone(allocator, src);
1698
+ }
1699
+
1700
+ // Both maps: deep merge. Clone dst so the caller's existing reference
1701
+ // is unchanged; callers that want in-place semantics either take the
1702
+ // return value or use the dedicated mergeIntoMap below.
1703
+ if (ismap(src) and ismap(dst)) {
1704
+ var result = try clone(allocator, dst);
1705
+ var it = src.object.iterator();
1706
+ while (it.next()) |kv| {
1707
+ const key_str = kv.key_ptr.*;
1708
+ const src_val = kv.value_ptr.*;
1709
+ const key_json = JsonValue{ .string = key_str };
1710
+
1711
+ if (result.object.get(key_str)) |dst_val| {
1712
+ if (isnode(src_val) and isnode(dst_val)) {
1713
+ const merged = try mergeNodes(allocator, dst_val, src_val, maxdepth, depth + 1);
1714
+ result = try setprop(allocator, result, key_json, merged);
1715
+ } else {
1716
+ result = try setprop(allocator, result, key_json, src_val);
1717
+ }
1718
+ } else {
1719
+ result = try setprop(allocator, result, key_json, src_val);
1720
+ }
1721
+ }
1722
+ return result;
1723
+ }
1724
+
1725
+ // Both lists: element-by-element overlay.
1726
+ if (islist(src) and islist(dst)) {
1727
+ var result = try clone(allocator, dst);
1728
+ for (src.array.data.items, 0..) |item, i| {
1729
+ const idx_json = JsonValue{ .integer = @intCast(i) };
1730
+ if (i < dst.array.data.items.len) {
1731
+ const dst_item = dst.array.data.items[i];
1732
+ if (isnode(item) and isnode(dst_item)) {
1733
+ const merged = try mergeNodes(allocator, dst_item, item, maxdepth, depth + 1);
1734
+ result = try setprop(allocator, result, idx_json, merged);
1735
+ } else {
1736
+ result = try setprop(allocator, result, idx_json, item);
1737
+ }
1738
+ } else {
1739
+ result = try setprop(allocator, result, idx_json, item);
1740
+ }
1741
+ }
1742
+ return result;
1743
+ }
1744
+
1745
+ return src;
1746
+ }
1747
+
1748
+ // In-place map merge: copy every key/value from src into dst, replacing
1749
+ // dst's entries. Used by validationModify's empty-spec branch where the
1750
+ // caller needs the merged result visible through the original *MapRef.
1751
+ fn mergeIntoMap(dst: JsonValue, src: JsonValue) !void {
1752
+ if (dst != .object or src != .object) return;
1753
+ var it = src.object.iterator();
1754
+ while (it.next()) |kv| {
1755
+ try dst.object.put(kv.key_ptr.*, kv.value_ptr.*);
1756
+ }
1757
+ }
1758
+
1759
+ // ============================================================================
1760
+ // GetPath — resolve a dotted path string against a store.
1761
+ // ============================================================================
1762
+
1763
+ pub fn getpath(allocator: Allocator, path_val: JsonValue, store: JsonValue) anyerror!JsonValue {
1764
+ return getpathInj(allocator, path_val, store, null);
1765
+ }
1766
+
1767
+ pub fn getpathInj(allocator: Allocator, path_val: JsonValue, store: JsonValue, inj: ?*Injection) anyerror!JsonValue {
1768
+ var parts_buf: [64][]const u8 = undefined;
1769
+ var numparts: usize = 0;
1770
+
1771
+ // Parse path into parts.
1772
+ switch (path_val) {
1773
+ .string => |s| {
1774
+ if (s.len == 0) {
1775
+ parts_buf[0] = S_MT;
1776
+ numparts = 1;
1777
+ } else {
1778
+ var it = std.mem.splitScalar(u8, s, '.');
1779
+ while (it.next()) |part| {
1780
+ if (numparts < parts_buf.len) {
1781
+ parts_buf[numparts] = part;
1782
+ numparts += 1;
1783
+ }
1784
+ }
1785
+ }
1786
+ },
1787
+ .array => |arr| {
1788
+ for (arr.data.items) |item| {
1789
+ if (numparts < parts_buf.len) {
1790
+ parts_buf[numparts] = if (item == .string) item.string else "";
1791
+ numparts += 1;
1792
+ }
1793
+ }
1794
+ },
1795
+ .null => {
1796
+ // Null path without injection → return null.
1797
+ // With injection, null path returns the source.
1798
+ if (inj == null) return .null;
1799
+ return getpropFromStore(store);
1800
+ },
1801
+ else => return .null,
1802
+ }
1803
+
1804
+ const parts = parts_buf[0..numparts];
1805
+
1806
+ // Single empty part (empty string path) → return source/dparent.
1807
+ // But NOT for multiple empty parts (.. ancestor paths).
1808
+ if (numparts == 1 and parts[0].len == 0) {
1809
+ if (inj) |ij| return ij.dparent;
1810
+ return getpropFromStore(store);
1811
+ }
1812
+ // Single "." (splits to ["",""]) → return dparent.
1813
+ if (numparts == 2 and parts[0].len == 0 and parts[1].len == 0) {
1814
+ if (inj) |ij| return ij.dparent;
1815
+ return getpropFromStore(store);
1816
+ }
1817
+
1818
+ // Single part: check store directly first (for $ commands etc).
1819
+ if (numparts == 1) {
1820
+ if (store == .object) {
1821
+ if (store.object.get(parts[0])) |v| {
1822
+ // If the value is a function, call it.
1823
+ if (v == .function) return try v.function.call(v.function.ctx, allocator, JsonValue{ .null = {} });
1824
+ return v;
1825
+ }
1826
+ }
1827
+ }
1828
+
1829
+ // Resolve through $TOP (or dparent for relative paths). However if the
1830
+ // path's first part already matches a key in store, start from store
1831
+ // directly — this lets absolute paths like "$TOP.z.p" walk without
1832
+ // double-traversing $TOP. Mirrors what the Rust port does (its
1833
+ // get_path_inj starts with src = store when there's no base).
1834
+ var val = if (numparts > 0 and parts[0].len > 0 and store == .object and store.object.get(parts[0]) != null)
1835
+ store
1836
+ else
1837
+ getpropFromStore(store);
1838
+
1839
+ // Meta-path syntax: "name$~rest" or "name$=rest" on the first part.
1840
+ if (numparts > 0 and inj != null and inj.?.meta != .null) {
1841
+ const first = parts[0];
1842
+ // Find "$~" or "$=" in first part.
1843
+ if (std.mem.indexOf(u8, first, "$~") orelse std.mem.indexOf(u8, first, "$=")) |dpos| {
1844
+ const meta_key = first[0..dpos];
1845
+ const rest = first[dpos + 2 ..];
1846
+ val = try getprop(allocator, inj.?.meta, JsonValue{ .string = meta_key }, .null);
1847
+ parts_buf[0] = rest;
1848
+ }
1849
+ }
1850
+
1851
+ var pI: usize = 0;
1852
+ while (pI < numparts) : (pI += 1) {
1853
+ if (val == .null) break;
1854
+ const part = parts[pI];
1855
+
1856
+ // Handle $REF:subpath$ — resolve subpath in $SPEC, use result as part.
1857
+ if (inj != null and part.len > 5 and std.mem.startsWith(u8, part, "$REF:") and part[part.len - 1] == '$') {
1858
+ const subpath = part[5 .. part.len - 1];
1859
+ const spec_val = if (store == .object) store.object.get(S_DSPEC) orelse .null else .null;
1860
+ if (spec_val != .null) {
1861
+ const result = try getpath(allocator, JsonValue{ .string = subpath }, spec_val);
1862
+ const effective = try stringify(allocator, result, null);
1863
+ val = try resolvePart(allocator, val, effective, inj);
1864
+ }
1865
+ continue;
1866
+ }
1867
+
1868
+ // Handle $GET:subpath$ — resolve subpath in store data, use result as part.
1869
+ if (inj != null and part.len > 5 and std.mem.startsWith(u8, part, "$GET:") and part[part.len - 1] == '$') {
1870
+ const subpath = part[5 .. part.len - 1];
1871
+ const result = try getpath(allocator, JsonValue{ .string = subpath }, store);
1872
+ const effective = try stringify(allocator, result, null);
1873
+ val = try resolvePart(allocator, val, effective, inj);
1874
+ continue;
1875
+ }
1876
+
1877
+ // Handle $META:subpath$ — resolve subpath in injection metadata.
1878
+ if (inj != null and part.len > 6 and std.mem.startsWith(u8, part, "$META:") and part[part.len - 1] == '$') {
1879
+ const subpath = part[6 .. part.len - 1];
1880
+ const ij = inj.?;
1881
+ if (ij.meta != .null) {
1882
+ const result = try getpathInj(allocator, JsonValue{ .string = subpath }, ij.meta, null);
1883
+ const effective = try stringify(allocator, result, null);
1884
+ val = try resolvePart(allocator, val, effective, inj);
1885
+ }
1886
+ continue;
1887
+ }
1888
+
1889
+ // Handle empty parts (from consecutive dots): ancestor traversal.
1890
+ if (part.len == 0) {
1891
+ // Count consecutive empty parts as ascend levels.
1892
+ var ascends: usize = 0;
1893
+ while (pI + 1 < numparts and parts[pI + 1].len == 0) {
1894
+ ascends += 1;
1895
+ pI += 1;
1896
+ }
1897
+
1898
+ if (inj != null and ascends > 0) {
1899
+ const ij = inj.?;
1900
+ // Last group of dots with no trailing part: adjust.
1901
+ if (pI == numparts - 1) {
1902
+ if (ascends > 0) ascends -= 1;
1903
+ }
1904
+
1905
+ if (ascends == 0) {
1906
+ val = ij.dparent;
1907
+ } else {
1908
+ // Build full path from dpath minus ascends, plus remaining parts.
1909
+ const dpath = ij.dpath;
1910
+ const cutLen = if (ascends > dpath.len) 0 else dpath.len - ascends;
1911
+ var fullpath = std.ArrayList([]const u8).init(allocator);
1912
+ for (dpath[0..cutLen]) |dp| try fullpath.append(dp);
1913
+ if (pI + 1 < numparts) {
1914
+ for (parts[pI + 1 .. numparts]) |rp| try fullpath.append(rp);
1915
+ }
1916
+ if (ascends <= dpath.len) {
1917
+ // Walk the fullpath array against the store directly.
1918
+ var resolved = store;
1919
+ var prev_fp: []const u8 = "";
1920
+ for (fullpath.items) |fp| {
1921
+ if (resolved == .null) break;
1922
+ // Skip synthetic $: markers.
1923
+ if (fp.len > 2 and std.mem.startsWith(u8, fp, "$:")) continue;
1924
+ // Skip duplicate consecutive $TOP entries.
1925
+ if (std.mem.eql(u8, fp, S_DTOP) and std.mem.eql(u8, prev_fp, S_DTOP)) continue;
1926
+ prev_fp = fp;
1927
+ if (resolved == .object) {
1928
+ if (resolved.object.get(fp)) |v| {
1929
+ resolved = v;
1930
+ } else {
1931
+ resolved = .null;
1932
+ }
1933
+ } else if (resolved == .array) {
1934
+ const idx = std.fmt.parseInt(i64, fp, 10) catch {
1935
+ resolved = .null;
1936
+ break;
1937
+ };
1938
+ if (idx >= 0 and idx < @as(i64, @intCast(resolved.array.data.items.len))) {
1939
+ resolved = resolved.array.data.items[@intCast(idx)];
1940
+ } else {
1941
+ resolved = .null;
1942
+ }
1943
+ } else {
1944
+ resolved = .null;
1945
+ }
1946
+ }
1947
+ val = resolved;
1948
+ } else {
1949
+ val = .null;
1950
+ }
1951
+ return val;
1952
+ }
1953
+ } else {
1954
+ val = if (inj) |ij| ij.dparent else val;
1955
+ }
1956
+ continue;
1957
+ }
1958
+
1959
+ val = try resolvePart(allocator, val, part, inj);
1960
+ }
1961
+
1962
+ return val;
1963
+ }
1964
+
1965
+ fn resolvePart(allocator: Allocator, val: JsonValue, part_in: []const u8, inj: ?*const Injection) !JsonValue {
1966
+ // Handle $$ escape → $.
1967
+ var part = part_in;
1968
+ if (std.mem.indexOf(u8, part, "$$")) |_| {
1969
+ var buf = std.ArrayList(u8).init(allocator);
1970
+ var i: usize = 0;
1971
+ while (i < part.len) {
1972
+ if (i + 1 < part.len and part[i] == '$' and part[i + 1] == '$') {
1973
+ buf.append('$') catch {};
1974
+ i += 2;
1975
+ } else {
1976
+ buf.append(part[i]) catch {};
1977
+ i += 1;
1978
+ }
1979
+ }
1980
+ part = buf.items;
1981
+ }
1982
+
1983
+ // Handle $KEY → replace with injection key.
1984
+ if (std.mem.eql(u8, part, "$KEY")) {
1985
+ if (inj) |ij| {
1986
+ part = ij.key;
1987
+ }
1988
+ }
1989
+
1990
+ if (val == .object) {
1991
+ return val.object.get(part) orelse .null;
1992
+ } else if (val == .array) {
1993
+ const idx = std.fmt.parseInt(i64, part, 10) catch return .null;
1994
+ if (idx >= 0 and idx < @as(i64, @intCast(val.array.data.items.len))) {
1995
+ return val.array.data.items[@intCast(idx)];
1996
+ }
1997
+ return .null;
1998
+ }
1999
+ return .null;
2000
+ }
2001
+
2002
+ fn getpropFromStore(store: JsonValue) JsonValue {
2003
+ if (store == .object) {
2004
+ return store.object.get(S_DTOP) orelse store;
2005
+ }
2006
+ return store;
2007
+ }
2008
+
2009
+ // ============================================================================
2010
+ // SetPath — set a value at a dotted path in a store.
2011
+ // ============================================================================
2012
+
2013
+ pub fn setpath(allocator: Allocator, store: JsonValue, path_val: JsonValue, val: JsonValue) !JsonValue {
2014
+ var parts_buf: [64][]const u8 = undefined;
2015
+ var is_numeric: [64]bool = undefined;
2016
+ var numparts: usize = 0;
2017
+
2018
+ switch (path_val) {
2019
+ .string => |s| {
2020
+ var it = std.mem.splitScalar(u8, s, '.');
2021
+ while (it.next()) |part| {
2022
+ if (numparts < parts_buf.len) {
2023
+ parts_buf[numparts] = part;
2024
+ is_numeric[numparts] = false;
2025
+ numparts += 1;
2026
+ }
2027
+ }
2028
+ },
2029
+ .array => |arr| {
2030
+ for (arr.data.items) |item| {
2031
+ if (numparts < parts_buf.len) {
2032
+ switch (item) {
2033
+ .string => |s| {
2034
+ parts_buf[numparts] = s;
2035
+ is_numeric[numparts] = false;
2036
+ },
2037
+ .integer => |i| {
2038
+ parts_buf[numparts] = std.fmt.allocPrint(allocator, "{d}", .{i}) catch "";
2039
+ is_numeric[numparts] = true;
2040
+ },
2041
+ else => {
2042
+ parts_buf[numparts] = "";
2043
+ is_numeric[numparts] = false;
2044
+ },
2045
+ }
2046
+ numparts += 1;
2047
+ }
2048
+ }
2049
+ },
2050
+ else => return store,
2051
+ }
2052
+
2053
+ if (numparts == 0) return store;
2054
+
2055
+ const parts = parts_buf[0..numparts];
2056
+ var parent = getpropFromStore(store);
2057
+
2058
+ // Navigate to the parent of the final key, creating nodes as needed.
2059
+ var i: usize = 0;
2060
+ while (i < numparts - 1) : (i += 1) {
2061
+ const part = parts[i];
2062
+ const key_json = JsonValue{ .string = part };
2063
+ var next = try getprop(allocator, parent, key_json, .null);
2064
+ if (!isnode(next)) {
2065
+ // Create array if the next part is a numeric from an array path, else object.
2066
+ if (i + 1 < numparts and is_numeric[i + 1]) {
2067
+ next = try JsonValue.makeList(allocator);
2068
+ } else {
2069
+ next = try JsonValue.makeMap(allocator);
2070
+ }
2071
+ parent = try setprop(allocator, parent, key_json, next);
2072
+ }
2073
+ parent = next;
2074
+ }
2075
+
2076
+ // Set the final value. Return the modified parent node.
2077
+ const last_key = JsonValue{ .string = parts[numparts - 1] };
2078
+ return try setprop(allocator, parent, last_key, val);
2079
+ }
2080
+
2081
+ // ============================================================================
2082
+ // Injection — state carried through recursive spec injection.
2083
+ // Mirrors the Go/TS Injection struct for three-phase key processing.
2084
+ // ============================================================================
2085
+
2086
+ // Modify callback — called after each injection step to post-process values.
2087
+ pub const ModifyFn = *const fn (
2088
+ allocator: Allocator,
2089
+ val: JsonValue,
2090
+ key: []const u8,
2091
+ parent: JsonValue,
2092
+ inj: *Injection,
2093
+ store: JsonValue,
2094
+ ) void;
2095
+
2096
+ pub const Injection = struct {
2097
+ allocator: Allocator,
2098
+ mode: i32 = M_VAL,
2099
+ full: bool = false,
2100
+ skip: bool = false, // Set by handlers to suppress setval.
2101
+ validate_mode: bool = false, // Enables $STRING/$NUMBER/etc validation commands.
2102
+ exact_mode: bool = false, // Exact matching mode for select.
2103
+ key_i: usize = 0,
2104
+ key: []const u8 = S_DTOP,
2105
+ val: JsonValue = .null,
2106
+ parent: JsonValue = .null,
2107
+ base: []const u8 = S_DTOP,
2108
+ prior: ?*Injection = null,
2109
+ dparent: JsonValue = .null,
2110
+
2111
+ // Heap-allocated slices from the arena.
2112
+ keys: [][]const u8,
2113
+ path: [][]const u8,
2114
+ nodes: []JsonValue,
2115
+ dpath: [][]const u8,
2116
+
2117
+ // Metadata for injection context.
2118
+ meta: JsonValue = .null,
2119
+
2120
+ // Optional modify callback — called after each injection step.
2121
+ modify: ?ModifyFn = null,
2122
+
2123
+ // Shared error collector (pointer so all children share it).
2124
+ errs: *std.ArrayList([]const u8),
2125
+
2126
+ // Create a child injection for processing key at keys[key_i].
2127
+ pub fn child(self: *Injection, key_i: usize, keys: []const []const u8) !*Injection {
2128
+ const a = self.allocator;
2129
+ const k = if (key_i < keys.len) keys[key_i] else S_MT;
2130
+
2131
+ // Extend path: parent path + new key.
2132
+ var new_path = try a.alloc([]const u8, self.path.len + 1);
2133
+ @memcpy(new_path[0..self.path.len], self.path);
2134
+ new_path[self.path.len] = k;
2135
+
2136
+ // Extend nodes: parent nodes + current val.
2137
+ var new_nodes = try a.alloc(JsonValue, self.nodes.len + 1);
2138
+ @memcpy(new_nodes[0..self.nodes.len], self.nodes);
2139
+ new_nodes[self.nodes.len] = self.val;
2140
+
2141
+ // Copy dpath.
2142
+ const new_dpath = try a.alloc([]const u8, self.dpath.len);
2143
+ @memcpy(new_dpath, self.dpath);
2144
+
2145
+ // Copy keys.
2146
+ const new_keys = try a.alloc([]const u8, keys.len);
2147
+ @memcpy(new_keys, keys);
2148
+
2149
+ const c = try a.create(Injection);
2150
+ c.* = Injection{
2151
+ .allocator = a,
2152
+ .mode = self.mode,
2153
+ .full = false,
2154
+ .key_i = key_i,
2155
+ .key = k,
2156
+ .val = getprop(a, self.val, JsonValue{ .string = k }, .null) catch .null,
2157
+ .parent = self.val,
2158
+ .base = self.base,
2159
+ .prior = self,
2160
+ .dparent = self.dparent,
2161
+ .keys = new_keys,
2162
+ .path = new_path,
2163
+ .nodes = new_nodes,
2164
+ .dpath = new_dpath,
2165
+ .meta = self.meta,
2166
+ .modify = self.modify,
2167
+ .validate_mode = self.validate_mode,
2168
+ .exact_mode = self.exact_mode,
2169
+ .errs = self.errs,
2170
+ };
2171
+ return c;
2172
+ }
2173
+
2174
+ // Set a value in the parent node (or an ancestor).
2175
+ pub fn setval(self: *Injection, val: JsonValue, ancestor: usize) !JsonValue {
2176
+ const a = self.allocator;
2177
+ if (ancestor < 2) {
2178
+ if (val == .null) {
2179
+ self.parent = delprop(a, self.parent, JsonValue{ .string = self.key }) catch self.parent;
2180
+ } else {
2181
+ self.parent = setprop(a, self.parent, JsonValue{ .string = self.key }, val) catch self.parent;
2182
+ }
2183
+ return self.parent;
2184
+ } else {
2185
+ // Ancestor access via nodes/path.
2186
+ const nlen = self.nodes.len;
2187
+ const plen = self.path.len;
2188
+ if (ancestor > nlen or ancestor > plen) return self.parent;
2189
+ const aval = self.nodes[nlen - ancestor];
2190
+ const akey = self.path[plen - ancestor];
2191
+ if (val == .null) {
2192
+ _ = delprop(a, aval, JsonValue{ .string = akey }) catch {};
2193
+ } else {
2194
+ _ = setprop(a, aval, JsonValue{ .string = akey }, val) catch {};
2195
+ }
2196
+ return aval;
2197
+ }
2198
+ }
2199
+
2200
+ // Advance dparent down the data tree based on the current path.
2201
+ pub fn descend(self: *Injection) void {
2202
+ const a = self.allocator;
2203
+ var parentkey: []const u8 = S_MT;
2204
+ if (self.path.len >= 2) {
2205
+ parentkey = self.path[self.path.len - 2];
2206
+ }
2207
+
2208
+ if (self.dparent == .null) {
2209
+ if (self.dpath.len > 1) {
2210
+ self.dpath = appendSlice(a, []const u8, self.dpath, parentkey) catch self.dpath;
2211
+ }
2212
+ } else {
2213
+ if (parentkey.len > 0) {
2214
+ self.dparent = getprop(a, self.dparent, JsonValue{ .string = parentkey }, .null) catch .null;
2215
+
2216
+ const lastpart: []const u8 = if (self.dpath.len > 0)
2217
+ self.dpath[self.dpath.len - 1]
2218
+ else
2219
+ S_MT;
2220
+
2221
+ // Check for synthetic path marker "$:key".
2222
+ const marker = std.fmt.allocPrint(a, "$:{s}", .{parentkey}) catch S_MT;
2223
+ if (std.mem.eql(u8, lastpart, marker)) {
2224
+ // Pop synthetic marker.
2225
+ self.dpath = self.dpath[0 .. self.dpath.len - 1];
2226
+ } else {
2227
+ self.dpath = appendSlice(a, []const u8, self.dpath, parentkey) catch self.dpath;
2228
+ }
2229
+ }
2230
+ }
2231
+ }
2232
+ };
2233
+
2234
+ fn appendSlice(allocator: Allocator, comptime T: type, existing: []const T, item: T) ![]T {
2235
+ var new = try allocator.alloc(T, existing.len + 1);
2236
+ @memcpy(new[0..existing.len], existing);
2237
+ new[existing.len] = item;
2238
+ return new;
2239
+ }
2240
+
2241
+ // ============================================================================
2242
+ // Inject — core injection function with three-phase key processing.
2243
+ // ============================================================================
2244
+
2245
+ pub fn inject(allocator: Allocator, val: JsonValue, store: JsonValue, inj_opt: ?*Injection) anyerror!JsonValue {
2246
+ var inj: *Injection = undefined;
2247
+
2248
+ if (inj_opt == null or (inj_opt != null and inj_opt.?.mode == 0)) {
2249
+ // Root injection: wrap val in a virtual parent.
2250
+ const parent_obj = try allocator.create(MapRef);
2251
+ parent_obj.* = .{ .data = MapData.init(allocator) };
2252
+ try parent_obj.put(S_DTOP, val);
2253
+ const parent_val = JsonValue{ .object = parent_obj };
2254
+
2255
+ var errs: *std.ArrayList([]const u8) = undefined;
2256
+ if (inj_opt) |existing| {
2257
+ errs = existing.errs;
2258
+ } else {
2259
+ errs = try allocator.create(std.ArrayList([]const u8));
2260
+ errs.* = std.ArrayList([]const u8).init(allocator);
2261
+ }
2262
+
2263
+ var init_keys = try allocator.alloc([]const u8, 1);
2264
+ init_keys[0] = S_DTOP;
2265
+ var init_path = try allocator.alloc([]const u8, 1);
2266
+ init_path[0] = S_DTOP;
2267
+ var init_nodes = try allocator.alloc(JsonValue, 1);
2268
+ init_nodes[0] = parent_val;
2269
+ var init_dpath = try allocator.alloc([]const u8, 1);
2270
+ init_dpath[0] = S_DTOP;
2271
+
2272
+ inj = try allocator.create(Injection);
2273
+ inj.* = Injection{
2274
+ .allocator = allocator,
2275
+ .mode = M_VAL,
2276
+ .key = S_DTOP,
2277
+ .val = val,
2278
+ .parent = parent_val,
2279
+ .base = S_DTOP,
2280
+ .dparent = store,
2281
+ .keys = init_keys,
2282
+ .path = init_path,
2283
+ .nodes = init_nodes,
2284
+ .dpath = init_dpath,
2285
+ .errs = errs,
2286
+ };
2287
+
2288
+ // Merge in partial init if provided.
2289
+ if (inj_opt) |existing| {
2290
+ if (existing.dparent != .null) inj.dparent = existing.dparent;
2291
+ if (existing.dpath.len > 0) inj.dpath = existing.dpath;
2292
+ if (existing.modify != null) inj.modify = existing.modify;
2293
+ if (existing.meta != .null) inj.meta = existing.meta;
2294
+ if (existing.validate_mode) inj.validate_mode = true;
2295
+ if (existing.exact_mode) inj.exact_mode = true;
2296
+ }
2297
+ } else {
2298
+ inj = inj_opt.?;
2299
+ }
2300
+
2301
+ inj.descend();
2302
+ var current = val;
2303
+
2304
+ if (isnode(val)) {
2305
+ // Get sorted keys: normal first, then $ transform keys.
2306
+ var normal_keys = std.ArrayList([]const u8).init(allocator);
2307
+ var transform_keys = std.ArrayList([]const u8).init(allocator);
2308
+
2309
+ const all_keys = try keysof(allocator, current);
2310
+ if (all_keys == .array) {
2311
+ for (all_keys.array.data.items) |k| {
2312
+ if (k != .string) continue;
2313
+ const ks = k.string;
2314
+ if (std.mem.indexOf(u8, ks, S_DS) != null) {
2315
+ try transform_keys.append(ks);
2316
+ } else {
2317
+ try normal_keys.append(ks);
2318
+ }
2319
+ }
2320
+ }
2321
+
2322
+ var node_keys = std.ArrayList([]const u8).init(allocator);
2323
+ for (normal_keys.items) |k| try node_keys.append(k);
2324
+ for (transform_keys.items) |k| try node_keys.append(k);
2325
+
2326
+ // nkI is signed so cmdRef's `prior.key_i -%= 1` on a fresh 0 wraps to
2327
+ // max-usize and bit-casts back to -1 here — then `nkI += 1` lands on
2328
+ // the same index again, re-visiting the slot that the parent list
2329
+ // just shifted into place. Matches the TS / Rust / Go ports.
2330
+ var nkI: isize = 0;
2331
+ while (nkI < @as(isize, @intCast(node_keys.items.len))) {
2332
+ const nodekey = node_keys.items[@as(usize, @intCast(nkI))];
2333
+
2334
+ var childinj = try inj.child(@as(usize, @intCast(nkI)), node_keys.items);
2335
+ childinj.mode = M_KEYPRE;
2336
+
2337
+ // Phase 1: KEYPRE — inject the key string.
2338
+ const pre_key = try injectStr(allocator, nodekey, store, childinj);
2339
+
2340
+ // Injection may modify child processing state.
2341
+ nkI = @as(isize, @bitCast(childinj.key_i));
2342
+ node_keys = blk: {
2343
+ var nk = std.ArrayList([]const u8).init(allocator);
2344
+ for (childinj.keys) |k| try nk.append(k);
2345
+ break :blk nk;
2346
+ };
2347
+ current = childinj.parent;
2348
+
2349
+ if (pre_key != .null) {
2350
+ const prekey_str = if (pre_key == .string) pre_key.string else nodekey;
2351
+ const childval = try getprop(allocator, current, JsonValue{ .string = prekey_str }, .null);
2352
+ childinj.val = childval;
2353
+ childinj.mode = M_VAL;
2354
+
2355
+ // Phase 2: VAL — inject the child value.
2356
+ _ = try inject(allocator, childval, store, childinj);
2357
+
2358
+ nkI = @as(isize, @bitCast(childinj.key_i));
2359
+ node_keys = blk: {
2360
+ var nk = std.ArrayList([]const u8).init(allocator);
2361
+ for (childinj.keys) |k| try nk.append(k);
2362
+ break :blk nk;
2363
+ };
2364
+ current = childinj.parent;
2365
+
2366
+ // Phase 3: KEYPOST — post-process the key.
2367
+ childinj.mode = M_KEYPOST;
2368
+ _ = try injectStr(allocator, nodekey, store, childinj);
2369
+
2370
+ nkI = @as(isize, @bitCast(childinj.key_i));
2371
+ node_keys = blk: {
2372
+ var nk = std.ArrayList([]const u8).init(allocator);
2373
+ for (childinj.keys) |k| try nk.append(k);
2374
+ break :blk nk;
2375
+ };
2376
+ current = childinj.parent;
2377
+ }
2378
+
2379
+ nkI += 1;
2380
+ }
2381
+ } else if (val == .string) {
2382
+ // Inject paths into string scalars.
2383
+ inj.mode = M_VAL;
2384
+ const result = try injectStr(allocator, val.string, store, inj);
2385
+ if (!inj.skip and (result != .null or val != .null)) {
2386
+ _ = try inj.setval(result, 0);
2387
+ }
2388
+ inj.skip = false;
2389
+ current = result;
2390
+ }
2391
+
2392
+ inj.val = current;
2393
+
2394
+ // Call modify callback if set (skip suppresses modify too).
2395
+ if (!inj.skip) {
2396
+ if (inj.modify) |modify_fn| {
2397
+ const mval = getprop(allocator, inj.parent, JsonValue{ .string = inj.key }, .null) catch .null;
2398
+ modify_fn(allocator, mval, inj.key, inj.parent, inj, store);
2399
+ }
2400
+ }
2401
+
2402
+ // Return value is the top-level result.
2403
+ return try getprop(allocator, inj.parent, JsonValue{ .string = S_DTOP }, .null);
2404
+ }
2405
+
2406
+ // ============================================================================
2407
+ // injectStr — resolve backtick path references using the Injection context.
2408
+ // ============================================================================
2409
+
2410
+ fn injectStr(allocator: Allocator, val: []const u8, store: JsonValue, inj: *Injection) !JsonValue {
2411
+ if (val.len == 0) return JsonValue{ .string = S_MT };
2412
+
2413
+ // Full injection: entire string is `path` (possibly with trailing digits).
2414
+ if (val.len >= 2 and val[0] == '`' and val[val.len - 1] == '`') {
2415
+ var inner_bt: usize = 0;
2416
+ for (val[1 .. val.len - 1]) |c| {
2417
+ if (c == '`') inner_bt += 1;
2418
+ }
2419
+ if (inner_bt == 0) {
2420
+ inj.full = true;
2421
+ var pathref = val[1 .. val.len - 1];
2422
+ pathref = stripCmdDigits(pathref);
2423
+ pathref = resolveSpecialEscapes(allocator, pathref);
2424
+ return try resolvePathOrCmd(allocator, pathref, store, inj);
2425
+ }
2426
+ }
2427
+
2428
+ // No backticks → return as-is.
2429
+ if (std.mem.indexOf(u8, val, "`") == null) {
2430
+ return JsonValue{ .string = val };
2431
+ }
2432
+
2433
+ // Partial injection: replace each `ref` segment.
2434
+ inj.full = false;
2435
+ var result = std.ArrayList(u8).init(allocator);
2436
+ var i: usize = 0;
2437
+ while (i < val.len) {
2438
+ if (val[i] == '`') {
2439
+ const close = std.mem.indexOfScalarPos(u8, val, i + 1, '`');
2440
+ if (close) |end| {
2441
+ var ref = val[i + 1 .. end];
2442
+ ref = resolveSpecialEscapes(allocator, ref);
2443
+ const found = try resolvePathOnly(allocator, ref, store, inj);
2444
+ if (found == .string) {
2445
+ try result.appendSlice(found.string);
2446
+ } else if (found == .null) {
2447
+ // Check if the key actually exists in the store with a null value
2448
+ // vs being absent. If present, stringify as "null".
2449
+ const exists = blk: {
2450
+ if (store == .object) {
2451
+ if (store.object.get(ref) != null) break :blk true;
2452
+ // Check in $TOP
2453
+ if (store.object.get(S_DTOP)) |top| {
2454
+ if (top == .object and top.object.get(ref) != null) break :blk true;
2455
+ }
2456
+ }
2457
+ break :blk false;
2458
+ };
2459
+ if (exists) try result.appendSlice("null");
2460
+ } else if (isnode(found)) {
2461
+ // Nodes use compact JSON format in partial injections.
2462
+ try result.appendSlice(try jsonifyCompact(allocator, found));
2463
+ } else {
2464
+ try result.appendSlice(try stringifyInner(allocator, found));
2465
+ }
2466
+ i = end + 1;
2467
+ } else {
2468
+ try result.append(val[i]);
2469
+ i += 1;
2470
+ }
2471
+ } else {
2472
+ try result.append(val[i]);
2473
+ i += 1;
2474
+ }
2475
+ }
2476
+ return JsonValue{ .string = result.items };
2477
+ }
2478
+
2479
+ // Resolve a path reference that may be a command or a data path.
2480
+ fn resolvePathOrCmd(allocator: Allocator, pathref: []const u8, store: JsonValue, inj: *Injection) !JsonValue {
2481
+ // Built-in escape commands (always resolve regardless of mode).
2482
+ if (std.mem.eql(u8, pathref, "$BT")) return JsonValue{ .string = S_BT };
2483
+ if (std.mem.eql(u8, pathref, "$DS")) return JsonValue{ .string = S_DS };
2484
+
2485
+ // Command dispatch — mode-sensitive.
2486
+ if (pathref.len > 0 and pathref[0] == '$') {
2487
+ return try dispatchCmd(allocator, pathref, store, inj);
2488
+ }
2489
+
2490
+ // Relative path — use getpathInj so ancestor traversal uses dpath.
2491
+ if (pathref.len > 0 and pathref[0] == '.') {
2492
+ return try getpathInj(allocator, JsonValue{ .string = pathref }, store, inj);
2493
+ }
2494
+
2495
+ // Absolute path from store.
2496
+ return try getpath(allocator, JsonValue{ .string = pathref }, store);
2497
+ }
2498
+
2499
+ // Resolve a path reference (no command dispatch — used for partial injections).
2500
+ fn resolvePathOnly(allocator: Allocator, pathref: []const u8, store: JsonValue, inj: *Injection) !JsonValue {
2501
+ if (std.mem.eql(u8, pathref, "$BT")) return JsonValue{ .string = S_BT };
2502
+ if (std.mem.eql(u8, pathref, "$DS")) return JsonValue{ .string = S_DS };
2503
+
2504
+ if (pathref.len > 0 and pathref[0] == '.') {
2505
+ return try getpathInj(allocator, JsonValue{ .string = pathref }, store, inj);
2506
+ }
2507
+
2508
+ return try getpath(allocator, JsonValue{ .string = pathref }, store);
2509
+ }
2510
+
2511
+ fn resolveRelativePath(allocator: Allocator, pathref: []const u8, dparent: JsonValue) anyerror!JsonValue {
2512
+ var dots: usize = 0;
2513
+ while (dots < pathref.len and pathref[dots] == '.') dots += 1;
2514
+
2515
+ const rest = pathref[dots..];
2516
+ if (rest.len == 0) return dparent;
2517
+
2518
+ var val = dparent;
2519
+ var it = std.mem.splitScalar(u8, rest, '.');
2520
+ while (it.next()) |part| {
2521
+ if (val == .null) break;
2522
+ val = try getprop(allocator, val, JsonValue{ .string = part }, .null);
2523
+ }
2524
+ return val;
2525
+ }
2526
+
2527
+ // ============================================================================
2528
+ // Command dispatch — routes $ commands to handlers based on mode.
2529
+ // ============================================================================
2530
+
2531
+ fn dispatchCmd(allocator: Allocator, cmd: []const u8, store: JsonValue, inj: *Injection) !JsonValue {
2532
+ if (std.mem.eql(u8, cmd, "$COPY")) return cmdCopy(allocator, inj);
2533
+ if (std.mem.eql(u8, cmd, "$DELETE")) return cmdDelete(inj);
2534
+ if (std.mem.eql(u8, cmd, "$KEY")) return cmdKey(inj);
2535
+ if (std.mem.eql(u8, cmd, "$MERGE")) return try cmdMerge(allocator, inj, store);
2536
+ if (std.mem.eql(u8, cmd, "$ANNO")) return cmdAnno(inj);
2537
+ if (std.mem.eql(u8, cmd, "$FORMAT")) return try cmdFormat(allocator, inj, store);
2538
+ if (std.mem.eql(u8, cmd, "$EACH")) return try cmdEach(allocator, inj, store);
2539
+ if (std.mem.eql(u8, cmd, "$PACK")) return try cmdPack(allocator, inj, store);
2540
+ if (std.mem.eql(u8, cmd, "$REF")) return try cmdRef(allocator, inj, store);
2541
+ if (std.mem.eql(u8, cmd, "$APPLY")) return try cmdApply(allocator, inj);
2542
+
2543
+ // Validation commands — only active when validate_mode is set.
2544
+ if (inj.validate_mode) {
2545
+ if (std.mem.eql(u8, cmd, "$STRING")) return try cmdValidateType(allocator, inj, S_string, T_string);
2546
+ if (std.mem.eql(u8, cmd, "$NUMBER")) return try cmdValidateType(allocator, inj, S_number, T_number);
2547
+ if (std.mem.eql(u8, cmd, "$INTEGER")) return try cmdValidateType(allocator, inj, S_integer, T_integer);
2548
+ if (std.mem.eql(u8, cmd, "$DECIMAL")) return try cmdValidateType(allocator, inj, S_decimal, T_decimal);
2549
+ if (std.mem.eql(u8, cmd, "$BOOLEAN")) return try cmdValidateType(allocator, inj, S_boolean, T_boolean);
2550
+ if (std.mem.eql(u8, cmd, "$NULL")) return try cmdValidateType(allocator, inj, S_null, T_null);
2551
+ if (std.mem.eql(u8, cmd, "$OBJECT") or std.mem.eql(u8, cmd, "$MAP"))
2552
+ return try cmdValidateType(allocator, inj, S_map, T_map);
2553
+ if (std.mem.eql(u8, cmd, "$ARRAY") or std.mem.eql(u8, cmd, "$LIST"))
2554
+ return try cmdValidateType(allocator, inj, S_list, T_list);
2555
+ if (std.mem.eql(u8, cmd, "$ANY")) return cmdValidateAny(inj);
2556
+ if (std.mem.eql(u8, cmd, "$ONE")) return try cmdValidateOne(allocator, inj, store);
2557
+ if (std.mem.eql(u8, cmd, "$EXACT")) return try cmdValidateExactCmd(allocator, inj);
2558
+ if (std.mem.eql(u8, cmd, "$CHILD")) return try cmdValidateChildCmd(allocator, inj, store);
2559
+ }
2560
+
2561
+ // Unknown $ key — check if the store has it as a function value.
2562
+ if (store == .object) {
2563
+ if (store.object.get(cmd)) |val| {
2564
+ if (val == .function) {
2565
+ return try val.function.call(val.function.ctx, allocator, JsonValue{ .null = {} });
2566
+ }
2567
+ return val;
2568
+ }
2569
+ }
2570
+ return .null;
2571
+ }
2572
+
2573
+ fn cmdCopy(allocator: Allocator, inj: *Injection) JsonValue {
2574
+ if (inj.mode != M_VAL) return .null;
2575
+ const out = getprop(allocator, inj.dparent, JsonValue{ .string = inj.key }, .null) catch .null;
2576
+ _ = inj.setval(out, 0) catch {};
2577
+ return out;
2578
+ }
2579
+
2580
+ fn cmdDelete(inj: *Injection) JsonValue {
2581
+ _ = inj.setval(.null, 0) catch {};
2582
+ return .null;
2583
+ }
2584
+
2585
+ fn cmdKey(inj: *Injection) JsonValue {
2586
+ if (inj.mode != M_VAL) return .null;
2587
+ if (inj.parent == .object) {
2588
+ if (inj.parent.object.get(S_BKEY)) |keyspec| {
2589
+ _ = inj.parent.object.fetchOrderedRemove(S_BKEY);
2590
+ return getprop(inj.allocator, inj.dparent, keyspec, .null) catch .null;
2591
+ }
2592
+ if (inj.parent.object.get(S_BANNO)) |anno| {
2593
+ if (anno == .object) {
2594
+ if (anno.object.get(S_KEY)) |pkey| return pkey;
2595
+ }
2596
+ }
2597
+ }
2598
+ if (inj.path.len >= 2) return JsonValue{ .string = inj.path[inj.path.len - 2] };
2599
+ return .null;
2600
+ }
2601
+
2602
+ fn cmdMerge(allocator: Allocator, inj: *Injection, store: JsonValue) !JsonValue {
2603
+ if (inj.mode == M_KEYPRE) return JsonValue{ .string = inj.key };
2604
+
2605
+ if (inj.mode == M_KEYPOST) {
2606
+ const args = try getprop(allocator, inj.parent, JsonValue{ .string = inj.key }, .null);
2607
+
2608
+ // Remove $MERGE key from parent first.
2609
+ if (inj.parent == .object) _ = inj.parent.object.fetchOrderedRemove(inj.key);
2610
+
2611
+ // Clone parent AFTER removing (Go does Clone(inj.Parent) post-remove).
2612
+ // With *MapRef, the clone reads from the same pointer data.
2613
+ const parent_clone = try clone(allocator, inj.parent);
2614
+
2615
+ const merge_list_lr = try allocator.create(ListRef);
2616
+ merge_list_lr.* = .{ .data = ListData.init(allocator) };
2617
+ const merge_list = merge_list_lr;
2618
+ try merge_list.append(inj.parent);
2619
+
2620
+ if (args == .string and args.string.len == 0) {
2621
+ const top = getpropFromStore(store);
2622
+ if (top != .null) try merge_list.append(try clone(allocator, top));
2623
+ } else if (args == .array) {
2624
+ for (args.array.data.items) |item| {
2625
+ if (item != .null) try merge_list.append(item);
2626
+ }
2627
+ } else if (args != .null) {
2628
+ try merge_list.append(args);
2629
+ }
2630
+
2631
+ // Literals in parent have precedence.
2632
+ try merge_list.append(parent_clone);
2633
+ const merged = try merge(allocator, JsonValue{ .array = merge_list }, MAXDEPTH);
2634
+
2635
+ // Copy merge result INTO the existing *MapRef to preserve pointer identity.
2636
+ // Go's Merge modifies the first element in place; outer references see changes.
2637
+ if (merged == .object and inj.parent == .object) {
2638
+ // Clear existing entries and copy from merged result.
2639
+ const parent_map = inj.parent.object;
2640
+ // Remove all existing keys.
2641
+ const existing_keys = try keysof(allocator, inj.parent);
2642
+ if (existing_keys == .array) {
2643
+ for (existing_keys.array.data.items) |k| {
2644
+ if (k == .string) _ = parent_map.fetchOrderedRemove(k.string);
2645
+ }
2646
+ }
2647
+ // Copy in merged entries.
2648
+ var it = merged.object.iterator();
2649
+ while (it.next()) |kv| {
2650
+ try parent_map.put(kv.key_ptr.*, kv.value_ptr.*);
2651
+ }
2652
+ } else {
2653
+ inj.parent = merged;
2654
+ }
2655
+ return JsonValue{ .string = inj.key };
2656
+ }
2657
+
2658
+ return .null;
2659
+ }
2660
+
2661
+ fn cmdAnno(inj: *Injection) JsonValue {
2662
+ if (inj.parent == .object) _ = inj.parent.object.fetchOrderedRemove(S_BANNO);
2663
+ return .null;
2664
+ }
2665
+
2666
+ // ============================================================================
2667
+ // Validation commands — fire inside the injection pipeline when validate_mode.
2668
+ // ============================================================================
2669
+
2670
+ fn cmdValidateType(allocator: Allocator, inj: *Injection, tname: []const u8, tbit: i32) anyerror!JsonValue {
2671
+ if (inj.mode != M_VAL) return .null;
2672
+ const out = getprop(allocator, inj.dparent, JsonValue{ .string = inj.key }, .null) catch .null;
2673
+ const t = typify(out);
2674
+
2675
+ // $STRING: also reject empty strings.
2676
+ if (tbit == T_string) {
2677
+ if (0 == (@as(i64, T_string) & t)) {
2678
+ try inj.errs.append(try invalidTypeMsg(allocator, inj.path, tname, out));
2679
+ return .null;
2680
+ }
2681
+ if (out == .string and out.string.len == 0) {
2682
+ try inj.errs.append(try std.fmt.allocPrint(allocator, "Empty string at {s}", .{try pathifySlice(allocator, inj.path[1..])}));
2683
+ return .null;
2684
+ }
2685
+ _ = try inj.setval(out, 0);
2686
+ return out;
2687
+ }
2688
+
2689
+ if (0 == (@as(i64, tbit) & t)) {
2690
+ try inj.errs.append(try invalidTypeMsg(allocator, inj.path, tname, out));
2691
+ return .null;
2692
+ }
2693
+ _ = try inj.setval(out, 0);
2694
+ return out;
2695
+ }
2696
+
2697
+ fn cmdValidateAny(inj: *Injection) JsonValue {
2698
+ if (inj.mode != M_VAL) return .null;
2699
+ const out = getprop(inj.allocator, inj.dparent, JsonValue{ .string = inj.key }, .null) catch .null;
2700
+ _ = inj.setval(out, 0) catch {};
2701
+ return out;
2702
+ }
2703
+
2704
+ fn cmdValidateOne(allocator: Allocator, inj: *Injection, _: JsonValue) anyerror!JsonValue {
2705
+ if (inj.mode != M_VAL) return .null;
2706
+ if (inj.parent != .array) return .null;
2707
+
2708
+ // Skip remaining keys in the list.
2709
+ inj.key_i = inj.keys.len;
2710
+
2711
+ const parent_items = inj.parent.array.data.items;
2712
+ if (parent_items.len < 2) return .null;
2713
+
2714
+ // The data value to validate is inj.dparent itself — $ONE wraps the
2715
+ // current data, not a sub-slot of it. Mirrors the Rust / Go ports.
2716
+ const data_val = inj.dparent;
2717
+
2718
+ // Replace [$ONE, alt0, alt1, ...] in the grandparent with data_val.
2719
+ _ = try inj.setval(data_val, 2);
2720
+
2721
+ // Try each alternative.
2722
+ const alts = parent_items[1..];
2723
+ for (alts) |alt| {
2724
+ const terrs = std.ArrayList([]const u8).init(allocator);
2725
+ const terrs_ptr = try allocator.create(std.ArrayList([]const u8));
2726
+ terrs_ptr.* = terrs;
2727
+ _ = try validateWalk(allocator, alt, data_val, terrs_ptr, if (inj.path.len > 1) inj.path[1..] else inj.path);
2728
+ if (terrs_ptr.items.len == 0) return .null;
2729
+ }
2730
+
2731
+ // No match — build error message.
2732
+ var desc = std.ArrayList(u8).init(allocator);
2733
+ for (alts, 0..) |alt, i| {
2734
+ if (i > 0) try desc.appendSlice(", ");
2735
+ try desc.appendSlice(try stringify(allocator, alt, null));
2736
+ }
2737
+ const prefix = if (alts.len > 1) "one of " else "";
2738
+ try inj.errs.append(try invalidTypeMsg(allocator, inj.path, try std.fmt.allocPrint(allocator, "{s}{s}", .{ prefix, desc.items }), data_val));
2739
+ return .null;
2740
+ }
2741
+
2742
+ fn cmdValidateExactCmd(allocator: Allocator, inj: *Injection) anyerror!JsonValue {
2743
+ if (inj.mode != M_VAL) return .null;
2744
+ if (inj.parent != .array) return .null;
2745
+
2746
+ inj.key_i = inj.keys.len;
2747
+
2748
+ const parent_items = inj.parent.array.data.items;
2749
+ if (parent_items.len < 2) return .null;
2750
+
2751
+ // $EXACT wraps the current data value; data_val is inj.dparent itself,
2752
+ // not a sub-slot. Mirrors Rust / Go ports.
2753
+ const data_val = inj.dparent;
2754
+ _ = try inj.setval(data_val, 2);
2755
+
2756
+ const alts = parent_items[1..];
2757
+ for (alts) |alt| {
2758
+ const a = try toStdJson(allocator, alt);
2759
+ const b = try toStdJson(allocator, data_val);
2760
+ if (stdJsonEqual(a, b)) return .null;
2761
+ // Also try string comparison.
2762
+ const sa = try stringify(allocator, alt, null);
2763
+ const sb = try stringify(allocator, data_val, null);
2764
+ if (std.mem.eql(u8, sa, sb)) return .null;
2765
+ }
2766
+
2767
+ var desc = std.ArrayList(u8).init(allocator);
2768
+ for (alts, 0..) |alt, i| {
2769
+ if (i > 0) try desc.appendSlice(", ");
2770
+ try desc.appendSlice(try stringify(allocator, alt, null));
2771
+ }
2772
+ const prefix = if (alts.len > 1) "one of " else "";
2773
+ try inj.errs.append(try invalidTypeMsg(allocator, inj.path, try std.fmt.allocPrint(allocator, "exactly equal to {s}{s}", .{ prefix, desc.items }), data_val));
2774
+ return .null;
2775
+ }
2776
+
2777
+ fn cmdValidateChildCmd(allocator: Allocator, inj: *Injection, store: JsonValue) anyerror!JsonValue {
2778
+ _ = store;
2779
+ if (inj.mode == M_KEYPRE and inj.parent == .object) {
2780
+ // Map mode: expand $CHILD for each key in the data.
2781
+ const child = getprop(allocator, inj.parent, JsonValue{ .string = inj.key }, .null) catch .null;
2782
+ const pkey = if (inj.path.len >= 2) inj.path[inj.path.len - 2] else S_DTOP;
2783
+ const tval = getprop(allocator, inj.dparent, JsonValue{ .string = pkey }, .null) catch .null;
2784
+
2785
+ if (tval == .object) {
2786
+ // For each key in data, clone the child spec into the parent.
2787
+ const ckeys = try keysof(allocator, tval);
2788
+ if (ckeys == .array) {
2789
+ for (ckeys.array.data.items) |ck| {
2790
+ if (ck == .string) {
2791
+ try inj.parent.object.put(ck.string, try clone(allocator, child));
2792
+ // Append to keys for further processing.
2793
+ inj.keys = appendSlice(allocator, []const u8, inj.keys, ck.string) catch inj.keys;
2794
+ }
2795
+ }
2796
+ }
2797
+ } else if (tval != .null) {
2798
+ try inj.errs.append(try invalidTypeMsg(allocator, if (inj.path.len > 1) inj.path[0 .. inj.path.len - 1] else inj.path, S_object, tval));
2799
+ }
2800
+
2801
+ // Remove the $CHILD key.
2802
+ _ = inj.parent.object.fetchOrderedRemove(inj.key);
2803
+ return .null;
2804
+ }
2805
+
2806
+ if (inj.mode == M_VAL and inj.parent == .array) {
2807
+ // List mode: [$CHILD, template] — expand for each element.
2808
+ if (inj.parent.array.data.items.len < 2) return .null;
2809
+ const child = inj.parent.array.data.items[1];
2810
+ const dparent_val = inj.dparent;
2811
+
2812
+ if (dparent_val == .null) {
2813
+ inj.parent.array.data.items.len = 0;
2814
+ return .null;
2815
+ }
2816
+
2817
+ if (dparent_val != .array) {
2818
+ try inj.errs.append(try invalidTypeMsg(allocator, if (inj.path.len > 1) inj.path[0 .. inj.path.len - 1] else inj.path, S_list, dparent_val));
2819
+ return dparent_val;
2820
+ }
2821
+
2822
+ const dlen = dparent_val.array.data.items.len;
2823
+ inj.parent.array.data.items.len = 0;
2824
+ var li: usize = 0;
2825
+ while (li < dlen) : (li += 1) {
2826
+ try inj.parent.array.append(try clone(allocator, child));
2827
+ }
2828
+ inj.key_i = 0;
2829
+ return if (dlen > 0) dparent_val.array.data.items[0] else .null;
2830
+ }
2831
+
2832
+ return .null;
2833
+ }
2834
+
2835
+ // ============================================================================
2836
+ // $FORMAT — apply a named formatter to a child value.
2837
+ // Format: ["`$FORMAT`", "name", child]
2838
+ // ============================================================================
2839
+
2840
+ fn cmdFormat(allocator: Allocator, inj: *Injection, store: JsonValue) !JsonValue {
2841
+ if (inj.mode != M_VAL) return .null;
2842
+ if (inj.keys.len > 1) inj.keys = inj.keys[0..1];
2843
+
2844
+ if (inj.parent != .array or inj.parent.array.data.items.len < 3) return .null;
2845
+ const name_val = inj.parent.array.data.items[1];
2846
+ const child_raw = inj.parent.array.data.items[2];
2847
+
2848
+ const name = if (name_val == .string) name_val.string else "";
2849
+
2850
+ // Inject the child value first (resolve $COPY etc).
2851
+ const child = try injectChild(allocator, child_raw, store, inj);
2852
+
2853
+ // Find target node and key.
2854
+ const tkey = if (inj.path.len >= 2) inj.path[inj.path.len - 2] else S_DTOP;
2855
+ const target = if (inj.nodes.len >= 2)
2856
+ inj.nodes[inj.nodes.len - 2]
2857
+ else if (inj.nodes.len > 0)
2858
+ inj.nodes[inj.nodes.len - 1]
2859
+ else
2860
+ JsonValue{ .null = {} };
2861
+
2862
+ const out = try applyFormat(allocator, name, child, inj.errs);
2863
+ if (out == .null and !std.mem.eql(u8, name, "identity")) {
2864
+ // Unknown format or error → delete from target.
2865
+ if (target != .null) _ = delprop(allocator, target, JsonValue{ .string = tkey }) catch {};
2866
+ return .null;
2867
+ }
2868
+
2869
+ if (target != .null) _ = setprop(allocator, target, JsonValue{ .string = tkey }, out) catch {};
2870
+ return out;
2871
+ }
2872
+
2873
+ fn applyFormat(allocator: Allocator, name: []const u8, val: JsonValue, errs: *std.ArrayList([]const u8)) !JsonValue {
2874
+ if (std.mem.eql(u8, name, "upper")) return try walkFormat(allocator, val, fmtUpper);
2875
+ if (std.mem.eql(u8, name, "lower")) return try walkFormat(allocator, val, fmtLower);
2876
+ if (std.mem.eql(u8, name, "string")) return try walkFormat(allocator, val, fmtString);
2877
+ if (std.mem.eql(u8, name, "number")) return try walkFormat(allocator, val, fmtNumber);
2878
+ if (std.mem.eql(u8, name, "integer")) return try walkFormat(allocator, val, fmtInteger);
2879
+ if (std.mem.eql(u8, name, "identity")) return val;
2880
+ if (std.mem.eql(u8, name, "concat")) {
2881
+ if (val == .array) {
2882
+ var buf = std.ArrayList(u8).init(allocator);
2883
+ for (val.array.data.items) |item| {
2884
+ if (isnode(item)) continue;
2885
+ try buf.appendSlice(try fmtStr(allocator, item));
2886
+ }
2887
+ return JsonValue{ .string = buf.items };
2888
+ }
2889
+ return val;
2890
+ }
2891
+ const msg = try std.fmt.allocPrint(allocator, "$FORMAT: unknown format: {s}.", .{name});
2892
+ try errs.append(msg);
2893
+ return .null;
2894
+ }
2895
+
2896
+ const FormatFn = *const fn (Allocator, JsonValue) anyerror!JsonValue;
2897
+
2898
+ fn walkFormat(allocator: Allocator, val: JsonValue, fmt_fn: FormatFn) !JsonValue {
2899
+ if (val == .object) {
2900
+ const new_obj = try allocator.create(MapRef);
2901
+ new_obj.* = .{ .data = MapData.init(allocator) };
2902
+ var it = val.object.iterator();
2903
+ while (it.next()) |kv| {
2904
+ try new_obj.put(kv.key_ptr.*, try walkFormat(allocator, kv.value_ptr.*, fmt_fn));
2905
+ }
2906
+ return JsonValue{ .object = new_obj };
2907
+ }
2908
+ if (val == .array) {
2909
+ const new_arr_lr = try allocator.create(ListRef);
2910
+ new_arr_lr.* = .{ .data = try ListData.initCapacity(allocator, val.array.data.items.len) };
2911
+ const new_arr = new_arr_lr;
2912
+ for (val.array.data.items) |item| {
2913
+ try new_arr.append(try walkFormat(allocator, item, fmt_fn));
2914
+ }
2915
+ return JsonValue{ .array = new_arr };
2916
+ }
2917
+ return try fmt_fn(allocator, val);
2918
+ }
2919
+
2920
+ fn fmtStr(allocator: Allocator, val: JsonValue) ![]const u8 {
2921
+ return switch (val) {
2922
+ .null => "null",
2923
+ .bool => |b| if (b) "true" else "false",
2924
+ .string => |s| s,
2925
+ .integer => |i| try std.fmt.allocPrint(allocator, "{d}", .{i}),
2926
+ .float => |f| try std.fmt.allocPrint(allocator, "{d}", .{f}),
2927
+ else => "",
2928
+ };
2929
+ }
2930
+
2931
+ fn fmtUpper(allocator: Allocator, val: JsonValue) !JsonValue {
2932
+ const s = try fmtStr(allocator, val);
2933
+ var buf = try allocator.alloc(u8, s.len);
2934
+ for (s, 0..) |c, i| buf[i] = std.ascii.toUpper(c);
2935
+ return JsonValue{ .string = buf };
2936
+ }
2937
+
2938
+ fn fmtLower(allocator: Allocator, val: JsonValue) !JsonValue {
2939
+ const s = try fmtStr(allocator, val);
2940
+ var buf = try allocator.alloc(u8, s.len);
2941
+ for (s, 0..) |c, i| buf[i] = std.ascii.toLower(c);
2942
+ return JsonValue{ .string = buf };
2943
+ }
2944
+
2945
+ fn fmtString(allocator: Allocator, val: JsonValue) !JsonValue {
2946
+ return JsonValue{ .string = try fmtStr(allocator, val) };
2947
+ }
2948
+
2949
+ fn fmtNumber(allocator: Allocator, val: JsonValue) !JsonValue {
2950
+ _ = allocator;
2951
+ return switch (val) {
2952
+ .integer => val,
2953
+ .float => val,
2954
+ .string => |s| {
2955
+ if (std.fmt.parseFloat(f64, s)) |f| {
2956
+ if (f == @trunc(f)) return JsonValue{ .integer = @intFromFloat(f) };
2957
+ return JsonValue{ .float = f };
2958
+ } else |_| return JsonValue{ .integer = 0 };
2959
+ },
2960
+ else => JsonValue{ .integer = 0 },
2961
+ };
2962
+ }
2963
+
2964
+ fn fmtInteger(allocator: Allocator, val: JsonValue) !JsonValue {
2965
+ _ = allocator;
2966
+ return switch (val) {
2967
+ .integer => val,
2968
+ .float => |f| JsonValue{ .integer = @intFromFloat(@trunc(f)) },
2969
+ .string => |s| {
2970
+ if (std.fmt.parseFloat(f64, s)) |f| {
2971
+ return JsonValue{ .integer = @intFromFloat(@trunc(f)) };
2972
+ } else |_| return JsonValue{ .integer = 0 };
2973
+ },
2974
+ else => JsonValue{ .integer = 0 },
2975
+ };
2976
+ }
2977
+
2978
+ // ============================================================================
2979
+ // $EACH — iterate source data, apply child template per item.
2980
+ // Format: ["`$EACH`", "source-path", child-template]
2981
+ // ============================================================================
2982
+
2983
+ fn cmdEach(allocator: Allocator, inj: *Injection, store: JsonValue) !JsonValue {
2984
+ if (inj.mode != M_VAL) return .null;
2985
+ if (inj.keys.len > 1) inj.keys = inj.keys[0..1];
2986
+
2987
+ if (inj.parent != .array or inj.parent.array.data.items.len < 3) return .null;
2988
+ const srcpath_val = inj.parent.array.data.items[1];
2989
+ const child_tmpl = inj.parent.array.data.items[2];
2990
+
2991
+ const srcpath = if (srcpath_val == .string) srcpath_val.string else "";
2992
+
2993
+ // Resolve source data. Pass the injection so a srcpath of "." (or any
2994
+ // other dparent-relative reference) resolves against inj.dparent — TS /
2995
+ // Rust / Go pass the inj through here too, otherwise "." reads as the
2996
+ // root store and $EACH iterates the wrong node.
2997
+ const src = if (srcpath.len == 0)
2998
+ getpropFromStore(store)
2999
+ else
3000
+ try getpathInj(allocator, JsonValue{ .string = srcpath }, store, inj);
3001
+
3002
+ // Find target node and key.
3003
+ const tkey = if (inj.path.len >= 2) inj.path[inj.path.len - 2] else S_DTOP;
3004
+ const target = if (inj.nodes.len >= 2)
3005
+ inj.nodes[inj.nodes.len - 2]
3006
+ else if (inj.nodes.len > 0)
3007
+ inj.nodes[inj.nodes.len - 1]
3008
+ else
3009
+ JsonValue{ .null = {} };
3010
+
3011
+ // Build source value list and key list.
3012
+ var src_vals = std.ArrayList(JsonValue).init(allocator);
3013
+ var src_keys = std.ArrayList([]const u8).init(allocator);
3014
+ var tval_items = std.ArrayList(JsonValue).init(allocator);
3015
+
3016
+ if (islist(src)) {
3017
+ for (src.array.data.items, 0..) |src_item, idx| {
3018
+ try src_vals.append(src_item);
3019
+ try src_keys.append(try std.fmt.allocPrint(allocator, "{d}", .{idx}));
3020
+ try tval_items.append(try clone(allocator, child_tmpl));
3021
+ }
3022
+ } else if (ismap(src)) {
3023
+ const src_items = try items(allocator, src);
3024
+ if (src_items == .array) {
3025
+ for (src_items.array.data.items) |pair| {
3026
+ if (pair != .array or pair.array.data.items.len < 2) continue;
3027
+ const sk = if (pair.array.data.items[0] == .string) pair.array.data.items[0].string else "";
3028
+ try src_vals.append(pair.array.data.items[1]);
3029
+ try src_keys.append(sk);
3030
+ const cclone = try clone(allocator, child_tmpl);
3031
+ // Add $ANNO with $KEY for map sources.
3032
+ if (cclone == .object) {
3033
+ const anno = try allocator.create(MapRef);
3034
+ anno.* = .{ .data = MapData.init(allocator) };
3035
+ try anno.put(S_KEY, pair.array.data.items[0]);
3036
+ _ = try setprop(allocator, cclone, JsonValue{ .string = S_BANNO }, JsonValue{ .object = anno });
3037
+ }
3038
+ try tval_items.append(cclone);
3039
+ }
3040
+ }
3041
+ }
3042
+
3043
+ // Build result by injecting each template individually with per-item context.
3044
+ const result_lr = try allocator.create(ListRef);
3045
+ result_lr.* = .{ .data = ListData.init(allocator) };
3046
+
3047
+ for (src_vals.items, 0..) |src_item, idx| {
3048
+ const child_clone = tval_items.items[idx];
3049
+
3050
+ // Build per-item store: original store + $TOP = src_item.
3051
+ // Also merge root data keys for ancestor path access.
3052
+ const each_store = try allocator.create(MapRef);
3053
+ each_store.* = .{ .data = MapData.init(allocator) };
3054
+ if (store == .object) {
3055
+ var sit = store.object.iterator();
3056
+ while (sit.next()) |kv| try each_store.put(kv.key_ptr.*, kv.value_ptr.*);
3057
+ }
3058
+ const root_data = getpropFromStore(store);
3059
+ if (root_data == .object) {
3060
+ var rit = root_data.object.iterator();
3061
+ while (rit.next()) |rkv| {
3062
+ if (each_store.get(rkv.key_ptr.*) == null)
3063
+ try each_store.put(rkv.key_ptr.*, rkv.value_ptr.*);
3064
+ }
3065
+ }
3066
+ try each_store.put(S_DTOP, src_item);
3067
+
3068
+ const injected = try inject(allocator, child_clone, JsonValue{ .object = each_store }, null);
3069
+ try result_lr.append(injected);
3070
+ }
3071
+
3072
+ const result = JsonValue{ .array = result_lr };
3073
+ if (target != .null) _ = setprop(allocator, target, JsonValue{ .string = tkey }, result) catch {};
3074
+
3075
+ if (result_lr.data.items.len > 0) return result_lr.data.items[0];
3076
+ return .null;
3077
+ }
3078
+
3079
+ // ============================================================================
3080
+ // $PACK — convert source list/map to keyed map.
3081
+ // Format: map key `$PACK` with value ["source-path", child-spec]
3082
+ // ============================================================================
3083
+
3084
+ fn cmdPack(allocator: Allocator, inj: *Injection, store: JsonValue) !JsonValue {
3085
+ if (inj.mode != M_KEYPRE) return .null;
3086
+
3087
+ if (inj.parent != .object) return .null;
3088
+ const args_val = try getprop(allocator, inj.parent, JsonValue{ .string = inj.key }, .null);
3089
+ if (args_val != .array or args_val.array.data.items.len < 2) return .null;
3090
+
3091
+ const srcpath_val = args_val.array.data.items[0];
3092
+ const childspec_raw = args_val.array.data.items[1];
3093
+
3094
+ const srcpath = if (srcpath_val == .string) srcpath_val.string else "";
3095
+
3096
+ // Resolve source data.
3097
+ const src_raw = if (srcpath.len == 0)
3098
+ getpropFromStore(store)
3099
+ else
3100
+ try getpath(allocator, JsonValue{ .string = srcpath }, store);
3101
+
3102
+ // Normalize source to list.
3103
+ var src_list = std.ArrayList(JsonValue).init(allocator);
3104
+ var src_keys = std.ArrayList([]const u8).init(allocator);
3105
+ var src_is_map = false;
3106
+
3107
+ if (islist(src_raw)) {
3108
+ for (src_raw.array.data.items, 0..) |item, idx| {
3109
+ try src_list.append(item);
3110
+ try src_keys.append(try std.fmt.allocPrint(allocator, "{d}", .{idx}));
3111
+ }
3112
+ } else if (ismap(src_raw)) {
3113
+ src_is_map = true;
3114
+ const src_items = try items(allocator, src_raw);
3115
+ if (src_items == .array) {
3116
+ for (src_items.array.data.items) |pair| {
3117
+ if (pair != .array or pair.array.data.items.len < 2) continue;
3118
+ const k = if (pair.array.data.items[0] == .string) pair.array.data.items[0].string else "";
3119
+ try src_list.append(pair.array.data.items[1]);
3120
+ try src_keys.append(k);
3121
+ }
3122
+ }
3123
+ } else return .null;
3124
+
3125
+ // Extract $KEY path and $VAL from child spec.
3126
+ var childspec = try clone(allocator, childspec_raw);
3127
+ var keypath: ?[]const u8 = null;
3128
+ var child_val_spec = childspec;
3129
+
3130
+ if (childspec == .object) {
3131
+ if (childspec.object.get(S_BKEY)) |kp| {
3132
+ if (kp == .string) keypath = kp.string;
3133
+ _ = childspec.object.fetchOrderedRemove(S_BKEY);
3134
+ }
3135
+ if (childspec.object.get(S_BVAL)) |vspec| {
3136
+ child_val_spec = vspec;
3137
+ _ = childspec.object.fetchOrderedRemove(S_BVAL);
3138
+ }
3139
+ }
3140
+
3141
+ // Find target.
3142
+ const tkey = if (inj.path.len >= 2) inj.path[inj.path.len - 2] else S_DTOP;
3143
+ const target = if (inj.nodes.len >= 2)
3144
+ inj.nodes[inj.nodes.len - 2]
3145
+ else if (inj.nodes.len > 0)
3146
+ inj.nodes[inj.nodes.len - 1]
3147
+ else
3148
+ JsonValue{ .null = {} };
3149
+
3150
+ // Build the output map.
3151
+ const result_obj = try allocator.create(MapRef);
3152
+ result_obj.* = .{ .data = MapData.init(allocator) };
3153
+ for (src_list.items, 0..) |src_item, idx| {
3154
+ // Resolve the key for this item.
3155
+ var item_key: []const u8 = "";
3156
+ if (keypath) |kp| {
3157
+ // Key from source item field or injection.
3158
+ if (std.mem.startsWith(u8, kp, "`")) {
3159
+ // Backtick path: inject to resolve.
3160
+ const key_store = try allocator.create(MapRef);
3161
+ key_store.* = .{ .data = MapData.init(allocator) };
3162
+ if (store == .object) {
3163
+ var sit = store.object.iterator();
3164
+ while (sit.next()) |kv| try key_store.put(kv.key_ptr.*, kv.value_ptr.*);
3165
+ }
3166
+ try key_store.put(S_DTOP, src_item);
3167
+ const key_result = try inject(allocator, JsonValue{ .string = kp }, JsonValue{ .object = key_store }, null);
3168
+ if (key_result == .string) item_key = key_result.string;
3169
+ } else {
3170
+ // Direct property path.
3171
+ const kval = try getpath(allocator, JsonValue{ .string = kp }, src_item);
3172
+ if (kval == .string) item_key = kval.string;
3173
+ }
3174
+ } else {
3175
+ item_key = try std.fmt.allocPrint(allocator, "{d}", .{idx});
3176
+ }
3177
+ if (item_key.len == 0) continue;
3178
+
3179
+ // Clone the child template for this item.
3180
+ const child_clone = try clone(allocator, child_val_spec);
3181
+
3182
+ // Build per-item store.
3183
+ const item_store = try allocator.create(MapRef);
3184
+ item_store.* = .{ .data = MapData.init(allocator) };
3185
+ if (store == .object) {
3186
+ var sit = store.object.iterator();
3187
+ while (sit.next()) |kv| try item_store.put(kv.key_ptr.*, kv.value_ptr.*);
3188
+ }
3189
+ try item_store.put(S_DTOP, src_item);
3190
+
3191
+ // Add $ANNO with $KEY. For map sources, use the source map key
3192
+ // so `$KEY` in the template returns "a"/"b". For array sources,
3193
+ // use the resolved item_key (supports $KEY=$COPY → "a" not "0").
3194
+ if (child_clone == .object) {
3195
+ const anno = try allocator.create(MapRef);
3196
+ anno.* = .{ .data = MapData.init(allocator) };
3197
+ const anno_val = if (src_is_map)
3198
+ JsonValue{ .string = src_keys.items[idx] }
3199
+ else
3200
+ JsonValue{ .string = item_key };
3201
+ try anno.put(S_KEY, anno_val);
3202
+ _ = try setprop(allocator, child_clone, JsonValue{ .string = S_BANNO }, JsonValue{ .object = anno });
3203
+ }
3204
+
3205
+ // Build dpath for ancestor path resolution using the ORIGINAL store,
3206
+ // so `...v100` can resolve back to the root data.
3207
+ var dpath_list = std.ArrayList([]const u8).init(allocator);
3208
+ try dpath_list.append(S_DTOP);
3209
+ if (srcpath.len > 0) {
3210
+ var spit = std.mem.splitScalar(u8, srcpath, '.');
3211
+ while (spit.next()) |sp| try dpath_list.append(sp);
3212
+ }
3213
+ try dpath_list.append(try std.fmt.allocPrint(allocator, "$:{s}", .{tkey}));
3214
+ if (inj.path.len > 3) {
3215
+ const pkey = if (inj.path.len >= 3) inj.path[inj.path.len - 3] else S_DTOP;
3216
+ try dpath_list.append(try std.fmt.allocPrint(allocator, "$:{s}", .{pkey}));
3217
+ }
3218
+
3219
+ // Wrap: {tkey: {src_key: src_item}} so dparent descent works.
3220
+ const inner_wrap = try allocator.create(MapRef);
3221
+ inner_wrap.* = .{ .data = MapData.init(allocator) };
3222
+ try inner_wrap.put(src_keys.items[idx], src_item);
3223
+ const outer_wrap = try allocator.create(MapRef);
3224
+ outer_wrap.* = .{ .data = MapData.init(allocator) };
3225
+ try outer_wrap.put(tkey, JsonValue{ .object = inner_wrap });
3226
+
3227
+ // Build per-item store: merge original root data keys into the
3228
+ // store alongside $TOP = src_item. This way `$COPY` gets the item
3229
+ // (via $TOP) and `...v100` can find v100 as a direct store key.
3230
+ const pack_store = try allocator.create(MapRef);
3231
+ pack_store.* = .{ .data = MapData.init(allocator) };
3232
+ if (store == .object) {
3233
+ var sit = store.object.iterator();
3234
+ while (sit.next()) |kv| try pack_store.put(kv.key_ptr.*, kv.value_ptr.*);
3235
+ }
3236
+ // Merge root data keys directly into store for ancestor access.
3237
+ const root_data = getpropFromStore(store);
3238
+ if (root_data == .object) {
3239
+ var rit = root_data.object.iterator();
3240
+ while (rit.next()) |rkv| {
3241
+ // Don't override existing store keys.
3242
+ if (pack_store.get(rkv.key_ptr.*) == null) {
3243
+ try pack_store.put(rkv.key_ptr.*, rkv.value_ptr.*);
3244
+ }
3245
+ }
3246
+ }
3247
+ try pack_store.put(S_DTOP, src_item);
3248
+
3249
+ const injected = try inject(allocator, child_clone, JsonValue{ .object = pack_store }, null);
3250
+ try result_obj.put(item_key, injected);
3251
+ }
3252
+
3253
+ const result = JsonValue{ .object = result_obj };
3254
+
3255
+ // Remove the $PACK key from parent and set result on target.
3256
+ if (inj.parent == .object) _ = inj.parent.object.fetchOrderedRemove(inj.key);
3257
+ if (target != .null) _ = setprop(allocator, target, JsonValue{ .string = tkey }, result) catch {};
3258
+
3259
+ return .null; // Drop the transform key.
3260
+ }
3261
+
3262
+ // ============================================================================
3263
+ // $REF — reference another spec path (enables recursive templates).
3264
+ // Format: ["`$REF`", "spec-path"]
3265
+ // ============================================================================
3266
+
3267
+ // Recursively scan a node tree for the literal "`$REF`" string. Used by
3268
+ // cmdRef to detect self-recursive references and break the cycle before
3269
+ // the inject loop stack-overflows.
3270
+ fn scanForRef(val: JsonValue, found: *bool) void {
3271
+ if (found.*) return;
3272
+ switch (val) {
3273
+ .string => |s| {
3274
+ if (std.mem.eql(u8, s, "`$REF`")) found.* = true;
3275
+ },
3276
+ .array => |arr| {
3277
+ for (arr.data.items) |item| {
3278
+ scanForRef(item, found);
3279
+ if (found.*) return;
3280
+ }
3281
+ },
3282
+ .object => |obj| {
3283
+ var it = obj.iterator();
3284
+ while (it.next()) |kv| {
3285
+ scanForRef(kv.value_ptr.*, found);
3286
+ if (found.*) return;
3287
+ }
3288
+ },
3289
+ else => {},
3290
+ }
3291
+ }
3292
+
3293
+ fn cmdRef(allocator: Allocator, inj: *Injection, store: JsonValue) !JsonValue {
3294
+ if (inj.mode != M_VAL) return .null;
3295
+
3296
+ if (inj.parent != .array or inj.parent.array.data.items.len < 2) return .null;
3297
+ const refpath_val = inj.parent.array.data.items[1];
3298
+ if (refpath_val != .string) return .null;
3299
+ const refpath = refpath_val.string;
3300
+
3301
+ // Skip remaining keys.
3302
+ inj.key_i = inj.keys.len;
3303
+
3304
+ // Get the original spec from the store.
3305
+ const spec_val = if (store == .object) store.object.get(S_DSPEC) orelse .null else .null;
3306
+ if (spec_val == .null) return .null;
3307
+
3308
+ // Resolve the ref path within the spec.
3309
+ const ref_result = try getpath(allocator, JsonValue{ .string = refpath }, spec_val);
3310
+ if (ref_result == .null) {
3311
+ // Ref not found → delete from parent.
3312
+ const tkey = if (inj.path.len >= 2) inj.path[inj.path.len - 2] else S_DTOP;
3313
+ const target = if (inj.nodes.len >= 2) inj.nodes[inj.nodes.len - 2] else .null;
3314
+ if (target != .null) _ = delprop(allocator, target, JsonValue{ .string = tkey }) catch {};
3315
+ return .null;
3316
+ }
3317
+
3318
+ // Cycle break: if the resolved spec contains another `$REF` literal AND
3319
+ // there is no current data at the target slot, do NOT inject. This is the
3320
+ // self-recursive-ref case (e.g. spec {z:{y:["$REF","z"]}} with data {}).
3321
+ // Other ports do the same check; without it the inject loop recurses
3322
+ // infinitely into the same clone and the test process stack-overflows
3323
+ // (manifests as a SIGSEGV during the transform-ref test).
3324
+ var has_sub_ref = false;
3325
+ if (isnode(ref_result)) scanForRef(ref_result, &has_sub_ref);
3326
+
3327
+ // Clone the referenced spec and inject it with proper data context.
3328
+ const tref = try clone(allocator, ref_result);
3329
+
3330
+ // Compute paths following Go: tpath = path[:-1], cpath = path[:-3]
3331
+ const tpath = if (inj.path.len > 0) inj.path[0 .. inj.path.len - 1] else inj.path;
3332
+ const cpath = if (inj.path.len > 3) inj.path[0 .. inj.path.len - 3] else &[_][]const u8{};
3333
+
3334
+ // Resolve data at these paths.
3335
+ const tcur = if (cpath.len > 0) blk: {
3336
+ var joined = std.ArrayList(u8).init(allocator);
3337
+ for (cpath, 0..) |p, pi| {
3338
+ if (pi > 0) try joined.append('.');
3339
+ try joined.appendSlice(p);
3340
+ }
3341
+ break :blk try getpath(allocator, JsonValue{ .string = joined.items }, store);
3342
+ } else store;
3343
+
3344
+ // Build child injection with proper context.
3345
+ const lastPath = if (tpath.len > 0) tpath[tpath.len - 1] else S_DTOP;
3346
+ const tinj = try allocator.create(Injection);
3347
+ const tinj_nodes_src = if (inj.nodes.len > 1) inj.nodes[0 .. inj.nodes.len - 1] else inj.nodes[0..0];
3348
+ const tinj_nodes = try allocator.alloc(JsonValue, tinj_nodes_src.len);
3349
+ @memcpy(tinj_nodes, tinj_nodes_src);
3350
+ const tinj_dpath = try allocator.alloc([]const u8, cpath.len);
3351
+ @memcpy(tinj_dpath, cpath);
3352
+ tinj.* = Injection{
3353
+ .allocator = allocator,
3354
+ .mode = M_VAL,
3355
+ .key = lastPath,
3356
+ .val = tref,
3357
+ .parent = if (inj.nodes.len >= 2) inj.nodes[inj.nodes.len - 2] else .null,
3358
+ .base = inj.base,
3359
+ .dparent = tcur,
3360
+ .keys = try allocator.alloc([]const u8, 1),
3361
+ .path = tpath,
3362
+ .nodes = tinj_nodes,
3363
+ .dpath = tinj_dpath,
3364
+ .meta = inj.meta,
3365
+ .errs = inj.errs,
3366
+ };
3367
+ tinj.keys[0] = lastPath;
3368
+
3369
+ // Cycle break (matches the Rust / JS / Py / Go ports): if the resolved
3370
+ // ref contains another `$REF` literal AND there is no current data at
3371
+ // the target path, skip injection. Otherwise inject the cloned ref.
3372
+ //
3373
+ // Zig's getpath auto-unwraps store.$TOP, so an absolute path like
3374
+ // ["$TOP", "z", "p"] would re-traverse "$TOP" inside the data and hit
3375
+ // a dead end. Strip the leading "$TOP" before joining.
3376
+ const tpath_strip: []const []const u8 = if (tpath.len > 0 and std.mem.eql(u8, tpath[0], S_DTOP))
3377
+ tpath[1..]
3378
+ else
3379
+ tpath;
3380
+ const tval_at: JsonValue = blk2: {
3381
+ if (tpath_strip.len == 0) break :blk2 store;
3382
+ var joined = std.ArrayList(u8).init(allocator);
3383
+ for (tpath_strip, 0..) |p, pi| {
3384
+ if (pi > 0) joined.append('.') catch break :blk2 .null;
3385
+ joined.appendSlice(p) catch break :blk2 .null;
3386
+ }
3387
+ break :blk2 getpath(allocator, JsonValue{ .string = joined.items }, store) catch .null;
3388
+ };
3389
+ const skip_for_cycle = has_sub_ref and tval_at == .null;
3390
+ const rval: JsonValue = if (skip_for_cycle) .null else blk: {
3391
+ _ = try inject(allocator, tref, store, tinj);
3392
+ break :blk tinj.val;
3393
+ };
3394
+
3395
+ // Set the result on the grandparent.
3396
+ _ = try inj.setval(rval, 2);
3397
+
3398
+ // Adjust prior key index if grandparent is a list. Wrap on underflow:
3399
+ // setval(rval, 2) above just shrunk the grandparent list at path[-2], so
3400
+ // the caller's loop variable needs to step back one slot to re-visit the
3401
+ // index that the shift moved into the current position. The TS / JS / Py
3402
+ // / Go / Rust ports do `prior.keyI--` on a signed counter; here key_i is
3403
+ // usize, so we wrap with -%= 1 — the consumer loop bit-casts back through
3404
+ // isize so 0 -% 1 reads as -1 and `+ 1` lands back on the same index.
3405
+ if (inj.prior) |prior| {
3406
+ const gp = if (inj.nodes.len >= 2) inj.nodes[inj.nodes.len - 2] else .null;
3407
+ if (islist(gp)) {
3408
+ prior.key_i = prior.key_i -% 1;
3409
+ }
3410
+ }
3411
+
3412
+ return .null;
3413
+ }
3414
+
3415
+ // ============================================================================
3416
+ // $APPLY — apply a custom function (all tests are error cases).
3417
+ // Format: ["`$APPLY`", function, child]
3418
+ // ============================================================================
3419
+
3420
+ fn cmdApply(allocator: Allocator, inj: *Injection) !JsonValue {
3421
+ const ijname = "APPLY";
3422
+
3423
+ if (inj.mode == M_KEYPRE) {
3424
+ const msg = try std.fmt.allocPrint(allocator, "${s}: invalid placement as key, expected: value.", .{ijname});
3425
+ try inj.errs.append(msg);
3426
+ return .null;
3427
+ }
3428
+
3429
+ if (inj.mode == M_VAL) {
3430
+ // Check parent type — must be list.
3431
+ if (inj.parent != .array) {
3432
+ const msg = try std.fmt.allocPrint(allocator, "${s}: invalid placement in parent map, expected: list.", .{ijname});
3433
+ try inj.errs.append(msg);
3434
+ return .null;
3435
+ }
3436
+
3437
+ // Check arguments.
3438
+ if (inj.parent.array.data.items.len >= 2) {
3439
+ const arg = inj.parent.array.data.items[1];
3440
+ // In Zig JSON, functions don't exist, so any non-function argument is an error.
3441
+ const arg_type = typify(arg);
3442
+ const arg_type_name = typename(arg_type);
3443
+ const arg_str = try stringify(allocator, arg, 22);
3444
+ const msg = try std.fmt.allocPrint(allocator, "${s}: invalid argument: {s} ({s} at position 1) is not of type: function.", .{ ijname, arg_str, arg_type_name });
3445
+ try inj.errs.append(msg);
3446
+ }
3447
+
3448
+ // Delete from target.
3449
+ const tkey = if (inj.path.len >= 2) inj.path[inj.path.len - 2] else S_DTOP;
3450
+ const target = if (inj.nodes.len >= 2) inj.nodes[inj.nodes.len - 2] else .null;
3451
+ if (target != .null) _ = delprop(allocator, target, JsonValue{ .string = tkey }) catch {};
3452
+ }
3453
+
3454
+ return .null;
3455
+ }
3456
+
3457
+ // ============================================================================
3458
+ // Injection helpers — exposed for callers writing custom injectors.
3459
+ // ============================================================================
3460
+
3461
+ // Human placement name for an injection mode (mirrors TS PLACEMENT).
3462
+ fn placementName(mode: i32) []const u8 {
3463
+ return if (mode == M_VAL) "value" else "key";
3464
+ }
3465
+
3466
+ // Validate where an injection result may be placed: the current mode must be
3467
+ // one of `modes`, and (if `parent_types` is non-zero) the parent's type must
3468
+ // match it. Pushes a message to `inj.errs` and returns false on a violation.
3469
+ // Mirrors TS `checkPlacement`.
3470
+ pub fn checkPlacement(
3471
+ allocator: Allocator,
3472
+ modes: i32,
3473
+ ijname: []const u8,
3474
+ parent_types: i64,
3475
+ inj: *Injection,
3476
+ ) !bool {
3477
+ if ((modes & inj.mode) == 0) {
3478
+ var expected = std.ArrayList(u8).init(allocator);
3479
+ var first = true;
3480
+ for ([_]i32{ M_KEYPRE, M_KEYPOST, M_VAL }) |m| {
3481
+ if ((modes & m) != 0) {
3482
+ if (!first) try expected.append(',');
3483
+ try expected.appendSlice(placementName(m));
3484
+ first = false;
3485
+ }
3486
+ }
3487
+ const msg = try std.fmt.allocPrint(allocator, "${s}: invalid placement as {s}, expected: {s}.", .{ ijname, placementName(inj.mode), expected.items });
3488
+ try inj.errs.append(msg);
3489
+ return false;
3490
+ }
3491
+ if (parent_types != 0) {
3492
+ const ptype = typify(inj.parent);
3493
+ if ((parent_types & ptype) == 0) {
3494
+ const msg = try std.fmt.allocPrint(allocator, "${s}: invalid placement in parent {s}, expected: {s}.", .{ ijname, typename(ptype), typename(parent_types) });
3495
+ try inj.errs.append(msg);
3496
+ return false;
3497
+ }
3498
+ }
3499
+ return true;
3500
+ }
3501
+
3502
+ // Type-check the argument list passed to a transform-command injector.
3503
+ // Returns a list whose element 0 is either JSON null (all args OK) or an error
3504
+ // string, followed by the args that passed (up to the first mismatch).
3505
+ // Mirrors TS `injectorArgs`.
3506
+ pub fn injectorArgs(allocator: Allocator, arg_types: []const i64, args: []const JsonValue) !JsonValue {
3507
+ const found = try JsonValue.makeList(allocator);
3508
+ try found.array.append(.null);
3509
+ for (arg_types, 0..) |at, arg_i| {
3510
+ const arg: JsonValue = if (arg_i < args.len) args[arg_i] else .null;
3511
+ const arg_type = typify(arg);
3512
+ if ((at & arg_type) == 0) {
3513
+ const arg_str = try stringify(allocator, arg, 22);
3514
+ const msg = try std.fmt.allocPrint(allocator, "invalid argument: {s} ({s} at position {d}) is not of type: {s}.", .{ arg_str, typename(arg_type), 1 + arg_i, typename(at) });
3515
+ found.array.data.items[0] = JsonValue{ .string = msg };
3516
+ break;
3517
+ }
3518
+ try found.array.append(arg);
3519
+ }
3520
+ return found;
3521
+ }
3522
+
3523
+ // ============================================================================
3524
+ // injectChild — inject a child value using the parent injection context.
3525
+ // ============================================================================
3526
+
3527
+ fn injectChild(allocator: Allocator, child_raw: JsonValue, store: JsonValue, inj: *Injection) !JsonValue {
3528
+ // For simple cases: inject using the current context.
3529
+ var child_clone = try clone(allocator, child_raw);
3530
+
3531
+ // Build store with correct data context.
3532
+ const child_store = try allocator.create(MapRef);
3533
+ child_store.* = .{ .data = MapData.init(allocator) };
3534
+ if (store == .object) {
3535
+ var sit = store.object.iterator();
3536
+ while (sit.next()) |kv| try child_store.put(kv.key_ptr.*, kv.value_ptr.*);
3537
+ }
3538
+ // Set $TOP to the data parent so $COPY works.
3539
+ child_store.put(S_DTOP, inj.dparent) catch {};
3540
+
3541
+ child_clone = try inject(allocator, child_clone, JsonValue{ .object = child_store }, null);
3542
+ return child_clone;
3543
+ }
3544
+
3545
+ // ============================================================================
3546
+ // Transform — public API. Builds store and calls Inject.
3547
+ // ============================================================================
3548
+
3549
+ pub fn transform(allocator: Allocator, data: JsonValue, spec: JsonValue) !JsonValue {
3550
+ if (spec == .null) return spec;
3551
+
3552
+ const spec_clone = try clone(allocator, spec);
3553
+ const data_clone = if (data == .null) JsonValue{ .null = {} } else try clone(allocator, data);
3554
+
3555
+ // Store the original spec for $REF.
3556
+ const orig_spec = try clone(allocator, spec);
3557
+
3558
+ const store = try allocator.create(MapRef);
3559
+ store.* = .{ .data = MapData.init(allocator) };
3560
+ try store.put(S_DTOP, data_clone);
3561
+ try store.put(S_DSPEC, orig_spec);
3562
+ const store_val = JsonValue{ .object = store };
3563
+
3564
+ return try inject(allocator, spec_clone, store_val, null);
3565
+ }
3566
+
3567
+ // Transform with a modify callback applied after each injection step.
3568
+ pub fn transformModify(allocator: Allocator, data: JsonValue, spec: JsonValue, modify: ?ModifyFn) !JsonValue {
3569
+ if (spec == .null) return spec;
3570
+
3571
+ const spec_clone = try clone(allocator, spec);
3572
+ const data_clone = if (data == .null) JsonValue{ .null = {} } else try clone(allocator, data);
3573
+ const orig_spec = try clone(allocator, spec);
3574
+
3575
+ const store = try allocator.create(MapRef);
3576
+ store.* = .{ .data = MapData.init(allocator) };
3577
+ try store.put(S_DTOP, data_clone);
3578
+ try store.put(S_DSPEC, orig_spec);
3579
+ const store_val = JsonValue{ .object = store };
3580
+
3581
+ // Create a partial injection with modify set.
3582
+ const inj_init = try allocator.create(Injection);
3583
+ const empty_keys = try allocator.alloc([]const u8, 0);
3584
+ const empty_path = try allocator.alloc([]const u8, 0);
3585
+ const empty_nodes = try allocator.alloc(JsonValue, 0);
3586
+ const empty_dpath = try allocator.alloc([]const u8, 0);
3587
+ const errs = try allocator.create(std.ArrayList([]const u8));
3588
+ errs.* = std.ArrayList([]const u8).init(allocator);
3589
+ inj_init.* = Injection{
3590
+ .allocator = allocator,
3591
+ .mode = 0, // triggers root initialization in inject
3592
+ .modify = modify,
3593
+ .keys = empty_keys,
3594
+ .path = empty_path,
3595
+ .nodes = empty_nodes,
3596
+ .dpath = empty_dpath,
3597
+ .errs = errs,
3598
+ };
3599
+
3600
+ return try inject(allocator, spec_clone, store_val, inj_init);
3601
+ }
3602
+
3603
+ // ============================================================================
3604
+ // Helpers retained from previous implementation.
3605
+ // ============================================================================
3606
+
3607
+ fn stripCmdDigits(pathref: []const u8) []const u8 {
3608
+ if (pathref.len == 0 or pathref[0] != '$') return pathref;
3609
+ var end: usize = pathref.len;
3610
+ while (end > 1 and pathref[end - 1] >= '0' and pathref[end - 1] <= '9') end -= 1;
3611
+ return pathref[0..end];
3612
+ }
3613
+
3614
+ fn resolveSpecialEscapes(allocator: Allocator, pathref: []const u8) []const u8 {
3615
+ if (pathref.len <= 3) return pathref;
3616
+ if (std.mem.indexOf(u8, pathref, "$BT") == null and
3617
+ std.mem.indexOf(u8, pathref, "$DS") == null) return pathref;
3618
+ var result = std.ArrayList(u8).init(allocator);
3619
+ var i: usize = 0;
3620
+ while (i < pathref.len) {
3621
+ if (i + 3 <= pathref.len and std.mem.eql(u8, pathref[i .. i + 3], "$BT")) {
3622
+ result.append('`') catch {};
3623
+ i += 3;
3624
+ } else if (i + 3 <= pathref.len and std.mem.eql(u8, pathref[i .. i + 3], "$DS")) {
3625
+ result.append('$') catch {};
3626
+ i += 3;
3627
+ } else {
3628
+ result.append(pathref[i]) catch {};
3629
+ i += 1;
3630
+ }
3631
+ }
3632
+ return result.items;
3633
+ }
3634
+
3635
+ // (resolveRelativePath defined above near resolvePathOnly)
3636
+
3637
+ // ============================================================================
3638
+ // Validate — check data against a spec, collecting type errors.
3639
+ // Uses the transform/inject infrastructure with type-checking commands.
3640
+ // ============================================================================
3641
+
3642
+ pub fn validate(allocator: Allocator, data: JsonValue, spec: JsonValue) anyerror!struct { out: JsonValue, err: ?[]const u8 } {
3643
+ const spec_clone = try clone(allocator, spec);
3644
+ const data_clone = if (data == .null) JsonValue{ .null = {} } else try clone(allocator, data);
3645
+ const orig_spec = try clone(allocator, spec);
3646
+
3647
+ // Build store with data and spec.
3648
+ const store = try allocator.create(MapRef);
3649
+ store.* = .{ .data = MapData.init(allocator) };
3650
+ try store.put(S_DTOP, data_clone);
3651
+ try store.put(S_DSPEC, orig_spec);
3652
+ const store_val = JsonValue{ .object = store };
3653
+
3654
+ // Create root injection with validate_mode enabled.
3655
+ // This causes dispatchCmd to handle $STRING, $NUMBER, etc.
3656
+ const errs = try allocator.create(std.ArrayList([]const u8));
3657
+ errs.* = std.ArrayList([]const u8).init(allocator);
3658
+
3659
+ const inj_init = try allocator.create(Injection);
3660
+ inj_init.* = Injection{
3661
+ .allocator = allocator,
3662
+ .mode = 0, // triggers root init
3663
+ .validate_mode = true,
3664
+ .modify = validationModify,
3665
+ .keys = try allocator.alloc([]const u8, 0),
3666
+ .path = try allocator.alloc([]const u8, 0),
3667
+ .nodes = try allocator.alloc(JsonValue, 0),
3668
+ .dpath = try allocator.alloc([]const u8, 0),
3669
+ .errs = errs,
3670
+ };
3671
+
3672
+ const result = try inject(allocator, spec_clone, store_val, inj_init);
3673
+
3674
+ if (errs.items.len > 0) {
3675
+ var msg = std.ArrayList(u8).init(allocator);
3676
+ try msg.appendSlice("Invalid data: ");
3677
+ for (errs.items, 0..) |e, i| {
3678
+ if (i > 0) try msg.appendSlice(" | ");
3679
+ try msg.appendSlice(e);
3680
+ }
3681
+ return .{ .out = result, .err = msg.items };
3682
+ }
3683
+ return .{ .out = result, .err = null };
3684
+ }
3685
+
3686
+ // Validation modify callback — runs after each injection step.
3687
+ // Matches TS's makeValidation(false) behavior.
3688
+ fn validationModify(allocator: Allocator, _: JsonValue, key: []const u8, parent: JsonValue, inj: *Injection, _: JsonValue) void {
3689
+ // Get the actual data value at this path.
3690
+ const cval = getprop(allocator, inj.dparent, JsonValue{ .string = key }, .null) catch .null;
3691
+ if (cval == .null and !inj.exact_mode) return;
3692
+
3693
+ const pval = getprop(allocator, parent, JsonValue{ .string = key }, .null) catch .null;
3694
+ const ptype = typify(pval);
3695
+
3696
+ // Skip remaining $ command strings.
3697
+ if (0 < (@as(i64, T_string) & ptype) and pval == .string) {
3698
+ if (std.mem.indexOf(u8, pval.string, S_DS) != null) return;
3699
+ }
3700
+
3701
+ const ctype = typify(cval);
3702
+
3703
+ // Type mismatch between spec and data.
3704
+ if (ptype != ctype and pval != .null) {
3705
+ inj.errs.append(invalidTypeMsg(allocator, inj.path, typename(ptype), cval) catch "type error") catch {};
3706
+ return;
3707
+ }
3708
+
3709
+ if (ismap(cval)) {
3710
+ if (!ismap(pval)) return;
3711
+
3712
+ // Check for unexpected keys (closed-world assumption).
3713
+ const pkeys = keysof(allocator, pval) catch return;
3714
+ if (pkeys == .array and pkeys.array.data.items.len > 0) {
3715
+ // Check for $OPEN flag.
3716
+ if (pval == .object) {
3717
+ if (pval.object.get(S_BOPEN)) |ov| {
3718
+ if (ov == .bool and ov.bool) {
3719
+ // Open mode: copy data keys into pval so they appear
3720
+ // in the result. Drop the $OPEN marker afterwards.
3721
+ mergeIntoMap(pval, cval) catch {};
3722
+ _ = pval.object.fetchOrderedRemove(S_BOPEN);
3723
+ return;
3724
+ }
3725
+ }
3726
+ }
3727
+
3728
+ // Closed: report unexpected keys.
3729
+ const ckeys = keysof(allocator, cval) catch return;
3730
+ if (ckeys == .array) {
3731
+ var bad = std.ArrayList([]const u8).init(allocator);
3732
+ for (ckeys.array.data.items) |ck| {
3733
+ if (ck != .string) continue;
3734
+ if (!((haskey(allocator, pval, ck) catch false))) {
3735
+ bad.append(ck.string) catch {};
3736
+ }
3737
+ }
3738
+ if (bad.items.len > 0) {
3739
+ var badmsg = std.ArrayList(u8).init(allocator);
3740
+ badmsg.appendSlice("Unexpected keys at field ") catch {};
3741
+ badmsg.appendSlice(pathifySlice(allocator, if (inj.path.len > 1) inj.path[1..] else inj.path) catch "<root>") catch {};
3742
+ badmsg.appendSlice(": ") catch {};
3743
+ for (bad.items, 0..) |bk, bi| {
3744
+ if (bi > 0) badmsg.appendSlice(", ") catch {};
3745
+ badmsg.appendSlice(bk) catch {};
3746
+ }
3747
+ inj.errs.append(badmsg.items) catch {};
3748
+ }
3749
+ }
3750
+ } else {
3751
+ // Empty spec object {} = open. Copy data keys into pval so the
3752
+ // result map (which IS pval, since spec_clone is what inject
3753
+ // returns) sees the data.
3754
+ mergeIntoMap(pval, cval) catch {};
3755
+ }
3756
+ } else if (!isnode(cval)) {
3757
+ if (inj.exact_mode) {
3758
+ // Exact matching for select.
3759
+ const a = toStdJson(allocator, cval) catch return;
3760
+ const b = toStdJson(allocator, pval) catch return;
3761
+ if (!stdJsonEqual(a, b)) {
3762
+ const p = pathifySlice(allocator, if (inj.path.len > 1) inj.path[1..] else inj.path) catch "<root>";
3763
+ inj.errs.append(std.fmt.allocPrint(allocator, "Value at {s}: {s} should equal {s}.", .{ p, stringify(allocator, cval, null) catch "?", stringify(allocator, pval, null) catch "?" }) catch "exact match error") catch {};
3764
+ }
3765
+ } else {
3766
+ // Non-exact: copy data value into spec result.
3767
+ _ = setprop(allocator, parent, JsonValue{ .string = key }, cval) catch {};
3768
+ }
3769
+ }
3770
+ }
3771
+
3772
+ fn validateWalk(
3773
+ allocator: Allocator,
3774
+ spec_val: JsonValue,
3775
+ data_val: JsonValue,
3776
+ errs: *std.ArrayList([]const u8),
3777
+ path: []const []const u8,
3778
+ ) anyerror!JsonValue {
3779
+ // Type command strings: `$STRING`, `$NUMBER` etc resolve to type checks.
3780
+ if (spec_val == .string) {
3781
+ const s = spec_val.string;
3782
+ if (s.len > 2 and s[0] == '`' and s[s.len - 1] == '`') {
3783
+ const cmd = s[1 .. s.len - 1];
3784
+ if (std.mem.startsWith(u8, cmd, "$")) {
3785
+ return try validateTypeCheck(allocator, cmd, data_val, errs, path);
3786
+ }
3787
+ }
3788
+ // Non-command string: if it matches data, use data value.
3789
+ return data_val;
3790
+ }
3791
+
3792
+ if (spec_val == .array) {
3793
+ // Check for [$ONE, ...] and [$EXACT, ...].
3794
+ if (spec_val.array.data.items.len > 0) {
3795
+ const first = spec_val.array.data.items[0];
3796
+ if (first == .string) {
3797
+ if (std.mem.eql(u8, first.string, "`$ONE`")) {
3798
+ return try validateOne(allocator, spec_val, data_val, errs, path);
3799
+ }
3800
+ if (std.mem.eql(u8, first.string, "`$EXACT`")) {
3801
+ return try validateExact(allocator, spec_val, data_val, errs, path);
3802
+ }
3803
+ if (std.mem.eql(u8, first.string, "`$CHILD`")) {
3804
+ return try validateChild(allocator, spec_val, data_val, errs, path);
3805
+ }
3806
+ }
3807
+ }
3808
+ // Array spec: validate element by element.
3809
+ if (data_val != .array) {
3810
+ try errs.append(try invalidTypeMsg(allocator, path, S_list, data_val));
3811
+ return data_val;
3812
+ }
3813
+ return data_val;
3814
+ }
3815
+
3816
+ if (spec_val == .object) {
3817
+ if (data_val != .object) {
3818
+ // Check for $CHILD as map key.
3819
+ if (spec_val.object.get("`$CHILD`")) |child_spec| {
3820
+ return try validateChildMap(allocator, child_spec, data_val, errs, path);
3821
+ }
3822
+ try errs.append(try invalidTypeMsg(allocator, path, S_map, data_val));
3823
+ return data_val;
3824
+ }
3825
+
3826
+ // Map validation: check each spec key exists in data.
3827
+ const is_open = spec_val.object.get(S_BOPEN) != null;
3828
+ var result = try clone(allocator, data_val);
3829
+
3830
+ var it = spec_val.object.iterator();
3831
+ while (it.next()) |kv| {
3832
+ const k = kv.key_ptr.*;
3833
+ if (std.mem.eql(u8, k, S_BOPEN)) continue;
3834
+ if (k.len > 0 and k[0] == '`') continue; // Skip command keys.
3835
+
3836
+ var new_path = try allocator.alloc([]const u8, path.len + 1);
3837
+ @memcpy(new_path[0..path.len], path);
3838
+ new_path[path.len] = k;
3839
+
3840
+ const child_data = if (data_val.object.get(k)) |v| v else .null;
3841
+ const child_spec = kv.value_ptr.*;
3842
+ const child_result = try validateWalk(allocator, child_spec, child_data, errs, new_path);
3843
+ try result.object.put(k, child_result);
3844
+ }
3845
+
3846
+ // Check for unexpected keys (closed validation).
3847
+ if (!is_open and spec_val.object.count() > 0) {
3848
+ var dit = data_val.object.iterator();
3849
+ while (dit.next()) |dkv| {
3850
+ if (spec_val.object.get(dkv.key_ptr.*) == null) {
3851
+ try errs.append(try std.fmt.allocPrint(
3852
+ allocator,
3853
+ "Unexpected keys at field {s}: {s}",
3854
+ .{ try pathify(allocator, .null, 0, 0), dkv.key_ptr.* },
3855
+ ));
3856
+ }
3857
+ }
3858
+ }
3859
+
3860
+ return result;
3861
+ }
3862
+
3863
+ // Scalar spec: treat as default value, use data if available.
3864
+ if (data_val != .null) return data_val;
3865
+ return spec_val;
3866
+ }
3867
+
3868
+ fn validateTypeCheck(
3869
+ allocator: Allocator,
3870
+ cmd: []const u8,
3871
+ data_val: JsonValue,
3872
+ errs: *std.ArrayList([]const u8),
3873
+ path: []const []const u8,
3874
+ ) anyerror!JsonValue {
3875
+ const t = typify(data_val);
3876
+
3877
+ if (std.mem.eql(u8, cmd, "$STRING")) {
3878
+ if (0 == (@as(i64, T_string) & t)) {
3879
+ try errs.append(try invalidTypeMsg(allocator, path, S_string, data_val));
3880
+ return .null;
3881
+ }
3882
+ if (data_val == .string and data_val.string.len == 0) {
3883
+ const p = try pathifySlice(allocator, path);
3884
+ try errs.append(try std.fmt.allocPrint(allocator, "Empty string at {s}", .{p}));
3885
+ return .null;
3886
+ }
3887
+ return data_val;
3888
+ }
3889
+ if (std.mem.eql(u8, cmd, "$NUMBER")) {
3890
+ if (0 == (@as(i64, T_number) & t)) {
3891
+ try errs.append(try invalidTypeMsg(allocator, path, S_number, data_val));
3892
+ return .null;
3893
+ }
3894
+ return data_val;
3895
+ }
3896
+ if (std.mem.eql(u8, cmd, "$INTEGER")) {
3897
+ if (0 == (@as(i64, T_integer) & t)) {
3898
+ try errs.append(try invalidTypeMsg(allocator, path, S_integer, data_val));
3899
+ return .null;
3900
+ }
3901
+ return data_val;
3902
+ }
3903
+ if (std.mem.eql(u8, cmd, "$BOOLEAN")) {
3904
+ if (0 == (@as(i64, T_boolean) & t)) {
3905
+ try errs.append(try invalidTypeMsg(allocator, path, S_boolean, data_val));
3906
+ return .null;
3907
+ }
3908
+ return data_val;
3909
+ }
3910
+ if (std.mem.eql(u8, cmd, "$OBJECT") or std.mem.eql(u8, cmd, "$MAP")) {
3911
+ if (0 == (@as(i64, T_map) & t)) {
3912
+ try errs.append(try invalidTypeMsg(allocator, path, S_map, data_val));
3913
+ return .null;
3914
+ }
3915
+ return data_val;
3916
+ }
3917
+ if (std.mem.eql(u8, cmd, "$ARRAY") or std.mem.eql(u8, cmd, "$LIST")) {
3918
+ if (0 == (@as(i64, T_list) & t)) {
3919
+ try errs.append(try invalidTypeMsg(allocator, path, S_list, data_val));
3920
+ return .null;
3921
+ }
3922
+ return data_val;
3923
+ }
3924
+ if (std.mem.eql(u8, cmd, "$ANY")) {
3925
+ return data_val;
3926
+ }
3927
+ if (std.mem.eql(u8, cmd, "$NULL")) {
3928
+ if (data_val != .null) {
3929
+ try errs.append(try invalidTypeMsg(allocator, path, S_null, data_val));
3930
+ return .null;
3931
+ }
3932
+ return data_val;
3933
+ }
3934
+ // Unknown command: pass through.
3935
+ return data_val;
3936
+ }
3937
+
3938
+ fn validateOne(
3939
+ allocator: Allocator,
3940
+ spec_val: JsonValue,
3941
+ data_val: JsonValue,
3942
+ errs: *std.ArrayList([]const u8),
3943
+ path: []const []const u8,
3944
+ ) anyerror!JsonValue {
3945
+ const alts = spec_val.array.data.items[1..];
3946
+ for (alts) |alt| {
3947
+ var terrs = std.ArrayList([]const u8).init(allocator);
3948
+ _ = try validateWalk(allocator, alt, data_val, &terrs, path);
3949
+ if (terrs.items.len == 0) return data_val;
3950
+ }
3951
+ // No match.
3952
+ const p = try pathifySlice(allocator, path);
3953
+ try errs.append(try std.fmt.allocPrint(allocator, "Expected one of alternatives at {s}, but found {s}.", .{ p, typename(typify(data_val)) }));
3954
+ return data_val;
3955
+ }
3956
+
3957
+ fn validateExact(
3958
+ allocator: Allocator,
3959
+ spec_val: JsonValue,
3960
+ data_val: JsonValue,
3961
+ errs: *std.ArrayList([]const u8),
3962
+ path: []const []const u8,
3963
+ ) anyerror!JsonValue {
3964
+ const alts = spec_val.array.data.items[1..];
3965
+ for (alts) |alt| {
3966
+ // Deep equality check via conversion to std.json for comparison.
3967
+ const a = try toStdJson(allocator, alt);
3968
+ const b = try toStdJson(allocator, data_val);
3969
+ if (stdJsonEqual(a, b)) return data_val;
3970
+ // Also try string comparison.
3971
+ const sa = try stringify(allocator, alt, null);
3972
+ const sb = try stringify(allocator, data_val, null);
3973
+ if (std.mem.eql(u8, sa, sb)) return data_val;
3974
+ }
3975
+ const p = try pathifySlice(allocator, path);
3976
+ try errs.append(try std.fmt.allocPrint(allocator, "Expected exactly equal at {s}, but found {s}.", .{ p, typename(typify(data_val)) }));
3977
+ return data_val;
3978
+ }
3979
+
3980
+ fn validateChild(
3981
+ allocator: Allocator,
3982
+ spec_val: JsonValue,
3983
+ data_val: JsonValue,
3984
+ errs: *std.ArrayList([]const u8),
3985
+ path: []const []const u8,
3986
+ ) anyerror!JsonValue {
3987
+ // [$CHILD, template] — validate each element of data array.
3988
+ if (spec_val.array.data.items.len < 2) return data_val;
3989
+ const tmpl = spec_val.array.data.items[1];
3990
+
3991
+ if (data_val != .array) {
3992
+ try errs.append(try invalidTypeMsg(allocator, path, S_list, data_val));
3993
+ return data_val;
3994
+ }
3995
+
3996
+ for (data_val.array.data.items, 0..) |item, idx| {
3997
+ var new_path = try allocator.alloc([]const u8, path.len + 1);
3998
+ @memcpy(new_path[0..path.len], path);
3999
+ new_path[path.len] = try std.fmt.allocPrint(allocator, "{d}", .{idx});
4000
+ _ = try validateWalk(allocator, tmpl, item, errs, new_path);
4001
+ }
4002
+ return data_val;
4003
+ }
4004
+
4005
+ fn validateChildMap(
4006
+ allocator: Allocator,
4007
+ child_spec: JsonValue,
4008
+ data_val: JsonValue,
4009
+ errs: *std.ArrayList([]const u8),
4010
+ path: []const []const u8,
4011
+ ) anyerror!JsonValue {
4012
+ if (data_val != .object) {
4013
+ try errs.append(try invalidTypeMsg(allocator, path, S_map, data_val));
4014
+ return data_val;
4015
+ }
4016
+ var it = data_val.object.iterator();
4017
+ while (it.next()) |kv| {
4018
+ var new_path = try allocator.alloc([]const u8, path.len + 1);
4019
+ @memcpy(new_path[0..path.len], path);
4020
+ new_path[path.len] = kv.key_ptr.*;
4021
+ _ = try validateWalk(allocator, child_spec, kv.value_ptr.*, errs, new_path);
4022
+ }
4023
+ return data_val;
4024
+ }
4025
+
4026
+ fn invalidTypeMsg(allocator: Allocator, path: []const []const u8, expected: []const u8, val: JsonValue) anyerror![]const u8 {
4027
+ const p = try pathifySlice(allocator, path);
4028
+ const actual = typename(typify(val));
4029
+ const val_str = try stringify(allocator, val, 33);
4030
+ if (path.len == 0) {
4031
+ if (val == .null) {
4032
+ return try std.fmt.allocPrint(allocator, "Expected {s}, but found no value.", .{expected});
4033
+ }
4034
+ return try std.fmt.allocPrint(allocator, "Expected {s}, but found {s}: {s}.", .{ expected, actual, val_str });
4035
+ }
4036
+ return try std.fmt.allocPrint(allocator, "Expected {s}, field {s} to be {s}, but found {s}: {s}.", .{ expected, p, expected, actual, val_str });
4037
+ }
4038
+
4039
+ fn pathifySlice(allocator: Allocator, path: []const []const u8) anyerror![]const u8 {
4040
+ if (path.len == 0) return "<root>";
4041
+ var buf = std.ArrayList(u8).init(allocator);
4042
+ for (path, 0..) |p, i| {
4043
+ if (i > 0) try buf.append('.');
4044
+ try buf.appendSlice(p);
4045
+ }
4046
+ return buf.items;
4047
+ }
4048
+
4049
+ fn stdJsonEqual(a: StdJsonValue, b: StdJsonValue) bool {
4050
+ // Use the runner's equality check logic.
4051
+ const TagType = std.meta.Tag(StdJsonValue);
4052
+ const tag_a: TagType = a;
4053
+ const tag_b: TagType = b;
4054
+
4055
+ if ((tag_a == .integer or tag_a == .float) and (tag_b == .integer or tag_b == .float)) {
4056
+ const fa: f64 = if (tag_a == .integer) @floatFromInt(a.integer) else a.float;
4057
+ const fb: f64 = if (tag_b == .integer) @floatFromInt(b.integer) else b.float;
4058
+ return fa == fb;
4059
+ }
4060
+ if (tag_a != tag_b) return false;
4061
+ return switch (a) {
4062
+ .null => true,
4063
+ .bool => |av| av == b.bool,
4064
+ .integer => |av| av == b.integer,
4065
+ .float => |av| av == b.float,
4066
+ .string => |av| std.mem.eql(u8, av, b.string),
4067
+ .number_string => |av| std.mem.eql(u8, av, b.number_string),
4068
+ .array => |av| {
4069
+ const bv = b.array;
4070
+ if (av.items.len != bv.items.len) return false;
4071
+ for (av.items, bv.items) |ai, bi| {
4072
+ if (!stdJsonEqual(ai, bi)) return false;
4073
+ }
4074
+ return true;
4075
+ },
4076
+ .object => |av| {
4077
+ const bv = b.object;
4078
+ if (av.count() != bv.count()) return false;
4079
+ var it = av.iterator();
4080
+ while (it.next()) |kv| {
4081
+ const bval = bv.get(kv.key_ptr.*) orelse return false;
4082
+ if (!stdJsonEqual(kv.value_ptr.*, bval)) return false;
4083
+ }
4084
+ return true;
4085
+ },
4086
+ };
4087
+ }
4088
+
4089
+ // ============================================================================
4090
+ // Select — filter children matching a query.
4091
+ // ============================================================================
4092
+
4093
+ pub fn select(allocator: Allocator, children: JsonValue, query: JsonValue) anyerror!JsonValue {
4094
+ if (!isnode(children)) return try JsonValue.makeList(allocator);
4095
+
4096
+ // Normalize children: add $KEY for map/list items.
4097
+ var child_list = std.ArrayList(JsonValue).init(allocator);
4098
+
4099
+ if (ismap(children)) {
4100
+ const pairs = try items(allocator, children);
4101
+ if (pairs == .array) {
4102
+ for (pairs.array.data.items) |pair| {
4103
+ if (pair != .array or pair.array.data.items.len < 2) continue;
4104
+ const k = pair.array.data.items[0];
4105
+ var child = pair.array.data.items[1];
4106
+ if (ismap(child)) {
4107
+ try child.object.put("$KEY", k);
4108
+ }
4109
+ try child_list.append(child);
4110
+ }
4111
+ }
4112
+ } else if (islist(children)) {
4113
+ for (children.array.data.items, 0..) |child_raw, idx| {
4114
+ var child = child_raw;
4115
+ if (ismap(child)) {
4116
+ try child.object.put("$KEY", JsonValue{ .integer = @intCast(idx) });
4117
+ }
4118
+ try child_list.append(child);
4119
+ }
4120
+ }
4121
+
4122
+ // For each child, try validating with exact matching against the query.
4123
+ const result_lr = try allocator.create(ListRef);
4124
+ result_lr.* = .{ .data = ListData.init(allocator) };
4125
+
4126
+ for (child_list.items) |child| {
4127
+ var terrs = std.ArrayList([]const u8).init(allocator);
4128
+ const q = try clone(allocator, query);
4129
+
4130
+ // Mark all maps in query as open.
4131
+ _ = try walk(allocator, q, markOpen, null, MAXDEPTH);
4132
+
4133
+ // Validate with exact matching.
4134
+ _ = try validateExactMatch(allocator, q, child, &terrs, &[_][]const u8{});
4135
+
4136
+ if (terrs.items.len == 0) {
4137
+ try result_lr.append(child);
4138
+ }
4139
+ }
4140
+
4141
+ return JsonValue{ .array = result_lr };
4142
+ }
4143
+
4144
+ fn markOpen(_: Allocator, _: ?[]const u8, val: JsonValue, _: JsonValue, _: []const []const u8) anyerror!JsonValue {
4145
+ if (val == .object) {
4146
+ val.object.put(S_BOPEN, JsonValue{ .bool = true }) catch {};
4147
+ }
4148
+ return val;
4149
+ }
4150
+
4151
+ fn validateExactMatch(
4152
+ allocator: Allocator,
4153
+ spec_val: JsonValue,
4154
+ data_val: JsonValue,
4155
+ errs: *std.ArrayList([]const u8),
4156
+ path: []const []const u8,
4157
+ ) anyerror!JsonValue {
4158
+ // Operator handling for select queries. Operators ($AND/$OR/$NOT/$CMP)
4159
+ // are combined AND-style with the rest of the spec keys at the same
4160
+ // level — every operator must pass AND every regular key must match
4161
+ // (open-world for the non-operator slots).
4162
+ if (spec_val == .object) {
4163
+ // Run each operator that appears, accumulating errors. Count whether
4164
+ // there are any non-operator keys; if none, skip the key-by-key
4165
+ // match step (which would otherwise require data to be an object).
4166
+ var has_plain_key = false;
4167
+ var it = spec_val.object.iterator();
4168
+ while (it.next()) |kv| {
4169
+ const k = kv.key_ptr.*;
4170
+ if (std.mem.eql(u8, k, S_BOPEN)) continue;
4171
+ if (k.len > 0 and k[0] == '`') continue;
4172
+ has_plain_key = true;
4173
+ break;
4174
+ }
4175
+
4176
+ if (spec_val.object.get("`$AND`")) |terms| {
4177
+ _ = try selectAnd(allocator, terms, data_val, errs, path);
4178
+ }
4179
+ if (spec_val.object.get("`$OR`")) |terms| {
4180
+ _ = try selectOr(allocator, terms, data_val, errs, path);
4181
+ }
4182
+ if (spec_val.object.get("`$NOT`")) |term| {
4183
+ _ = try selectNot(allocator, term, data_val, errs, path);
4184
+ }
4185
+ if (spec_val.object.get("`$GT`")) |term| {
4186
+ _ = try selectCmp(allocator, "$GT", term, data_val, errs, path);
4187
+ }
4188
+ if (spec_val.object.get("`$LT`")) |term| {
4189
+ _ = try selectCmp(allocator, "$LT", term, data_val, errs, path);
4190
+ }
4191
+ if (spec_val.object.get("`$GTE`")) |term| {
4192
+ _ = try selectCmp(allocator, "$GTE", term, data_val, errs, path);
4193
+ }
4194
+ if (spec_val.object.get("`$LTE`")) |term| {
4195
+ _ = try selectCmp(allocator, "$LTE", term, data_val, errs, path);
4196
+ }
4197
+ if (spec_val.object.get("`$LIKE`")) |term| {
4198
+ _ = try selectCmp(allocator, "$LIKE", term, data_val, errs, path);
4199
+ }
4200
+
4201
+ if (!has_plain_key) return data_val;
4202
+
4203
+ if (data_val != .object) {
4204
+ try errs.append("type mismatch: expected object");
4205
+ return data_val;
4206
+ }
4207
+
4208
+ // Match each non-operator spec key against data (open: extra data
4209
+ // keys are OK). Group A/B-aware: a missing key in data fails the
4210
+ // match unconditionally, even if the spec slot is null. Otherwise
4211
+ // a query like {value:null} would spuriously match objects that
4212
+ // don't have a "value" key.
4213
+ var it2 = spec_val.object.iterator();
4214
+ while (it2.next()) |kv| {
4215
+ const k = kv.key_ptr.*;
4216
+ if (std.mem.eql(u8, k, S_BOPEN)) continue;
4217
+ if (k.len > 0 and k[0] == '`') continue;
4218
+
4219
+ var new_path = try allocator.alloc([]const u8, path.len + 1);
4220
+ @memcpy(new_path[0..path.len], path);
4221
+ new_path[path.len] = k;
4222
+
4223
+ if (data_val.object.get(k)) |child_data| {
4224
+ _ = try validateExactMatch(allocator, kv.value_ptr.*, child_data, errs, new_path);
4225
+ } else {
4226
+ const p = try pathifySlice(allocator, new_path);
4227
+ try errs.append(try std.fmt.allocPrint(
4228
+ allocator,
4229
+ "Missing key at {s}.",
4230
+ .{p},
4231
+ ));
4232
+ }
4233
+ }
4234
+ return data_val;
4235
+ }
4236
+
4237
+ if (spec_val == .array) {
4238
+ if (spec_val.array.data.items.len > 0) {
4239
+ const first = spec_val.array.data.items[0];
4240
+ if (first == .string) {
4241
+ if (std.mem.eql(u8, first.string, "`$ONE`"))
4242
+ return try validateOne(allocator, spec_val, data_val, errs, path);
4243
+ if (std.mem.eql(u8, first.string, "`$EXACT`"))
4244
+ return try validateExact(allocator, spec_val, data_val, errs, path);
4245
+ }
4246
+ }
4247
+ // Plain array spec: compare to data element-by-element. Length and
4248
+ // every element must match (recurse via validateExactMatch). A non-
4249
+ // array data fails immediately.
4250
+ if (data_val != .array) {
4251
+ const p = try pathifySlice(allocator, path);
4252
+ try errs.append(try std.fmt.allocPrint(
4253
+ allocator,
4254
+ "Value at {s}: {s} should be a list.",
4255
+ .{ p, try stringify(allocator, data_val, null) },
4256
+ ));
4257
+ return data_val;
4258
+ }
4259
+ if (spec_val.array.data.items.len != data_val.array.data.items.len) {
4260
+ const p = try pathifySlice(allocator, path);
4261
+ try errs.append(try std.fmt.allocPrint(
4262
+ allocator,
4263
+ "Value at {s}: list length {d} should equal {d}.",
4264
+ .{ p, data_val.array.data.items.len, spec_val.array.data.items.len },
4265
+ ));
4266
+ return data_val;
4267
+ }
4268
+ for (spec_val.array.data.items, data_val.array.data.items, 0..) |sv, dv, i| {
4269
+ const idx_buf = try std.fmt.allocPrint(allocator, "{d}", .{i});
4270
+ var new_path = try allocator.alloc([]const u8, path.len + 1);
4271
+ @memcpy(new_path[0..path.len], path);
4272
+ new_path[path.len] = idx_buf;
4273
+ _ = try validateExactMatch(allocator, sv, dv, errs, new_path);
4274
+ }
4275
+ return data_val;
4276
+ }
4277
+
4278
+ if (spec_val == .string) {
4279
+ const s = spec_val.string;
4280
+ if (s.len > 2 and s[0] == '`' and s[s.len - 1] == '`') {
4281
+ const cmd = s[1 .. s.len - 1];
4282
+ if (std.mem.startsWith(u8, cmd, "$")) {
4283
+ return try validateTypeCheck(allocator, cmd, data_val, errs, path);
4284
+ }
4285
+ }
4286
+ }
4287
+
4288
+ // Exact scalar match.
4289
+ const a = try toStdJson(allocator, spec_val);
4290
+ const b = try toStdJson(allocator, data_val);
4291
+ if (!stdJsonEqual(a, b)) {
4292
+ const p = try pathifySlice(allocator, path);
4293
+ try errs.append(try std.fmt.allocPrint(
4294
+ allocator,
4295
+ "Value at {s}: {s} should equal {s}.",
4296
+ .{ p, try stringify(allocator, data_val, null), try stringify(allocator, spec_val, null) },
4297
+ ));
4298
+ }
4299
+ return data_val;
4300
+ }
4301
+
4302
+ fn selectAnd(
4303
+ allocator: Allocator,
4304
+ terms: JsonValue,
4305
+ data_val: JsonValue,
4306
+ errs: *std.ArrayList([]const u8),
4307
+ path: []const []const u8,
4308
+ ) anyerror!JsonValue {
4309
+ if (terms != .array) return data_val;
4310
+ for (terms.array.data.items) |term| {
4311
+ var terrs = std.ArrayList([]const u8).init(allocator);
4312
+ _ = try validateExactMatch(allocator, term, data_val, &terrs, path);
4313
+ if (terrs.items.len > 0) {
4314
+ try errs.append("AND condition failed");
4315
+ return data_val;
4316
+ }
4317
+ }
4318
+ return data_val;
4319
+ }
4320
+
4321
+ fn selectOr(
4322
+ allocator: Allocator,
4323
+ terms: JsonValue,
4324
+ data_val: JsonValue,
4325
+ errs: *std.ArrayList([]const u8),
4326
+ path: []const []const u8,
4327
+ ) anyerror!JsonValue {
4328
+ if (terms != .array) return data_val;
4329
+ for (terms.array.data.items) |term| {
4330
+ var terrs = std.ArrayList([]const u8).init(allocator);
4331
+ _ = try validateExactMatch(allocator, term, data_val, &terrs, path);
4332
+ if (terrs.items.len == 0) return data_val;
4333
+ }
4334
+ try errs.append("OR: no condition matched");
4335
+ return data_val;
4336
+ }
4337
+
4338
+ fn selectNot(
4339
+ allocator: Allocator,
4340
+ term: JsonValue,
4341
+ data_val: JsonValue,
4342
+ errs: *std.ArrayList([]const u8),
4343
+ path: []const []const u8,
4344
+ ) anyerror!JsonValue {
4345
+ var terrs = std.ArrayList([]const u8).init(allocator);
4346
+ _ = try validateExactMatch(allocator, term, data_val, &terrs, path);
4347
+ if (terrs.items.len == 0) {
4348
+ try errs.append("NOT: condition should not have matched");
4349
+ }
4350
+ return data_val;
4351
+ }
4352
+
4353
+ fn selectCmp(
4354
+ allocator: Allocator,
4355
+ op: []const u8,
4356
+ term: JsonValue,
4357
+ data_val: JsonValue,
4358
+ errs: *std.ArrayList([]const u8),
4359
+ path: []const []const u8,
4360
+ ) anyerror!JsonValue {
4361
+ _ = path;
4362
+ const pf = toFloat(data_val);
4363
+ const tf = toFloat(term);
4364
+
4365
+ var pass = false;
4366
+ if (std.mem.eql(u8, op, "$GT")) {
4367
+ if (pf != null and tf != null) pass = pf.? > tf.?;
4368
+ } else if (std.mem.eql(u8, op, "$LT")) {
4369
+ if (pf != null and tf != null) pass = pf.? < tf.?;
4370
+ } else if (std.mem.eql(u8, op, "$GTE")) {
4371
+ if (pf != null and tf != null) pass = pf.? >= tf.?;
4372
+ } else if (std.mem.eql(u8, op, "$LTE")) {
4373
+ if (pf != null and tf != null) pass = pf.? <= tf.?;
4374
+ } else if (std.mem.eql(u8, op, "$LIKE")) {
4375
+ if (term == .string) {
4376
+ const subject = try stringify(allocator, data_val, null);
4377
+ pass = regexMatch(term.string, subject);
4378
+ }
4379
+ }
4380
+
4381
+ if (!pass) {
4382
+ try errs.append(try std.fmt.allocPrint(allocator, "CMP {s} failed", .{op}));
4383
+ }
4384
+ return data_val;
4385
+ }
4386
+
4387
+ fn toFloat(val: JsonValue) ?f64 {
4388
+ return switch (val) {
4389
+ .integer => |i| @floatFromInt(i),
4390
+ .float => |f| f,
4391
+ else => null,
4392
+ };
4393
+ }
4394
+
4395
+ // Regex matching via the in-tree pure-Zig Thompson NFA engine.
4396
+ fn regexMatch(pattern: []const u8, subject: []const u8) bool {
4397
+ var regex = _re_engine.compile(std.heap.page_allocator, pattern) orelse return false;
4398
+ defer regex.deinit();
4399
+ return regex.isMatch(subject);
4400
+ }