@voxgig/sdkgen 3.5.1 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/cmp/AgentGuideTop.js +17 -0
  3. package/dist/cmp/AgentGuideTop.js.map +1 -1
  4. package/dist/cmp/ExternalTarget.js +1 -1
  5. package/dist/cmp/ExternalTarget.js.map +1 -1
  6. package/dist/cmp/Readme.js +2 -0
  7. package/dist/cmp/Readme.js.map +1 -1
  8. package/dist/cmp/ReadmeStation.d.ts +2 -0
  9. package/dist/cmp/ReadmeStation.js +57 -0
  10. package/dist/cmp/ReadmeStation.js.map +1 -0
  11. package/dist/helpers/naming.d.ts +6 -1
  12. package/dist/helpers/naming.js +156 -5
  13. package/dist/helpers/naming.js.map +1 -1
  14. package/dist/helpers/opShape.js +72 -0
  15. package/dist/helpers/opShape.js.map +1 -1
  16. package/dist/helpers/packageMeta.d.ts +2 -1
  17. package/dist/helpers/packageMeta.js +57 -20
  18. package/dist/helpers/packageMeta.js.map +1 -1
  19. package/dist/sdkgen.d.ts +3 -3
  20. package/dist/sdkgen.js +63 -18
  21. package/dist/sdkgen.js.map +1 -1
  22. package/dist/testkit.d.ts +39 -0
  23. package/dist/testkit.js +663 -0
  24. package/dist/testkit.js.map +1 -0
  25. package/dist/tsconfig.tsbuildinfo +1 -1
  26. package/dist/utility.d.ts +1 -1
  27. package/dist/utility.js +16 -2
  28. package/dist/utility.js.map +1 -1
  29. package/package.json +32 -8
  30. package/project/.sdk/src/cmp/c/Config_c.ts +34 -13
  31. package/project/.sdk/src/cmp/c/Test_c.ts +5 -7
  32. package/project/.sdk/src/cmp/clojure/Test_clojure.ts +3 -7
  33. package/project/.sdk/src/cmp/cpp/Config_cpp.ts +9 -46
  34. package/project/.sdk/src/cmp/cpp/Test_cpp.ts +4 -7
  35. package/project/.sdk/src/cmp/csharp/Config_csharp.ts +7 -1
  36. package/project/.sdk/src/cmp/csharp/Package_csharp.ts +1 -1
  37. package/project/.sdk/src/cmp/csharp/Test_csharp.ts +5 -7
  38. package/project/.sdk/src/cmp/dart/Config_dart.ts +14 -2
  39. package/project/.sdk/src/cmp/dart/Test_dart.ts +3 -4
  40. package/project/.sdk/src/cmp/dart/fragment/Config.data.fragment.dart +5 -0
  41. package/project/.sdk/src/cmp/dart/fragment/Config.fragment.dart +6 -0
  42. package/project/.sdk/src/cmp/dart/fragment/Main.fragment.dart +13 -4
  43. package/project/.sdk/src/cmp/elixir/Config_elixir.ts +12 -2
  44. package/project/.sdk/src/cmp/elixir/Package_elixir.ts +42 -3
  45. package/project/.sdk/src/cmp/elixir/Test_elixir.ts +5 -6
  46. package/project/.sdk/src/cmp/go/Config_go.ts +8 -1
  47. package/project/.sdk/src/cmp/go/EntityTypes_go.ts +1 -1
  48. package/project/.sdk/src/cmp/go/Entity_go.ts +1 -1
  49. package/project/.sdk/src/cmp/go/Gitignore_go.ts +6 -0
  50. package/project/.sdk/src/cmp/go/Main_go.ts +2 -2
  51. package/project/.sdk/src/cmp/go/Package_go.ts +1 -1
  52. package/project/.sdk/src/cmp/go/ReadmeExamplesTest_go.ts +59 -6
  53. package/project/.sdk/src/cmp/go/ReadmeExplanation_go.ts +1 -1
  54. package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +1 -1
  55. package/project/.sdk/src/cmp/go/ReadmeInstall_go.ts +1 -1
  56. package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +1 -1
  57. package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +1 -1
  58. package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +1 -1
  59. package/project/.sdk/src/cmp/go/ReadmeTopTest_go.ts +1 -1
  60. package/project/.sdk/src/cmp/go/Test_go.ts +6 -8
  61. package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +6 -2
  62. package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +6 -2
  63. package/project/.sdk/src/cmp/java/Config_java.ts +8 -1
  64. package/project/.sdk/src/cmp/java/Test_java.ts +4 -7
  65. package/project/.sdk/src/cmp/js/Config_js.ts +9 -1
  66. package/project/.sdk/src/cmp/js/Package_js.ts +1 -1
  67. package/project/.sdk/src/cmp/js/Test_js.ts +4 -7
  68. package/project/.sdk/src/cmp/js/fragment/Config.data.fragment.js +7 -0
  69. package/project/.sdk/src/cmp/js/fragment/Config.fragment.js +8 -0
  70. package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +33 -5
  71. package/project/.sdk/src/cmp/kotlin/Config_kotlin.ts +8 -1
  72. package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +4 -7
  73. package/project/.sdk/src/cmp/lean/Test_lean.ts +3 -3
  74. package/project/.sdk/src/cmp/lua/Config_lua.ts +11 -2
  75. package/project/.sdk/src/cmp/lua/Package_lua.ts +26 -3
  76. package/project/.sdk/src/cmp/lua/Test_lua.ts +5 -7
  77. package/project/.sdk/src/cmp/ocaml/Test_ocaml.ts +3 -7
  78. package/project/.sdk/src/cmp/perl/Config_perl.ts +8 -60
  79. package/project/.sdk/src/cmp/perl/Package_perl.ts +1 -1
  80. package/project/.sdk/src/cmp/perl/Test_perl.ts +5 -7
  81. package/project/.sdk/src/cmp/php/Config_php.ts +11 -2
  82. package/project/.sdk/src/cmp/php/EntityTypes_php.ts +13 -2
  83. package/project/.sdk/src/cmp/php/Main_php.ts +25 -0
  84. package/project/.sdk/src/cmp/php/Package_php.ts +2 -2
  85. package/project/.sdk/src/cmp/php/Test_php.ts +5 -7
  86. package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +23 -6
  87. package/project/.sdk/src/cmp/py/Config_py.ts +11 -2
  88. package/project/.sdk/src/cmp/py/Main_py.ts +17 -7
  89. package/project/.sdk/src/cmp/py/Package_py.ts +2 -2
  90. package/project/.sdk/src/cmp/py/Test_py.ts +5 -7
  91. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +23 -6
  92. package/project/.sdk/src/cmp/py-data/Main_py-data.ts +14 -19
  93. package/project/.sdk/src/cmp/rb/Config_rb.ts +7 -1
  94. package/project/.sdk/src/cmp/rb/Package_rb.ts +3 -3
  95. package/project/.sdk/src/cmp/rb/ReadmeInstall_rb.ts +1 -1
  96. package/project/.sdk/src/cmp/rb/Test_rb.ts +5 -7
  97. package/project/.sdk/src/cmp/rust/Config_rust.ts +5 -2
  98. package/project/.sdk/src/cmp/rust/Test_rust.ts +5 -7
  99. package/project/.sdk/src/cmp/scala/Test_scala.ts +5 -2
  100. package/project/.sdk/src/cmp/seneca-provider/Gitignore_seneca-provider.ts +161 -0
  101. package/project/.sdk/src/cmp/seneca-provider/Main_seneca-provider.ts +20 -11
  102. package/project/.sdk/src/cmp/swift/Config_swift.ts +8 -54
  103. package/project/.sdk/src/cmp/swift/Package_swift.ts +52 -10
  104. package/project/.sdk/src/cmp/swift/Test_swift.ts +5 -7
  105. package/project/.sdk/src/cmp/ts/Config_ts.ts +9 -1
  106. package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +5 -2
  107. package/project/.sdk/src/cmp/ts/Entity_ts.ts +8 -2
  108. package/project/.sdk/src/cmp/ts/Package_ts.ts +1 -1
  109. package/project/.sdk/src/cmp/ts/Test_ts.ts +8 -7
  110. package/project/.sdk/src/cmp/ts/fragment/Config.data.fragment.ts +7 -0
  111. package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +8 -0
  112. package/project/.sdk/src/cmp/ts/fragment/Entity.fragment.ts +1 -1
  113. package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +12 -4
  114. package/project/.sdk/src/cmp/zig/Test_zig.ts +3 -7
  115. package/project/.sdk/tm/c/Makefile +6 -1
  116. package/project/.sdk/tm/c/utility/make_options.c +12 -1
  117. package/project/.sdk/tm/c/utility/make_point.c +64 -3
  118. package/project/.sdk/tm/clojure/src/sdk/core.clj +49 -14
  119. package/project/.sdk/tm/cpp/utility/pipeline.hpp +64 -4
  120. package/project/.sdk/tm/csharp/feature/TestFeature.cs +36 -2
  121. package/project/.sdk/tm/csharp/utility/Fetcher.cs +23 -5
  122. package/project/.sdk/tm/csharp/utility/MakeOptions.cs +13 -0
  123. package/project/.sdk/tm/csharp/utility/MakePoint.cs +65 -2
  124. package/project/.sdk/tm/dart/lib/feature/test/TestFeature.dart +34 -4
  125. package/project/.sdk/tm/dart/lib/utility/FetcherUtility.dart +9 -0
  126. package/project/.sdk/tm/dart/lib/utility/MakeOptionsUtility.dart +17 -0
  127. package/project/.sdk/tm/dart/lib/utility/MakePointUtility.dart +48 -2
  128. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +109 -13
  129. package/project/.sdk/tm/elixir/test/feature_test.exs +19 -0
  130. package/project/.sdk/tm/elixir/test/primary_utility_test.exs +72 -0
  131. package/project/.sdk/tm/go/feature/test_feature.go +34 -2
  132. package/project/.sdk/tm/go/test/primary_utility_test.go +42 -20
  133. package/project/.sdk/tm/go/test/runner_test.go +1 -1
  134. package/project/.sdk/tm/go/utility/fetcher.go +14 -0
  135. package/project/.sdk/tm/go/utility/make_options.go +31 -4
  136. package/project/.sdk/tm/go/utility/make_point.go +66 -2
  137. package/project/.sdk/tm/java/feature/TestFeature.java +42 -2
  138. package/project/.sdk/tm/java/utility/Fetcher.java +11 -1
  139. package/project/.sdk/tm/java/utility/MakeOptions.java +11 -0
  140. package/project/.sdk/tm/java/utility/MakePoint.java +61 -2
  141. package/project/.sdk/tm/js/src/feature/test/TestFeature.js +22 -3
  142. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +20 -2
  143. package/project/.sdk/tm/js/src/utility/MakePointUtility.js +72 -2
  144. package/project/.sdk/tm/kotlin/feature/TestFeature.kt +31 -2
  145. package/project/.sdk/tm/kotlin/utility/Fetcher.kt +10 -1
  146. package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +11 -0
  147. package/project/.sdk/tm/kotlin/utility/MakePoint.kt +58 -2
  148. package/project/.sdk/tm/lean/src/SdkUtility.lean +28 -0
  149. package/project/.sdk/tm/lean/test/TPrimaryUtility.lean +13 -2
  150. package/project/.sdk/tm/lua/utility/make_options.lua +44 -0
  151. package/project/.sdk/tm/lua/utility/make_point.lua +65 -2
  152. package/project/.sdk/tm/ocaml/sdk_runtime.ml +40 -2
  153. package/project/.sdk/tm/perl/utility/fetcher.pm +10 -1
  154. package/project/.sdk/tm/perl/utility/make_options.pm +36 -0
  155. package/project/.sdk/tm/perl/utility/make_point.pm +55 -2
  156. package/project/.sdk/tm/php/feature/TestFeature.php +30 -1
  157. package/project/.sdk/tm/php/test/PipelineTest.php +20 -0
  158. package/project/.sdk/tm/php/utility/Fetcher.php +12 -1
  159. package/project/.sdk/tm/php/utility/MakeOptions.php +58 -0
  160. package/project/.sdk/tm/php/utility/MakePoint.php +49 -1
  161. package/project/.sdk/tm/py/pkg/utility/fetcher.py +13 -1
  162. package/project/.sdk/tm/py/pkg/utility/make_options.py +23 -0
  163. package/project/.sdk/tm/py/pkg/utility/make_point.py +56 -2
  164. package/project/.sdk/tm/rb/utility/make_options.rb +18 -0
  165. package/project/.sdk/tm/rb/utility/make_point.rb +42 -2
  166. package/project/.sdk/tm/rust/tests/common/mod.rs +1 -1
  167. package/project/.sdk/tm/rust/tests/feature_test.rs +27 -0
  168. package/project/.sdk/tm/rust/utility/fetcher.rs +8 -0
  169. package/project/.sdk/tm/rust/utility/make_options.rs +15 -0
  170. package/project/.sdk/tm/rust/utility/make_point.rs +69 -2
  171. package/project/.sdk/tm/scala/feature/TestFeature.scala +36 -1
  172. package/project/.sdk/tm/scala/utility/Make.scala +57 -3
  173. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TestFeature.swift +29 -1
  174. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Fetcher.swift +24 -1
  175. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Make.swift +51 -2
  176. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +12 -0
  177. package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +22 -3
  178. package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +20 -2
  179. package/project/.sdk/tm/ts/src/utility/MakePointUtility.ts +72 -2
  180. package/project/.sdk/tm/ts/test/utility/Corpus.test.ts +85 -0
  181. package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +10 -17
  182. package/project/.sdk/tm/zig/core/utility.zig +66 -3
  183. package/project/sdkgen-package.json +1 -2
  184. package/src/cmp/AgentGuideTop.ts +18 -0
  185. package/src/cmp/ExternalTarget.ts +1 -1
  186. package/src/cmp/Readme.ts +2 -0
  187. package/src/cmp/ReadmeStation.ts +69 -0
  188. package/src/helpers/naming.ts +172 -5
  189. package/src/helpers/opShape.ts +85 -0
  190. package/src/helpers/packageMeta.ts +59 -20
  191. package/src/sdkgen.ts +70 -20
  192. package/src/testkit.ts +863 -0
  193. package/src/utility.ts +17 -2
  194. package/testkit.d.ts +3 -0
  195. package/testkit.js +12 -0
  196. package/project/.sdk/model/target/haskell.aontu +0 -72
  197. package/project/.sdk/src/cmp/haskell/Config_haskell.ts +0 -98
  198. package/project/.sdk/src/cmp/haskell/Entity_haskell.ts +0 -13
  199. package/project/.sdk/src/cmp/haskell/Gitignore_haskell.ts +0 -27
  200. package/project/.sdk/src/cmp/haskell/Main_haskell.ts +0 -123
  201. package/project/.sdk/src/cmp/haskell/Package_haskell.ts +0 -60
  202. package/project/.sdk/src/cmp/haskell/ReadmeEntity_haskell.ts +0 -186
  203. package/project/.sdk/src/cmp/haskell/ReadmeExamplesTest_haskell.ts +0 -135
  204. package/project/.sdk/src/cmp/haskell/ReadmeExplanation_haskell.ts +0 -48
  205. package/project/.sdk/src/cmp/haskell/ReadmeHowto_haskell.ts +0 -168
  206. package/project/.sdk/src/cmp/haskell/ReadmeInstall_haskell.ts +0 -51
  207. package/project/.sdk/src/cmp/haskell/ReadmeIntro_haskell.ts +0 -67
  208. package/project/.sdk/src/cmp/haskell/ReadmeModel_haskell.ts +0 -162
  209. package/project/.sdk/src/cmp/haskell/ReadmeOptions_haskell.ts +0 -74
  210. package/project/.sdk/src/cmp/haskell/ReadmeQuick_haskell.ts +0 -241
  211. package/project/.sdk/src/cmp/haskell/ReadmeRef_haskell.ts +0 -408
  212. package/project/.sdk/src/cmp/haskell/ReadmeTopHowto_haskell.ts +0 -31
  213. package/project/.sdk/src/cmp/haskell/ReadmeTopQuick_haskell.ts +0 -104
  214. package/project/.sdk/src/cmp/haskell/ReadmeTopTest_haskell.ts +0 -80
  215. package/project/.sdk/src/cmp/haskell/Test_haskell.ts +0 -300
  216. package/project/.sdk/src/cmp/haskell/tsconfig.json +0 -15
  217. package/project/.sdk/src/cmp/haskell/utility_haskell.ts +0 -166
  218. package/project/.sdk/tm/haskell/LICENSE +0 -21
  219. package/project/.sdk/tm/haskell/Makefile +0 -22
  220. package/project/.sdk/tm/haskell/VERSION +0 -1
  221. package/project/.sdk/tm/haskell/src/SdkFeatures.hs +0 -1440
  222. package/project/.sdk/tm/haskell/src/SdkHelpers.hs +0 -337
  223. package/project/.sdk/tm/haskell/src/SdkJson.hs +0 -111
  224. package/project/.sdk/tm/haskell/src/SdkRuntime.hs +0 -1219
  225. package/project/.sdk/tm/haskell/src/SdkTypes.hs +0 -195
  226. package/project/.sdk/tm/haskell/src/VoxgigStruct.hs +0 -2299
  227. package/project/.sdk/tm/haskell/src/Vregex.hs +0 -237
  228. package/project/.sdk/tm/haskell/src/feature/README.md +0 -5
  229. package/project/.sdk/tm/haskell/src/feature/audit/.gitkeep +0 -0
  230. package/project/.sdk/tm/haskell/src/feature/base/.gitkeep +0 -0
  231. package/project/.sdk/tm/haskell/src/feature/cache/.gitkeep +0 -0
  232. package/project/.sdk/tm/haskell/src/feature/clienttrack/.gitkeep +0 -0
  233. package/project/.sdk/tm/haskell/src/feature/debug/.gitkeep +0 -0
  234. package/project/.sdk/tm/haskell/src/feature/idempotency/.gitkeep +0 -0
  235. package/project/.sdk/tm/haskell/src/feature/log/.gitkeep +0 -0
  236. package/project/.sdk/tm/haskell/src/feature/metrics/.gitkeep +0 -0
  237. package/project/.sdk/tm/haskell/src/feature/netsim/.gitkeep +0 -0
  238. package/project/.sdk/tm/haskell/src/feature/paging/.gitkeep +0 -0
  239. package/project/.sdk/tm/haskell/src/feature/proxy/.gitkeep +0 -0
  240. package/project/.sdk/tm/haskell/src/feature/ratelimit/.gitkeep +0 -0
  241. package/project/.sdk/tm/haskell/src/feature/rbac/.gitkeep +0 -0
  242. package/project/.sdk/tm/haskell/src/feature/retry/.gitkeep +0 -0
  243. package/project/.sdk/tm/haskell/src/feature/streaming/.gitkeep +0 -0
  244. package/project/.sdk/tm/haskell/src/feature/telemetry/.gitkeep +0 -0
  245. package/project/.sdk/tm/haskell/src/feature/test/.gitkeep +0 -0
  246. package/project/.sdk/tm/haskell/src/feature/timeout/.gitkeep +0 -0
  247. package/project/.sdk/tm/haskell/test/Harness.hs +0 -281
  248. package/project/.sdk/tm/haskell/test/Runner.hs +0 -47
  249. package/project/.sdk/tm/haskell/test/StructCorpus.hs +0 -449
  250. package/project/.sdk/tm/haskell/test/TCustomUtility.hs +0 -38
  251. package/project/.sdk/tm/haskell/test/TFeature.hs +0 -794
  252. package/project/.sdk/tm/haskell/test/TNetsim.hs +0 -50
  253. package/project/.sdk/tm/haskell/test/TPipeline.hs +0 -334
  254. package/project/.sdk/tm/haskell/test/TPrimaryUtility.hs +0 -386
  255. package/project/.sdk/tm/haskell/test/Testutil.hs +0 -59
