@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
@@ -50,18 +50,26 @@ class ProjectNameSDK {
50
50
  // the `test` feature installs the base mock transport and the transport
51
51
  // features (retry/cache/netsim/proxy/ratelimit) wrap whatever is current,
52
52
  // so `test` must be added before them to sit at the base of the chain.
53
+ const extend = this._options.extend || []
54
+
53
55
  const featureorder = getpath(this._options, '__derived__.featureorder') || []
54
56
  for (const fname of featureorder) {
55
57
  const fopts = this._options.feature[fname] || {}
56
58
  if (fopts.active) {
59
+ // An active name with no generated class is legal when an
60
+ // extend-supplied instance carries that name (station's adopt
61
+ // path): the instance is added below, positioned by its own
62
+ // __after__ entry, so skip it here rather than fail construction.
63
+ if (!this._rootctx.config.hasFeature(fname) &&
64
+ extend.some((f) => fname === f.name)) {
65
+ continue
66
+ }
57
67
  featureAdd(this._rootctx, this._rootctx.config.makeFeature(fname))
58
68
  }
59
69
  }
60
70
 
61
- if (null != this._options.extend) {
62
- for (let f of this._options.extend) {
63
- featureAdd(this._rootctx, f)
64
- }
71
+ for (let f of extend) {
72
+ featureAdd(this._rootctx, f)
65
73
  }
66
74
 
67
75
  for (let f of this._features) {
@@ -185,7 +193,27 @@ class ProjectNameSDK {
185
193
  }
186
194
 
187
195
  const status = fetched.status
188
- const json = 'function' === typeof fetched.json ? await fetched.json() : fetched.json
196
+
197
+ // No body responses (204 No Content, 304 Not Modified) and explicit
198
+ // zero content-length must skip JSON parsing — fetched.json() would
199
+ // throw `Unexpected end of JSON input` on an empty body.
200
+ const headers = fetched.headers
201
+ const contentLength = headers && 'function' === typeof headers.get
202
+ ? headers.get('content-length')
203
+ : (headers || {})['content-length']
204
+ const noBody = 204 === status || 304 === status || '0' === String(contentLength)
205
+
206
+ let json = undefined
207
+ if (!noBody) {
208
+ try {
209
+ json = 'function' === typeof fetched.json ? await fetched.json() : fetched.json
210
+ }
211
+ catch (parseErr) {
212
+ // Body wasn't valid JSON — surface the raw response rather than
213
+ // throwing. data stays undefined; callers can inspect status/headers.
214
+ json = undefined
215
+ }
216
+ }
189
217
 
190
218
  return {
191
219
  ok: status >= 200 && status < 300,
@@ -3,6 +3,7 @@ import {
3
3
  Content,
4
4
  File,
5
5
  cmp,
6
+ configDefinition,
6
7
  each,
7
8
  isAuthActive,
8
9
  resolveAuthPrefix,
@@ -72,8 +73,14 @@ const Config = cmp(async function Config(props: any) {
72
73
  relations: n.relations,
73
74
  }, true), a), {})
74
75
 
76
+ // Identity comes from configDefinition's def, not re-derived here, so
77
+ // this target cannot disagree with the shared emitter on main.slug /
78
+ // main.version / main.target (the three station descriptor fields,
79
+ // station design §4) — passing target.name is what opts this target in.
80
+ const { def: configDef } = configDefinition(model, target.name)
81
+
75
82
  const config = {
76
- main: { name: model.const.Name },
83
+ main: configDef.main,
77
84
  feature: featureConfig,
78
85
  options,
79
86
  entity: entityConfig,
@@ -1,14 +1,9 @@
1
1
 
2
- import {
3
- KIT,
4
- getModelPath
5
- } from '@voxgig/apidef'
6
-
7
2
  import type {
8
3
  ModelEntity
9
4
  } from '@voxgig/apidef'
10
5
 
11
- import { cmp, each, Folder } from '@voxgig/sdkgen'
6
+ import { cmp, each, Folder, entityCollection } from '@voxgig/sdkgen'
12
7
 
13
8
 
14
9
  import { TestEntity } from './TestEntity_kotlin'
@@ -30,7 +25,9 @@ const Test = cmp(function Test(props: any) {
30
25
  // CustomUtilityTest, StructRunner/StructCorpusTest, ExistsTest and
31
26
  // sdk-test-control.json) ships as templates in tm/kotlin/test/ and is
32
27
  // copied by Main_kotlin. Here we generate only the API-specific tests.
33
- each(model.main[KIT].entity, (entity: ModelEntity) => {
28
+ const entity = each(entityCollection(model))
29
+ .filter((e: any) => false !== e.active)
30
+ each(entity, (entity: ModelEntity) => {
34
31
  TestEntity({ target, entity, kotlinpackage })
35
32
  TestDirect({ target, entity, kotlinpackage })
36
33
  })
@@ -4,12 +4,11 @@ import {
4
4
  Folder,
5
5
  cmp,
6
6
  each,
7
+ entityCollection,
7
8
  } from '@voxgig/sdkgen'
8
9
 
9
10
  import {
10
- KIT,
11
11
  Model,
12
- getModelPath,
13
12
  } from '@voxgig/apidef'
14
13
 
15
14
 
@@ -70,7 +69,8 @@ const Test = cmp(async function Test(props: any) {
70
69
  const target = props.target
71
70
  const model: Model = ctx$.model
72
71
 
73
- const entity = getModelPath(model, `main.${KIT}.entity`)
72
+ const entity = each(entityCollection(model))
73
+ .filter((e: any) => false !== e.active)
74
74
 
75
75
  // Per-entity OFFLINE (test-mode) blocks: seeded store, no server.
76
76
  let offline = ''
@@ -68,8 +68,11 @@ const Config = cmp(async function Config(props: any) {
68
68
  // The same config as an OBJECT, built by the shared helper so this target's
69
69
  // literal and the data that replaces it above the threshold are the same
70
70
  // config by construction. The JSON is what the threshold is measured on -
71
- // emitted source size varies by language, the model does not.
72
- const { json: configJson } = configDefinition(model)
71
+ // emitted source size varies by language, the model does not. Passing the
72
+ // target name opts this target into the main slug/version/target identity
73
+ // fields (station descriptor v1 reads all three) - the literal branch
74
+ // below emits them too, so the two representations cannot diverge.
75
+ const { def: configDef, json: configJson } = configDefinition(model, target.name)
73
76
  const asData = isConfigData(configJson, configReprSetting(model))
74
77
 
75
78
  File({ name: 'config.' + target.ext }, () => {
@@ -112,6 +115,9 @@ end
112
115
  }
113
116
  else {
114
117
 
118
+ // Identity values from configDefinition's def, not re-derived here, so
119
+ // the literal rep and the data rep cannot disagree (the ts #MainMeta
120
+ // discipline).
115
121
  Content(`-- Build a fresh, fully materialised config table. Every call rebuilds the
116
122
  -- whole structure, so prefer require("config_shared") unless you need a
117
123
  -- private copy you intend to mutate.
@@ -119,6 +125,9 @@ local function make_config()
119
125
  return {
120
126
  main = {
121
127
  name = "${model.const.Name}",
128
+ slug = ${JSON.stringify(configDef.main.slug)},
129
+ version = ${JSON.stringify(configDef.main.version)},
130
+ target = ${JSON.stringify(configDef.main.target)},
122
131
  },
123
132
  feature = {
124
133
  `)
@@ -4,6 +4,7 @@ import {
4
4
  File,
5
5
  cmp,
6
6
  collectDeps,
7
+ each,
7
8
  pkgDescription,
8
9
  keywords,
9
10
  repoInfo, packageName,
@@ -11,6 +12,11 @@ import {
11
12
  } from '@voxgig/sdkgen'
12
13
 
13
14
 
15
+ import {
16
+ KIT,
17
+ getModelPath,
18
+ } from '@voxgig/apidef'
19
+
14
20
  import type {
15
21
  Model,
16
22
  } from '@voxgig/apidef'
@@ -27,7 +33,7 @@ const Package = cmp(async function Package(props: any) {
27
33
  // (`${model.name}_sdk`) used by `require` is unchanged.
28
34
  const ns = model.origin || 'voxgig-sdk'
29
35
  const pkgBase = ns.endsWith('-sdk') ? model.name : `${model.name}-sdk`
30
- const rockName = packageName(model, 'lua')
36
+ const rockName = packageName(model, target.name)
31
37
  const { repoUrl, issuesUrl } = repoInfo(model)
32
38
  const labels = keywords(model).map((k) => `"${k}"`).join(', ')
33
39
 
@@ -46,7 +52,7 @@ source = {
46
52
  dir = "${model.name}-sdk/lua"
47
53
  }
48
54
  description = {
49
- summary = "${pkgDescription(model, 'lua')}",
55
+ summary = "${pkgDescription(model, target.name)}",
50
56
  homepage = "${repoUrl}",
51
57
  issues_url = "${issuesUrl}",
52
58
  license = "MIT",
@@ -66,6 +72,23 @@ dependencies = {
66
72
  `)
67
73
  }
68
74
 
75
+ // Feature modules must be listed too, or an install-from-rock ships a
76
+ // features.lua whose requires cannot resolve. Emitted from the model
77
+ // (each = sorted order, byte-stable), plus the base feature every
78
+ // factory falls back to. The station feature additionally carries the
79
+ // VENDORED voxgig_station library beside its adapter (no voxgig-station
80
+ // rock exists to depend on - station design 9.2's registry-less tier).
81
+ const feature = getModelPath(model, `main.${KIT}.feature`)
82
+ let featureModules = ` ["feature.base_feature"] = "feature/base_feature.lua",\n`
83
+ each(feature, (f: any) => {
84
+ featureModules +=
85
+ ` ["feature.${f.name}_feature"] = "feature/${f.name}_feature.lua",\n`
86
+ if ('station' === f.name) {
87
+ featureModules +=
88
+ ` ["feature.station.voxgig_station"] = "feature/station/voxgig_station.lua",\n`
89
+ }
90
+ })
91
+
69
92
  Content(`}
70
93
  build = {
71
94
  type = "builtin",
@@ -74,7 +97,7 @@ build = {
74
97
  ["config"] = "config.lua",
75
98
  ["config_shared"] = "config_shared.lua",
76
99
  ["features"] = "features.lua",
77
- }
100
+ ${featureModules} }
78
101
  }
79
102
  `)
80
103
  })
@@ -1,14 +1,9 @@
1
1
 
2
- import {
3
- KIT,
4
- getModelPath
5
- } from '@voxgig/apidef'
6
-
7
2
  import type {
8
3
  ModelEntity
9
4
  } from '@voxgig/apidef'
10
5
 
11
- import { cmp, each, Folder, File, Content } from '@voxgig/sdkgen'
6
+ import { cmp, each, Folder, File, Content, entityCollection } from '@voxgig/sdkgen'
12
7
 
13
8
 
14
9
  import { TestEntity } from './TestEntity_lua'
@@ -37,7 +32,10 @@ end)
37
32
  `)
38
33
  })
39
34
 
40
- each(model.main[KIT].entity, (entity: ModelEntity) => {
35
+ const entity = each(entityCollection(model))
36
+ .filter((e: any) => false !== e.active)
37
+
38
+ each(entity, (entity: ModelEntity) => {
41
39
  TestEntity({ target, entity })
42
40
  TestDirect({ target, entity })
43
41
  })
@@ -1,14 +1,9 @@
1
1
 
2
- import {
3
- KIT,
4
- getModelPath,
5
- } from '@voxgig/apidef'
6
-
7
2
  import type {
8
3
  ModelEntity
9
4
  } from '@voxgig/apidef'
10
5
 
11
- import { cmp, each, Folder } from '@voxgig/sdkgen'
6
+ import { cmp, each, Folder, entityCollection } from '@voxgig/sdkgen'
12
7
 
13
8
 
14
9
  import { TestEntity } from './TestEntity_ocaml'
@@ -20,7 +15,8 @@ const Test = cmp(function Test(props: any) {
20
15
  const { model } = props.ctx$
21
16
  const { target } = props
22
17
 
23
- const entity = getModelPath(model, `main.${KIT}.entity`)
18
+ const entity = each(entityCollection(model))
19
+ .filter((e: any) => false !== e.active)
24
20
 
25
21
  Folder({ name: 'test' }, () => {
26
22
  each(entity, (entity: ModelEntity) => {
@@ -3,24 +3,15 @@ import {
3
3
  Content,
4
4
  File,
5
5
  cmp,
6
- each,
7
- isAuthActive,
8
- resolveAuthPrefix,
6
+ configDefinition,
9
7
  } from '@voxgig/sdkgen'
10
8
 
11
9
 
12
10
  import {
13
- KIT,
14
11
  Model,
15
- getModelPath,
16
12
  } from '@voxgig/apidef'
17
13
 
18
14
 
19
- import {
20
- clean,
21
- } from './utility_perl'
22
-
23
-
24
15
  // The config is emitted as a JSON heredoc parsed at load time by the
25
16
  // vendored struct utility (Voxgig::Struct::parse_json). This keeps
26
17
  // booleans/nulls faithful (Perl has no native boolean scalar) and yields
@@ -32,57 +23,14 @@ const Config = cmp(async function Config(props: any) {
32
23
 
33
24
  const model: Model = ctx$.model
34
25
 
35
- const entity = getModelPath(model, `main.${KIT}.entity`)
36
- const feature = getModelPath(model, `main.${KIT}.feature`)
37
-
38
- const headers = getModelPath(model, `main.${KIT}.config.headers`) || {}
39
-
40
- const authActive = isAuthActive(model)
41
- // config.auth.prefix override -> spec-derived info.security.prefix -> 'Bearer'
42
- const authPrefix = resolveAuthPrefix(model)
43
-
44
- let baseUrl = ''
45
- try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
46
-
47
- // Build the config structure with deterministic (sorted) key order for
48
- // the model-derived collections (each() iterates sorted).
49
- const featureBlock: any = {}
50
- each(feature, (f: any) => {
51
- featureBlock[f.name] = clean(f.config || {})
52
- })
53
-
54
- const entityOptions: any = {}
55
- each(entity, (ent: any) => {
56
- entityOptions[ent.name] = {}
57
- })
58
-
59
- const entityBlock: any = {}
60
- each(entity, (ent: any) => {
61
- entityBlock[ent.name] = clean({
62
- fields: ent.fields,
63
- name: ent.name,
64
- op: ent.op,
65
- relations: ent.relations,
66
- }, true)
67
- })
26
+ // THE canonical config object, from the shared helper - this component
27
+ // used to hand-assemble its own (and had already drifted: no server
28
+ // block, no identity beyond main.name). Passing the target name opts
29
+ // in to the main slug/version/target identity fields (station
30
+ // descriptor inputs), matching the ts/js/rb targets.
31
+ const { def: configDef } = configDefinition(model, target.name)
68
32
 
69
- const options: any = {
70
- base: baseUrl,
71
- }
72
- if (authActive) {
73
- options.auth = { prefix: authPrefix }
74
- }
75
- options.headers = headers
76
- options.entity = entityOptions
77
-
78
- const config = {
79
- main: { name: model.const.Name },
80
- feature: featureBlock,
81
- options,
82
- entity: entityBlock,
83
- }
84
-
85
- const configJson = JSON.stringify(config, null, 2)
33
+ const configJson = JSON.stringify(configDef, null, 2)
86
34
 
87
35
  File({ name: 'config.pm' }, () => {
88
36
 
@@ -48,7 +48,7 @@ use ExtUtils::MakeMaker;
48
48
  WriteMakefile(
49
49
  NAME => '${Name}SDK',
50
50
  VERSION_FROM => 'lib/${Name}SDK.pm',
51
- ABSTRACT => '${pkgDescription(model, 'perl')}',
51
+ ABSTRACT => '${pkgDescription(model, target.name)}',
52
52
  AUTHOR => 'Voxgig',
53
53
  LICENSE => 'mit',
54
54
  MIN_PERL_VERSION => '5.018',
@@ -1,14 +1,9 @@
1
1
 
2
- import {
3
- KIT,
4
- getModelPath
5
- } from '@voxgig/apidef'
6
-
7
2
  import type {
8
3
  ModelEntity
9
4
  } from '@voxgig/apidef'
10
5
 
11
- import { cmp, each, Folder, File, Content } from '@voxgig/sdkgen'
6
+ import { cmp, each, Folder, File, Content, entityCollection } from '@voxgig/sdkgen'
12
7
 
13
8
 
14
9
  import { TestEntity } from './TestEntity_perl'
@@ -42,7 +37,10 @@ done_testing();
42
37
  `)
43
38
  })
44
39
 
45
- each(model.main[KIT].entity, (entity: ModelEntity) => {
40
+ const entity = each(entityCollection(model))
41
+ .filter((e: any) => false !== e.active)
42
+
43
+ each(entity, (entity: ModelEntity) => {
46
44
  TestEntity({ target, entity })
47
45
  TestDirect({ target, entity })
48
46
  })
@@ -70,8 +70,10 @@ const Config = cmp(async function Config(props: any) {
70
70
  // The same config as an OBJECT, built by the shared helper so this target's
71
71
  // literal and the data that replaces it above the threshold are the same
72
72
  // config by construction. The JSON is what the threshold is measured on -
73
- // emitted source size varies by language, the model does not.
74
- const { json: configJson } = configDefinition(model)
73
+ // emitted source size varies by language, the model does not. Passing the
74
+ // target name opts in to the main.slug/version/target identity fields -
75
+ // both representations below carry them, keeping the reps interchangeable.
76
+ const { def: configDef, json: configJson } = configDefinition(model, target.name)
75
77
  const asData = isConfigData(configJson, configReprSetting(model))
76
78
 
77
79
  File({ name: 'config.' + target.ext }, () => {
@@ -174,6 +176,10 @@ class ${model.const.Name}Config
174
176
  }
175
177
  else {
176
178
 
179
+ // Identity beyond the camel Name: values from configDefinition's def, not
180
+ // re-derived here, so the literal rep and the data rep cannot disagree on
181
+ // identity (the slug is CARRIED, never derived from the camel name -
182
+ // station's descriptor reads all three; mirrors cmp/ts's #MainMeta).
177
183
  Content(` /**
178
184
  * Build a fresh, fully materialised config array. Every call rebuilds the
179
185
  * whole structure, so prefer shared_config unless you need a private copy.
@@ -183,6 +189,9 @@ class ${model.const.Name}Config
183
189
  return [
184
190
  "main" => [
185
191
  "name" => "${model.const.Name}",
192
+ "slug" => ${phps(configDef.main.slug)},
193
+ "version" => ${phps(configDef.main.version)},
194
+ "target" => ${phps(configDef.main.target)},
186
195
  ],
187
196
  "feature" => [
188
197
  `)
@@ -29,7 +29,7 @@ import {
29
29
  File, Content, Folder,
30
30
  } from '@voxgig/sdkgen'
31
31
 
32
- import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames } from '@voxgig/sdkgen'
32
+ import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames, phpSafeTypeName } from '@voxgig/sdkgen'
33
33
 
34
34
  import {
35
35
  KIT,
@@ -114,9 +114,20 @@ declare(strict_types=1);
114
114
  const fields = (ent.fields ? each(ent.fields) : [])
115
115
  .filter((f: any) => f.active !== false && validName(f.name))
116
116
 
117
+ // PHP refuses a reserved word where a class name is expected, and the
118
+ // check is CASE-INSENSITIVE — an entity named `Namespace` emitted
119
+ // `class Namespace`, which does not parse, and took the whole types
120
+ // file with it (issue #64). phpSafeTypeName appends `Type` on a real
121
+ // collision and leaves every other name untouched.
122
+ //
123
+ // Only the bare data class needs it: the per-op names below already
124
+ // carry a suffix no reserved word matches, and the entity accessor is
125
+ // a method, which PHP resolves separately.
126
+ const TypeName = phpSafeTypeName(Name)
127
+
117
128
  // Entity data model: one typed property per field (`req:false` -> nullable).
118
129
  Content(`/** ${Name} entity data model. */
119
- class ${Name}
130
+ class ${TypeName}
120
131
  {
121
132
  `)
122
133
  fields.forEach((f: any) => {
@@ -130,6 +130,31 @@ class ${model.const.Name}Features
130
130
  return new ${model.const.Name}BaseFeature();
131
131
  }
132
132
  }
133
+
134
+ /**
135
+ * Does a generated feature class back this name? False for a name only
136
+ * an options extend instance can supply (the station adopt path) - the
137
+ * constructor uses this to skip make_feature for such names instead of
138
+ * adding a stray BaseFeature.
139
+ */
140
+ public static function has_feature(string $name): bool
141
+ {
142
+ switch ($name) {
143
+ case "base":
144
+ `)
145
+
146
+ each(feature, (feat: any) => {
147
+ if (feat.name !== 'base') {
148
+ Content(` case "${feat.name}":
149
+ `)
150
+ }
151
+ })
152
+
153
+ Content(` return true;
154
+ default:
155
+ return false;
156
+ }
157
+ }
133
158
  }
134
159
  `)
135
160
  })
@@ -39,8 +39,8 @@ const Package = cmp(async function Package(props: any) {
39
39
  // Generate composer.json
40
40
  File({ name: 'composer.json' }, () => {
41
41
  Content(`{
42
- "name": "${packageName(model, 'php')}",
43
- "description": "${pkgDescription(model, 'php')}",
42
+ "name": "${packageName(model, target.name)}",
43
+ "description": "${pkgDescription(model, target.name)}",
44
44
  "type": "library",
45
45
  "keywords": [${kw}],
46
46
  "homepage": "${repoUrl}",
@@ -1,14 +1,9 @@
1
1
 
2
- import {
3
- KIT,
4
- getModelPath
5
- } from '@voxgig/apidef'
6
-
7
2
  import type {
8
3
  ModelEntity
9
4
  } from '@voxgig/apidef'
10
5
 
11
- import { cmp, each, Folder, File, Content } from '@voxgig/sdkgen'
6
+ import { cmp, each, Folder, File, Content, entityCollection } from '@voxgig/sdkgen'
12
7
 
13
8
 
14
9
  import { TestEntity } from './TestEntity_php'
@@ -44,7 +39,10 @@ class ExistsTest extends TestCase
44
39
  `)
45
40
  })
46
41
 
47
- each(model.main[KIT].entity, (entity: ModelEntity) => {
42
+ const entity = each(entityCollection(model))
43
+ .filter((e: any) => false !== e.active)
44
+
45
+ each(entity, (entity: ModelEntity) => {
48
46
  TestEntity({ target, entity })
49
47
  TestDirect({ target, entity })
50
48
  })
@@ -58,6 +58,12 @@ class ProjectNameSDK
58
58
 
59
59
  $this->_rootctx->options = $this->options;
60
60
 
61
+ // Feature INSTANCES supplied at construction (the station adopt
62
+ // path) are read from the RAW construction options - extend is
63
+ // consumed exactly once, here; make_options strips it from the
64
+ // processed map so options_map() stays clean data.
65
+ $extend_val = is_array($options["extend"] ?? null) ? $options["extend"] : [];
66
+
61
67
  // Add features in the resolved order (make_options puts an explicit
62
68
  // list order first, else defaults to test-first). Ordering matters: the
63
69
  // `test` feature installs the base mock transport and the transport
@@ -70,6 +76,20 @@ class ProjectNameSDK
70
76
  foreach ($featureorder as $fname) {
71
77
  $fopts = ProjectNameHelpers::to_map($feature_opts[$fname] ?? null);
72
78
  if ($fopts && isset($fopts["active"]) && $fopts["active"] === true) {
79
+ // An active name with no generated feature class is
80
+ // legal when an extend-supplied instance carries that
81
+ // name (station's adopt path): the instance is added
82
+ // below, positioned by its own __after__ entry, so
83
+ // skip it here rather than add a BaseFeature stray
84
+ // that would silently shift feature positions.
85
+ if (!ProjectNameFeatures::has_feature($fname)) {
86
+ foreach ($extend_val as $ef) {
87
+ if (is_object($ef) && method_exists($ef, 'get_name')
88
+ && $fname === $ef->get_name()) {
89
+ continue 2;
90
+ }
91
+ }
92
+ }
73
93
  ($utility->feature_add)($this->_rootctx, ProjectNameFeatures::make_feature($fname));
74
94
  }
75
95
  }
@@ -77,12 +97,9 @@ class ProjectNameSDK
77
97
  }
78
98
 
79
99
  // Add extension features.
80
- $extend_val = Struct::getprop($this->options, "extend");
81
- if (is_array($extend_val)) {
82
- foreach ($extend_val as $f) {
83
- if (is_object($f) && method_exists($f, 'get_name')) {
84
- ($utility->feature_add)($this->_rootctx, $f);
85
- }
100
+ foreach ($extend_val as $f) {
101
+ if (is_object($f) && method_exists($f, 'get_name')) {
102
+ ($utility->feature_add)($this->_rootctx, $f);
86
103
  }
87
104
  }
88
105
 
@@ -67,8 +67,10 @@ const Config = cmp(async function Config(props: any) {
67
67
  // The same config as an OBJECT, built by the shared helper so this target's
68
68
  // literal and the data that replaces it above the threshold are the same
69
69
  // config by construction. The JSON is what the threshold is measured on -
70
- // emitted source size varies by language, the model does not.
71
- const { json: configJson } = configDefinition(model)
70
+ // emitted source size varies by language, the model does not. Passing the
71
+ // target name opts in to the main.slug/version/target identity fields -
72
+ // the literal path below emits them too, keeping the two reps in step.
73
+ const { def: configDef, json: configJson } = configDefinition(model, target.name)
72
74
  const asData = isConfigData(configJson, configReprSetting(model))
73
75
 
74
76
  File({ name: 'config.' + target.ext }, () => {
@@ -130,6 +132,10 @@ def make_config():
130
132
  return
131
133
  }
132
134
 
135
+ // Identity values from configDefinition's def, not re-derived here, so
136
+ // the literal rep and the data rep cannot disagree on identity (the
137
+ // slug is CARRIED, never derived from the camel name - station's
138
+ // descriptor reads all three; see cmp/ts/Config_ts.ts #MainMeta).
133
139
  Content(`def make_config():
134
140
  """Build a fresh, fully materialised config dict.
135
141
 
@@ -139,6 +145,9 @@ def make_config():
139
145
  return {
140
146
  "main": {
141
147
  "name": "${model.const.Name}",
148
+ "slug": ${JSON.stringify(configDef.main.slug)},
149
+ "version": ${JSON.stringify(configDef.main.version)},
150
+ "target": ${JSON.stringify(configDef.main.target)},
142
151
  },
143
152
  "feature": {
144
153
  `)