@@ -1,300 +0,0 @@
1
- import {
2
- KIT,
3
- getModelPath
4
- } from '@voxgig/apidef'
5
-
6
- import type {
7
- ModelEntity
8
- } from '@voxgig/apidef'
9
-
10
- import { cmp, each, Folder, File, Content } from '@voxgig/sdkgen'
11
-
12
- import { hsVarName } from './utility_haskell'
13
- import { ReadmeExamplesTest } from './ReadmeExamplesTest_haskell'
14
-
15
-
16
- // test/SdkGenTests.hs — model-driven per-entity tests: an instance test, a
17
- // CRUD basic-flow test driven through the in-memory mock (test mode), and a
18
- // direct() call test against an injected system.fetch mock. Only ops the
19
- // entity actually defines are exercised.
20
- const Test = cmp(function Test(props: any) {
21
- const { model } = props.ctx$
22
- const { target } = props
23
-
24
- const entity = getModelPath(model, `main.${KIT}.entity`)
25
-
26
- Folder({ name: 'test' }, () => {
27
-
28
- // Structural gate over the documented Haskell examples (emits
29
- // test/TReadmeExamples.hs); wired into genTests below so it runs in the
30
- // standard Runner.
31
- ReadmeExamplesTest({ target })
32
-
33
- File({ name: 'SdkGenTests.' + target.ext }, () => {
34
-
35
- let calls = ''
36
- let defs = ''
37
-
38
- each(entity, (e: any) => {
39
- const fn = hsVarName(e.name)
40
- const ops = Object.keys(e.op || {})
41
- const hasCreate = ops.includes('create')
42
- const hasList = ops.includes('list')
43
- const hasLoad = ops.includes('load')
44
- const hasUpdate = ops.includes('update')
45
- const hasRemove = ops.includes('remove')
46
-
47
- // Pick a text field to mutate in update (first non-id field with a
48
- // string value in the new-ref data, else "name").
49
- let updField = 'name'
50
- try {
51
- const nf = e.fields || {}
52
- const cand = Object.keys(nf).find((k) => k !== 'id' && !k.endsWith('$'))
53
- if (cand) updField = cand
54
- } catch (_e) { }
55
-
56
- const instFn = `${fn}InstanceTest`
57
- const basicFn = `${fn}BasicTest`
58
- const directFn = `${fn}DirectTest`
59
-
60
- calls += ` ${instFn} c\n`
61
- calls += ` ${basicFn} c\n`
62
- calls += ` ${directFn} c\n`
63
-
64
- defs += `
65
- ${instFn} :: Counters -> IO ()
66
- ${instFn} c = runTest c "${e.name}.instance" $ do
67
- sdk <- C.testSdk0
68
- ent <- C.${fn} sdk VNoval
69
- pure (eName ent == "${e.name}")
70
-
71
- ${basicFn} :: Counters -> IO ()
72
- ${basicFn} c = do
73
- fixture <- loadFixture "${e.Name}"
74
- existing <- getp fixture "existing"
75
- opts <- jo [("entity", existing)]
76
- `
77
- // Basic flow. Each op is an independent runTest.
78
- if (hasList) {
79
- defs += ` runTest c "${e.name}.list" $ do
80
- sdk <- C.testSdk opts VNoval
81
- ent <- C.${fn} sdk VNoval
82
- em1 <- emptyMap; em2 <- emptyMap
83
- lst <- eList ent em1 em2
84
- -- \`list\` resolves to one ENTITY per record; the record is reached
85
- -- through eDataGet. See AGENTS.md "Entity operations return ENTITIES".
86
- ok <- mapM (\\en -> ismap <$> eDataGet en) lst
87
- pure (all id ok)
88
- `
89
- }
90
- if (hasLoad) {
91
- defs += ` runTest c "${e.name}.load" $ do
92
- sdk <- C.testSdk opts VNoval
93
- ent <- C.${fn} sdk VNoval
94
- entmap <- getp existing "${e.name}"
95
- ids <- keysof entmap
96
- case ids of
97
- [] -> pure True
98
- (id0 : _) -> do
99
- m <- jo [("id", VStr id0)]; ctrl <- emptyMap
100
- loaded <- eLoad ent m ctrl
101
- ld <- eDataGet loaded
102
- lid <- getp ld "id"
103
- pure (ismap ld && vstring lid == id0)
104
- `
105
- }
106
- if (hasCreate) {
107
- defs += ` runTest c "${e.name}.create" $ do
108
- sdk <- C.testSdk opts VNoval
109
- ent <- C.${fn} sdk VNoval
110
- d <- newRefData fixture "${e.name}"
111
- ctrl <- emptyMap
112
- created <- eCreate ent d ctrl
113
- cd <- eDataGet created
114
- cid <- getp cd "id"
115
- pure (ismap cd && not (isNoval cid))
116
- `
117
- }
118
- if (hasCreate && hasUpdate) {
119
- defs += ` runTest c "${e.name}.update" $ do
120
- sdk <- C.testSdk opts VNoval
121
- ent <- C.${fn} sdk VNoval
122
- d <- newRefData fixture "${e.name}"
123
- ctrl <- emptyMap
124
- created <- eCreate ent d ctrl
125
- cd <- eDataGet created
126
- cid <- getp cd "id"
127
- upd <- jo [("id", cid), ("${updField}", VStr "UpdatedMark")]
128
- ctrl2 <- emptyMap
129
- updated <- eUpdate ent upd ctrl2
130
- ud <- eDataGet updated
131
- uv <- getp ud "${updField}"
132
- pure (ismap ud && vstring uv == "UpdatedMark")
133
- `
134
- }
135
- if (hasCreate && hasRemove) {
136
- defs += ` runTest c "${e.name}.remove" $ do
137
- sdk <- C.testSdk opts VNoval
138
- ent <- C.${fn} sdk VNoval
139
- d <- newRefData fixture "${e.name}"
140
- ctrl <- emptyMap
141
- created <- eCreate ent d ctrl
142
- cd <- eDataGet created
143
- cid <- getp cd "id"
144
- rm <- jo [("id", cid)]; ctrl2 <- emptyMap
145
- -- \`remove\` resolves to the entity, marked. It KEEPS the data it held.
146
- removed <- eRemove ent rm ctrl2
147
- gone <- readIORef (eDeleted removed)
148
- rd <- eDataGet removed
149
- rid <- getp rd "id"
150
- pure (gone && vstring rid == vstring cid)
151
- `
152
- }
153
- // An op-less entity (no list/load/create — e.g. a bare path entity)
154
- // appends no runTest, leaving the do-block ending on `opts <- jo [...]`
155
- // (a bind), which is illegal as the final statement. Terminate it.
156
- if (!hasList && !hasLoad && !hasCreate) {
157
- defs += ` pure ()\n`
158
- }
159
-
160
- // Direct call test (via injected system.fetch mock).
161
- defs += `
162
- ${directFn} :: Counters -> IO ()
163
- ${directFn} c = runTest c "${e.name}.direct" $ do
164
- calls <- newIORef (0 :: Int)
165
- let mock = VFunc (\\_ _ _ _ -> do
166
- modifyIORef calls (+ 1)
167
- d <- jo [("id", VStr "direct01")]
168
- jo [("status", VNum 200), ("statusText", VStr "OK"), ("json", jsonThunk d)])
169
- sys <- jo [("fetch", mock)]
170
- opts <- jo [("base", VStr "http://localhost:8080"), ("system", sys)]
171
- sdk <- C.newSdk opts
172
- args <- jo [("path", VStr "/${e.name}/x"), ("method", VStr "GET")]
173
- res <- F.direct sdk args
174
- ok <- getp res "ok"
175
- st <- getp res "status"
176
- dat <- getp res "data"
177
- did <- getp dat "id"
178
- n <- readIORef calls
179
- pure (isTrueV ok && toInt st == 200 && vstring did == "direct01" && n == 1)
180
- `
181
-
182
- // PR review #4: entity eStream(action, args, callopts) runs the op
183
- // through the full pipeline and returns a lazy list. Fallback (no
184
- // streaming feature) yields the materialised items; with the streaming
185
- // feature active it yields from the streaming iterator (chunkSize
186
- // groups into batches). Needs a list op; seeds three records.
187
- if (hasList) {
188
- const streamFn = `${fn}StreamTest`
189
- calls += ` ${streamFn} c\n`
190
- defs += `
191
- ${streamFn} :: Counters -> IO ()
192
- ${streamFn} c = do
193
- let mkSeed = do
194
- r1 <- jo [("id", VStr "S1"), ("name", VStr "a")]
195
- r2 <- jo [("id", VStr "S2"), ("name", VStr "b")]
196
- r3 <- jo [("id", VStr "S3"), ("name", VStr "c")]
197
- recs <- jo [("S1", r1), ("S2", r2), ("S3", r3)]
198
- jo [("${e.name}", recs)]
199
- hasStreaming = do
200
- sdk0 <- C.testSdk0
201
- fs <- getp (clConfig sdk0) "feature"
202
- st <- getp fs "streaming"
203
- pure (not (isNoval st))
204
- runTest c "${e.name}.stream" $ do
205
- seed <- mkSeed; opts <- jo [("entity", seed)]
206
- sdk <- C.testSdk opts VNoval
207
- ent <- C.${fn} sdk VNoval
208
- em1 <- emptyMap
209
- items <- eStream ent "list" em1 VNoval
210
- pure (length items == 3 && (case items of (x : _) -> ismap x; [] -> False))
211
- runTest c "${e.name}.stream_signal" $ do
212
- seed <- mkSeed; opts <- jo [("entity", seed)]
213
- sdk <- C.testSdk opts VNoval
214
- ent <- C.${fn} sdk VNoval
215
- em1 <- emptyMap
216
- n <- newIORef (0 :: Int)
217
- let sig = vfunc0 (do modifyIORef n (+ 1); v <- readIORef n; pure (VBool (v >= 2)))
218
- co <- jo [("signal", sig)]
219
- items <- eStream ent "list" em1 co
220
- pure (length items == 1)
221
- runTest c "${e.name}.stream_active" $ do
222
- hs <- hasStreaming
223
- if not hs then pure True else do
224
- seed <- mkSeed; opts <- jo [("entity", seed)]
225
- stg <- jo [("active", VBool True)]; strm <- jo [("streaming", stg)]; sopts <- jo [("feature", strm)]
226
- sdk <- C.testSdk opts sopts
227
- ent <- C.${fn} sdk VNoval
228
- em1 <- emptyMap
229
- items <- eStream ent "list" em1 VNoval
230
- pure (length items == 3)
231
- runTest c "${e.name}.stream_chunk" $ do
232
- hs <- hasStreaming
233
- if not hs then pure True else do
234
- seed <- mkSeed; opts <- jo [("entity", seed)]
235
- stg <- jo [("active", VBool True), ("chunkSize", VNum 2)]; strm <- jo [("streaming", stg)]; sopts <- jo [("feature", strm)]
236
- sdk <- C.testSdk opts sopts
237
- ent <- C.${fn} sdk VNoval
238
- em1 <- emptyMap
239
- batches <- eStream ent "list" em1 VNoval
240
- pure (length batches == 2)
241
- `
242
- }
243
- })
244
-
245
- Content(`-- Generated model-driven entity + direct tests.
246
- {-# LANGUAGE ScopedTypeVariables #-}
247
-
248
- module SdkGenTests (genTests) where
249
-
250
- import Control.Exception (SomeException, try)
251
- import Data.IORef
252
-
253
- import VoxgigStruct (Value (..), emptyMap, keysof, ismap, islist, isNoval, clone)
254
- import SdkTypes
255
- import SdkHelpers
256
- import qualified SdkFeatures as F
257
- import qualified SdkClient as C
258
- import qualified TReadmeExamples
259
- import Testutil
260
- import SdkJson (jsonRead)
261
-
262
- -- Load an entity fixture (../.sdk/test/entity/<name>/<Name>TestData.json).
263
- loadFixture :: String -> IO Value
264
- loadFixture entName = do
265
- -- The fixture DIRECTORY is the snake_case entity name (create_result), so a
266
- -- plain lowercase of the CamelCase entName (createresult) misses the
267
- -- underscores for multi-word entities. Convert CamelCase -> snake_case.
268
- let lname = camelToSnake entName
269
- raw <- readFile ("../.sdk/test/entity/" ++ lname ++ "/" ++ entName ++ "TestData.json")
270
- jsonRead raw
271
- where
272
- toLowerCh ch = if ch >= 'A' && ch <= 'Z' then toEnum (fromEnum ch + 32) else ch
273
- camelToSnake [] = []
274
- camelToSnake (c0 : rest) = toLowerCh c0 : go rest
275
- go [] = []
276
- go (c : cs)
277
- | c >= 'A' && c <= 'Z' = '_' : toLowerCh c : go cs
278
- | otherwise = c : go cs
279
-
280
- -- The first new-ref data map for an entity (fixture.new.<entity>.<ref0>).
281
- newRefData :: Value -> String -> IO Value
282
- newRefData fixture entName = do
283
- newEnts <- getpathS fixture ("new." ++ entName)
284
- refs <- keysof newEnts
285
- case refs of
286
- [] -> emptyMap
287
- (r0 : _) -> do d <- getp newEnts r0; clone d
288
-
289
- genTests :: Counters -> IO ()
290
- genTests c = do
291
- TReadmeExamples.tests c
292
- ${calls}${defs}`)
293
- })
294
- })
295
- })
296
-
297
-
298
- export {
299
- Test
300
- }
@@ -1,15 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "esModuleInterop": true,
4
- "module": "nodenext",
5
- "noEmitOnError": true,
6
- "outDir":"../dist",
7
- "rootDir":".",
8
- "resolveJsonModule": true,
9
- "sourceMap": true,
10
- "strict": true,
11
- "target": "es2022",
12
- "declaration": true,
13
- "declarationDir": "../dist"
14
- }
15
- }
@@ -1,166 +0,0 @@
1
- import * as Path from 'node:path'
2
-
3
- import {
4
- clone,
5
- walk,
6
- } from '@voxgig/struct'
7
-
8
-
9
- function projectPath(suffix?: string): string {
10
- return Path.normalize(Path.join(__dirname, '../../..', suffix ?? ''))
11
- }
12
-
13
-
14
- // Haskell reserved words that cannot be used as identifiers.
15
- const HS_RESERVED = new Set<string>([
16
- 'case', 'class', 'data', 'default', 'deriving', 'do', 'else', 'foreign',
17
- 'if', 'import', 'in', 'infix', 'infixl', 'infixr', 'instance', 'let',
18
- 'module', 'newtype', 'of', 'then', 'type', 'where', 'as', 'hiding',
19
- 'qualified',
20
- ])
21
-
22
-
23
- // A collision-free lower-camel Haskell identifier for a model name.
24
- function hsVarName(name: string): string {
25
- let s = String(name).replace(/[^a-zA-Z0-9_]/g, '_')
26
- if (s.length === 0) {
27
- s = 'x'
28
- }
29
- // Identifiers must start with a lowercase letter.
30
- s = s.charAt(0).toLowerCase() + s.slice(1)
31
- if (!/^[a-z_]/.test(s)) {
32
- s = 'e_' + s
33
- }
34
- return HS_RESERVED.has(s) ? s + '_' : s
35
- }
36
-
37
-
38
- // A Haskell string literal (7-bit safe: non-printable / non-ASCII use the
39
- // decimal numeric escape with a `\&` separator so digits never merge).
40
- function hsString(s: string): string {
41
- let out = '"'
42
- for (const ch of String(s)) {
43
- const code = ch.codePointAt(0) as number
44
- if (ch === '"') out += '\\"'
45
- else if (ch === '\\') out += '\\\\'
46
- else if (ch === '\n') out += '\\n'
47
- else if (ch === '\t') out += '\\t'
48
- else if (ch === '\r') out += '\\r'
49
- else if (code >= 32 && code < 127) out += ch
50
- else out += '\\' + code + '\\&'
51
- }
52
- return out + '"'
53
- }
54
-
55
-
56
- // Render a JSON-shaped value as a Haskell `CV` literal (the generated
57
- // SdkConfig realises it with buildCV). Empty map/list render as
58
- // (CVMap []) / (CVList []) — valid for 0, 1 or N entries (N-feature-safe).
59
- //
60
- // KEY ORDER IS INSERTION ORDER, not sorted. struct's Haskell `Value` holds a
61
- // map as an ORDERED assoc list, so key order is observable — it survives into
62
- // keysof, iteration and stringify. This used to sort, which was fine while
63
- // this was the only representation, but above the size threshold the same
64
- // config arrives via jsonRead in the JSON text's order. Sorting here would
65
- // have made the two representations describe the same config in a different
66
- // order, which is exactly what rung L1 promises cannot happen.
67
- //
68
- // Insertion order is still byte-stable: every nested level of the config comes
69
- // from `each`, which iterates sorted, and the two levels built by hand
70
- // (the root, and `options`) have a fixed order every target's literal follows.
71
- function formatHsValue(val: any): string {
72
- if (val === null || val === undefined) {
73
- return 'CVNull'
74
- }
75
- if (typeof val === 'string') {
76
- return '(CVStr ' + hsString(val) + ')'
77
- }
78
- if (typeof val === 'number') {
79
- return '(CVNum (' + (Number.isFinite(val) ? String(val) : '0') + '))'
80
- }
81
- if (typeof val === 'boolean') {
82
- return '(CVBool ' + (val ? 'True' : 'False') + ')'
83
- }
84
- if (Array.isArray(val)) {
85
- const items = val.map((v) => formatHsValue(v)).join(', ')
86
- return '(CVList [' + items + '])'
87
- }
88
- if (typeof val === 'object') {
89
- const items = Object.keys(val)
90
- .map((k) => '(' + hsString(k) + ', ' + formatHsValue(val[k]) + ')')
91
- .join(', ')
92
- return '(CVMap [' + items + '])'
93
- }
94
- return 'CVNull'
95
- }
96
-
97
-
98
- // Remove `$`-suffixed model annotation keys.
99
- // Emission-time normalisation of a model subtree (L0).
100
- //
101
- // Always drops jostraca's iteration metadata (`$`-suffixed keys: index$,
102
- // key$, val$). With `dropDefaults`, also drops keys whose value IS the
103
- // default the runtime already assumes when the key is absent, which is pure
104
- // payload — see CONFIG_DEFAULT.
105
- //
106
- // Rebuilds the tree rather than mutating during a walk. The previous
107
- // implementation walked a clone calling `delete p[k]`, but walk() assigns its
108
- // callback's result back over the child (`setprop(out, ckey, walk(...))`), so
109
- // the delete was undone on the way out and the helper silently did nothing.
110
- // Returning `undefined` from the callback does not fix it either: setprop
111
- // stores undefined rather than removing the key, which then emits as a null.
112
- //
113
- // `dropDefaults` is opt-in and must be passed ONLY for the entity subtree.
114
- // `active` means something different in feature config, where absent reads as
115
- // INACTIVE (see feature_init) — dropping `active: true` there would silently
116
- // disable the feature.
117
- // jostraca's iteration metadata, injected by each()/names() while it walks the
118
- // model. Listed explicitly rather than matched by trailing-dollar suffix: a
119
- // trailing dollar is not exclusive to jostraca -- Seneca uses entity$ as real
120
- // data -- so a blanket suffix match can silently drop a legitimate API field.
121
- const MODEL_META = ['index$', 'key$', 'val$']
122
-
123
- // Keys whose value IS the default the runtime already assumes when the key is
124
- // absent, so emitting them is pure payload.
125
- const CONFIG_DEFAULT: Record<string, any> = {
126
- active: true,
127
- req: false,
128
- reqd: false,
129
- }
130
-
131
- // Subtrees carrying user payload rather than schema. An active:true inside an
132
- // OpenAPI example is DATA, not a default, so default-pruning stops at these
133
- // keys and everything below them is passed through untouched.
134
- const PAYLOAD_KEYS = ['default', 'example', 'examples']
135
-
136
- function clean(o: any, dropDefaults?: boolean): any {
137
- const prune = (node: any, defaults: boolean): any => {
138
- if (Array.isArray(node)) {
139
- return node.map((n: any) => prune(n, defaults))
140
- }
141
- if (null != node && 'object' === typeof node) {
142
- const out: any = {}
143
- for (const k of Object.keys(node)) {
144
- if (MODEL_META.includes(k)) {
145
- continue
146
- }
147
- if (defaults && k in CONFIG_DEFAULT && CONFIG_DEFAULT[k] === node[k]) {
148
- continue
149
- }
150
- out[k] = prune(node[k], defaults && !PAYLOAD_KEYS.includes(k))
151
- }
152
- return out
153
- }
154
- return node
155
- }
156
- return prune(o, true === dropDefaults)
157
- }
158
-
159
-
160
- export {
161
- clean,
162
- formatHsValue,
163
- hsString,
164
- hsVarName,
165
- projectPath,
166
- }
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 voxgig
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,22 +0,0 @@
1
- # ProjectName SDK — Haskell build/test.
2
- # Requires GHC (`ghc`) on PATH. No third-party dependencies (only the GHC
3
- # boot libraries: base, containers, array, time). The vendored voxgig struct
4
- # port lives under src/ (VoxgigStruct.hs + Vregex.hs).
5
-
6
- .PHONY: test build clean
7
-
8
- BUILDDIR := .hsbuild
9
-
10
- # Build and run the full SDK test suite + vendored struct corpus. The runner
11
- # reads the shared spec at ../.sdk/test/test.json (run from this directory).
12
- test:
13
- @mkdir -p $(BUILDDIR)
14
- ghc -O0 -isrc -itest -outputdir $(BUILDDIR) -o $(BUILDDIR)/runner test/Runner.hs
15
- $(BUILDDIR)/runner
16
-
17
- # Type-check only (a clean compile = pass).
18
- build:
19
- ghc -fno-code -isrc -itest test/Runner.hs
20
-
21
- clean:
22
- rm -rf $(BUILDDIR) src/*.hi src/*.o test/*.hi test/*.o
@@ -1 +0,0 @@
1
- PROJECTVERSION