@voxgig/sdkgen 3.5.1 → 3.6.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 (171) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/cmp/ExternalTarget.js +1 -1
  3. package/dist/cmp/ExternalTarget.js.map +1 -1
  4. package/dist/helpers/naming.d.ts +4 -1
  5. package/dist/helpers/naming.js +119 -5
  6. package/dist/helpers/naming.js.map +1 -1
  7. package/dist/helpers/opShape.js +72 -0
  8. package/dist/helpers/opShape.js.map +1 -1
  9. package/dist/helpers/packageMeta.d.ts +2 -1
  10. package/dist/helpers/packageMeta.js +57 -20
  11. package/dist/helpers/packageMeta.js.map +1 -1
  12. package/dist/sdkgen.d.ts +3 -3
  13. package/dist/sdkgen.js +61 -18
  14. package/dist/sdkgen.js.map +1 -1
  15. package/dist/testkit.d.ts +39 -0
  16. package/dist/testkit.js +663 -0
  17. package/dist/testkit.js.map +1 -0
  18. package/dist/tsconfig.tsbuildinfo +1 -1
  19. package/package.json +32 -8
  20. package/project/.sdk/src/cmp/c/Test_c.ts +5 -7
  21. package/project/.sdk/src/cmp/clojure/Test_clojure.ts +3 -7
  22. package/project/.sdk/src/cmp/cpp/Test_cpp.ts +4 -7
  23. package/project/.sdk/src/cmp/csharp/Package_csharp.ts +1 -1
  24. package/project/.sdk/src/cmp/csharp/Test_csharp.ts +5 -7
  25. package/project/.sdk/src/cmp/dart/Test_dart.ts +3 -4
  26. package/project/.sdk/src/cmp/elixir/Package_elixir.ts +1 -1
  27. package/project/.sdk/src/cmp/elixir/Test_elixir.ts +5 -6
  28. package/project/.sdk/src/cmp/go/EntityTypes_go.ts +1 -1
  29. package/project/.sdk/src/cmp/go/Entity_go.ts +1 -1
  30. package/project/.sdk/src/cmp/go/Gitignore_go.ts +6 -0
  31. package/project/.sdk/src/cmp/go/Main_go.ts +2 -2
  32. package/project/.sdk/src/cmp/go/Package_go.ts +1 -1
  33. package/project/.sdk/src/cmp/go/ReadmeExamplesTest_go.ts +59 -6
  34. package/project/.sdk/src/cmp/go/ReadmeExplanation_go.ts +1 -1
  35. package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +1 -1
  36. package/project/.sdk/src/cmp/go/ReadmeInstall_go.ts +1 -1
  37. package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +1 -1
  38. package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +1 -1
  39. package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +1 -1
  40. package/project/.sdk/src/cmp/go/ReadmeTopTest_go.ts +1 -1
  41. package/project/.sdk/src/cmp/go/Test_go.ts +6 -8
  42. package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +6 -2
  43. package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +6 -2
  44. package/project/.sdk/src/cmp/java/Test_java.ts +4 -7
  45. package/project/.sdk/src/cmp/js/Package_js.ts +1 -1
  46. package/project/.sdk/src/cmp/js/Test_js.ts +4 -7
  47. package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +4 -7
  48. package/project/.sdk/src/cmp/lean/Test_lean.ts +3 -3
  49. package/project/.sdk/src/cmp/lua/Package_lua.ts +2 -2
  50. package/project/.sdk/src/cmp/lua/Test_lua.ts +5 -7
  51. package/project/.sdk/src/cmp/ocaml/Test_ocaml.ts +3 -7
  52. package/project/.sdk/src/cmp/perl/Package_perl.ts +1 -1
  53. package/project/.sdk/src/cmp/perl/Test_perl.ts +5 -7
  54. package/project/.sdk/src/cmp/php/EntityTypes_php.ts +13 -2
  55. package/project/.sdk/src/cmp/php/Package_php.ts +2 -2
  56. package/project/.sdk/src/cmp/php/Test_php.ts +5 -7
  57. package/project/.sdk/src/cmp/py/Package_py.ts +2 -2
  58. package/project/.sdk/src/cmp/py/Test_py.ts +5 -7
  59. package/project/.sdk/src/cmp/py-data/Main_py-data.ts +14 -19
  60. package/project/.sdk/src/cmp/rb/Package_rb.ts +3 -3
  61. package/project/.sdk/src/cmp/rb/ReadmeInstall_rb.ts +1 -1
  62. package/project/.sdk/src/cmp/rb/Test_rb.ts +5 -7
  63. package/project/.sdk/src/cmp/rust/Test_rust.ts +5 -7
  64. package/project/.sdk/src/cmp/scala/Test_scala.ts +5 -2
  65. package/project/.sdk/src/cmp/seneca-provider/Gitignore_seneca-provider.ts +161 -0
  66. package/project/.sdk/src/cmp/seneca-provider/Main_seneca-provider.ts +20 -11
  67. package/project/.sdk/src/cmp/swift/Test_swift.ts +5 -7
  68. package/project/.sdk/src/cmp/ts/Package_ts.ts +1 -1
  69. package/project/.sdk/src/cmp/ts/Test_ts.ts +8 -7
  70. package/project/.sdk/src/cmp/zig/Test_zig.ts +3 -7
  71. package/project/.sdk/tm/c/utility/make_point.c +64 -3
  72. package/project/.sdk/tm/clojure/src/sdk/core.clj +49 -14
  73. package/project/.sdk/tm/cpp/utility/pipeline.hpp +55 -3
  74. package/project/.sdk/tm/csharp/feature/TestFeature.cs +36 -2
  75. package/project/.sdk/tm/csharp/utility/MakePoint.cs +65 -2
  76. package/project/.sdk/tm/dart/lib/feature/test/TestFeature.dart +34 -4
  77. package/project/.sdk/tm/dart/lib/utility/MakePointUtility.dart +48 -2
  78. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +70 -10
  79. package/project/.sdk/tm/go/feature/test_feature.go +34 -2
  80. package/project/.sdk/tm/go/utility/make_point.go +66 -2
  81. package/project/.sdk/tm/java/feature/TestFeature.java +42 -2
  82. package/project/.sdk/tm/java/utility/MakePoint.java +61 -2
  83. package/project/.sdk/tm/js/src/feature/test/TestFeature.js +22 -3
  84. package/project/.sdk/tm/js/src/utility/MakePointUtility.js +72 -2
  85. package/project/.sdk/tm/kotlin/feature/TestFeature.kt +31 -2
  86. package/project/.sdk/tm/kotlin/utility/MakePoint.kt +58 -2
  87. package/project/.sdk/tm/lean/src/SdkUtility.lean +28 -0
  88. package/project/.sdk/tm/lua/utility/make_point.lua +65 -2
  89. package/project/.sdk/tm/ocaml/sdk_runtime.ml +40 -2
  90. package/project/.sdk/tm/perl/utility/make_point.pm +55 -2
  91. package/project/.sdk/tm/php/feature/TestFeature.php +30 -1
  92. package/project/.sdk/tm/php/utility/MakePoint.php +49 -1
  93. package/project/.sdk/tm/py/pkg/utility/make_point.py +56 -2
  94. package/project/.sdk/tm/rb/utility/make_point.rb +42 -2
  95. package/project/.sdk/tm/rust/utility/make_point.rs +69 -2
  96. package/project/.sdk/tm/scala/feature/TestFeature.scala +36 -1
  97. package/project/.sdk/tm/scala/utility/Make.scala +57 -3
  98. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TestFeature.swift +29 -1
  99. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Make.swift +51 -2
  100. package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +22 -3
  101. package/project/.sdk/tm/ts/src/utility/MakePointUtility.ts +72 -2
  102. package/project/.sdk/tm/zig/core/utility.zig +66 -3
  103. package/project/sdkgen-package.json +1 -2
  104. package/src/cmp/ExternalTarget.ts +1 -1
  105. package/src/helpers/naming.ts +129 -5
  106. package/src/helpers/opShape.ts +85 -0
  107. package/src/helpers/packageMeta.ts +59 -20
  108. package/src/sdkgen.ts +68 -20
  109. package/src/testkit.ts +863 -0
  110. package/testkit.d.ts +3 -0
  111. package/testkit.js +12 -0
  112. package/project/.sdk/model/target/haskell.aontu +0 -72
  113. package/project/.sdk/src/cmp/haskell/Config_haskell.ts +0 -98
  114. package/project/.sdk/src/cmp/haskell/Entity_haskell.ts +0 -13
  115. package/project/.sdk/src/cmp/haskell/Gitignore_haskell.ts +0 -27
  116. package/project/.sdk/src/cmp/haskell/Main_haskell.ts +0 -123
  117. package/project/.sdk/src/cmp/haskell/Package_haskell.ts +0 -60
  118. package/project/.sdk/src/cmp/haskell/ReadmeEntity_haskell.ts +0 -186
  119. package/project/.sdk/src/cmp/haskell/ReadmeExamplesTest_haskell.ts +0 -135
  120. package/project/.sdk/src/cmp/haskell/ReadmeExplanation_haskell.ts +0 -48
  121. package/project/.sdk/src/cmp/haskell/ReadmeHowto_haskell.ts +0 -168
  122. package/project/.sdk/src/cmp/haskell/ReadmeInstall_haskell.ts +0 -51
  123. package/project/.sdk/src/cmp/haskell/ReadmeIntro_haskell.ts +0 -67
  124. package/project/.sdk/src/cmp/haskell/ReadmeModel_haskell.ts +0 -162
  125. package/project/.sdk/src/cmp/haskell/ReadmeOptions_haskell.ts +0 -74
  126. package/project/.sdk/src/cmp/haskell/ReadmeQuick_haskell.ts +0 -241
  127. package/project/.sdk/src/cmp/haskell/ReadmeRef_haskell.ts +0 -408
  128. package/project/.sdk/src/cmp/haskell/ReadmeTopHowto_haskell.ts +0 -31
  129. package/project/.sdk/src/cmp/haskell/ReadmeTopQuick_haskell.ts +0 -104
  130. package/project/.sdk/src/cmp/haskell/ReadmeTopTest_haskell.ts +0 -80
  131. package/project/.sdk/src/cmp/haskell/Test_haskell.ts +0 -300
  132. package/project/.sdk/src/cmp/haskell/tsconfig.json +0 -15
  133. package/project/.sdk/src/cmp/haskell/utility_haskell.ts +0 -166
  134. package/project/.sdk/tm/haskell/LICENSE +0 -21
  135. package/project/.sdk/tm/haskell/Makefile +0 -22
  136. package/project/.sdk/tm/haskell/VERSION +0 -1
  137. package/project/.sdk/tm/haskell/src/SdkFeatures.hs +0 -1440
  138. package/project/.sdk/tm/haskell/src/SdkHelpers.hs +0 -337
  139. package/project/.sdk/tm/haskell/src/SdkJson.hs +0 -111
  140. package/project/.sdk/tm/haskell/src/SdkRuntime.hs +0 -1219
  141. package/project/.sdk/tm/haskell/src/SdkTypes.hs +0 -195
  142. package/project/.sdk/tm/haskell/src/VoxgigStruct.hs +0 -2299
  143. package/project/.sdk/tm/haskell/src/Vregex.hs +0 -237
  144. package/project/.sdk/tm/haskell/src/feature/README.md +0 -5
  145. package/project/.sdk/tm/haskell/src/feature/audit/.gitkeep +0 -0
  146. package/project/.sdk/tm/haskell/src/feature/base/.gitkeep +0 -0
  147. package/project/.sdk/tm/haskell/src/feature/cache/.gitkeep +0 -0
  148. package/project/.sdk/tm/haskell/src/feature/clienttrack/.gitkeep +0 -0
  149. package/project/.sdk/tm/haskell/src/feature/debug/.gitkeep +0 -0
  150. package/project/.sdk/tm/haskell/src/feature/idempotency/.gitkeep +0 -0
  151. package/project/.sdk/tm/haskell/src/feature/log/.gitkeep +0 -0
  152. package/project/.sdk/tm/haskell/src/feature/metrics/.gitkeep +0 -0
  153. package/project/.sdk/tm/haskell/src/feature/netsim/.gitkeep +0 -0
  154. package/project/.sdk/tm/haskell/src/feature/paging/.gitkeep +0 -0
  155. package/project/.sdk/tm/haskell/src/feature/proxy/.gitkeep +0 -0
  156. package/project/.sdk/tm/haskell/src/feature/ratelimit/.gitkeep +0 -0
  157. package/project/.sdk/tm/haskell/src/feature/rbac/.gitkeep +0 -0
  158. package/project/.sdk/tm/haskell/src/feature/retry/.gitkeep +0 -0
  159. package/project/.sdk/tm/haskell/src/feature/streaming/.gitkeep +0 -0
  160. package/project/.sdk/tm/haskell/src/feature/telemetry/.gitkeep +0 -0
  161. package/project/.sdk/tm/haskell/src/feature/test/.gitkeep +0 -0
  162. package/project/.sdk/tm/haskell/src/feature/timeout/.gitkeep +0 -0
  163. package/project/.sdk/tm/haskell/test/Harness.hs +0 -281
  164. package/project/.sdk/tm/haskell/test/Runner.hs +0 -47
  165. package/project/.sdk/tm/haskell/test/StructCorpus.hs +0 -449
  166. package/project/.sdk/tm/haskell/test/TCustomUtility.hs +0 -38
  167. package/project/.sdk/tm/haskell/test/TFeature.hs +0 -794
  168. package/project/.sdk/tm/haskell/test/TNetsim.hs +0 -50
  169. package/project/.sdk/tm/haskell/test/TPipeline.hs +0 -334
  170. package/project/.sdk/tm/haskell/test/TPrimaryUtility.hs +0 -386
  171. package/project/.sdk/tm/haskell/test/Testutil.hs +0 -59
package/testkit.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ // Types for the `@voxgig/sdkgen/testkit` entry point. See testkit.js.
2
+
3
+ export * from './dist/testkit'
package/testkit.js ADDED
@@ -0,0 +1,12 @@
1
+ /* Copyright (c) 2024-2026 Voxgig Ltd, MIT License */
2
+
3
+ // `require('@voxgig/sdkgen/testkit')` — the package's second entry point.
4
+ //
5
+ // A stub rather than an `exports` map entry, on purpose. A map would name
6
+ // this subpath and, in doing so, replace the deep-import freedom this package
7
+ // has without one — and consumers depend on that freedom invisibly (generated
8
+ // model files include `@voxgig/sdkgen/model/sdkgen.aontu`; the scaffold is
9
+ // reached as `@voxgig/sdkgen/project/<lang>`). See the `_no_exports_comment`
10
+ // in package.json for what was measured.
11
+
12
+ module.exports = require('./dist/testkit.js')
@@ -1,72 +0,0 @@
1
-
2
- main: kit: target: haskell: {
3
-
4
- title: Haskell
5
- ext: hs
6
- comment: line: "--"
7
- module: name: '$$name$$'
8
- base: 'BASE'
9
- srcfeature: false
10
-
11
- # Entities are generic (config-driven F.makeEntity), so no per-entity or
12
- # per-feature generated modules. The readme + agentguide phases are
13
- # model-driven (they read the API model directly, not per-entity generated
14
- # code), so they are active and produce the docs; entity/feature generation
15
- # stays off.
16
- phase: {
17
- entity: { active: false }
18
- feature: { active: false }
19
- readme: { active: true }
20
- agentguide: { active: true }
21
- test: { active: true }
22
- }
23
-
24
- deps: &: {
25
- kind: *'prod' | string
26
- }
27
-
28
- # struct is vendored under src/ (VoxgigStruct.hs + Vregex.hs) — the runtime
29
- # is dependency-free: it compiles with the stock ghc (base + containers, the
30
- # GHC boot libraries), no cabal packages, no stack. So there are no manifest
31
- # dependencies.
32
- deps: {}
33
- }
34
-
35
-
36
- main: kit: feature: &: target: haskell: deps: &: {
37
- kind: *'prod' | string
38
- }
39
-
40
-
41
- # Publication: Hackage registry (declared, publish pending — git-tag only).
42
- #
43
- # `target add <t>` OVERWRITES this file, so a project must never set its
44
- # publication values here — voxgig-solardemo-sdk lost its pinned npm package
45
- # name exactly that way. Set them in the project's own model
46
- # (`model/sdk.aontu`), where they survive a resync.
47
- #
48
- # For that to work this file must LEAVE THOSE KEYS UNSET: in aontu a concrete
49
- # value does not yield to another concrete value, it CONFLICTS, and two
50
- # defaults conflict too. The schema (@voxgig/sdkgen/model/sdkgen.aontu)
51
- # already defaults `tag.active`, `registry.state`, `registry.active` and
52
- # `registry.package`, so a project's concrete value wins over the default and
53
- # repeating them here would only take that away.
54
- #
55
- # What remains below is per-target registry IDENTITY, which is not a project
56
- # choice and stays concrete.
57
- main: kit: target: haskell: publish: {
58
- registry: {
59
- name: 'hackage'
60
- url: 'https://hackage.haskell.org'
61
- vault: { alias: 'hackage', env: 'HACKAGE_TOKEN' }
62
- }
63
- }
64
-
65
-
66
- # Feature source is NOT trimmed to the model's selection here: every
67
- # feature lives inside a single generated module (src/SdkFeatures.hs), not
68
- # in per-feature source files, so there is nothing per-feature to leave
69
- # out. Trimming waits on that module becoming model-driven.
70
- main: kit: target: haskell: feature: {
71
- trim: false
72
- }
@@ -1,98 +0,0 @@
1
- import {
2
- Content,
3
- File,
4
- cmp,
5
- configDefinition,
6
- configReprSetting,
7
- isConfigData,
8
- } from '@voxgig/sdkgen'
9
-
10
-
11
- import {
12
- Model,
13
- } from '@voxgig/apidef'
14
-
15
-
16
- import {
17
- formatHsValue,
18
- hsString,
19
- } from './utility_haskell'
20
-
21
-
22
- // The full set of feature constructors in SdkFeatures (name -> <name>Feature).
23
- const FEATURE_NAMES = [
24
- 'log', 'test', 'retry', 'timeout', 'ratelimit', 'cache', 'idempotency',
25
- 'paging', 'streaming', 'proxy', 'telemetry', 'metrics', 'debug', 'audit',
26
- 'clienttrack', 'rbac', 'netsim',
27
- ]
28
-
29
-
30
- // SdkConfig.hs: makeConfig builds the embedded API model as a struct Value;
31
- // makeFeature(name) is the N-feature-safe factory the client uses to
32
- // instantiate features named in the options.
33
- const Config = cmp(async function Config(props: any) {
34
- const ctx$ = props.ctx$
35
- const target = props.target
36
-
37
- const model: Model = ctx$.model
38
-
39
- // The same config as an OBJECT, built by the shared helper so this target's
40
- // literal and the data that replaces it above the threshold are the same
41
- // config by construction. The JSON is what the threshold is measured on -
42
- // emitted source size varies by language, the model does not.
43
- const { def: configDef, json: configJson } = configDefinition(model)
44
- const asData = isConfigData(configJson, configReprSetting(model))
45
-
46
- // ABOVE THE THRESHOLD: emit the model as DATA.
47
- //
48
- // The literal representation is one enormous CV expression. GHC type-checks
49
- // and desugars every constructor application in it, and buildCV then walks
50
- // the whole tree allocating an IORef per node. A string constant is one
51
- // token, and jsonRead builds the same Value from it directly.
52
- //
53
- // Both branches return a FRESH Value per call - buildCV allocates new
54
- // IORefs, jsonRead re-parses - so a caller that mutates one config cannot
55
- // reach another's, exactly as before.
56
- const configBody = asData
57
- ? `-- THE API MODEL, EMBEDDED AS DATA (sdkgen rung L1).
58
- --
59
- -- Emitted only above a size threshold, or when \`main.kit.config.repr\` pins
60
- -- it: for a small model the CV literal is smaller and far easier to read when
61
- -- debugging.
62
- configData :: String
63
- configData = ${hsString(configJson)}
64
-
65
- makeConfig :: IO Value
66
- makeConfig = jsonRead configData`
67
- : `makeConfig :: IO Value
68
- makeConfig = buildCV ${formatHsValue(configDef)}`
69
-
70
- File({ name: 'SdkConfig.' + target.ext }, () => {
71
-
72
- Content(`-- Generated API configuration (make_config) and the feature factory.
73
-
74
- module SdkConfig (makeConfig, makeFeature) where
75
-
76
- import VoxgigStruct (Value)
77
- import ${asData ? 'SdkJson (jsonRead)' : 'SdkHelpers (CV (..), buildCV)'}
78
- import SdkTypes (Feature)
79
- import qualified SdkFeatures as F
80
-
81
- ${configBody}
82
-
83
- makeFeature :: String -> IO Feature
84
- makeFeature name = case name of
85
- `)
86
-
87
- for (const fname of FEATURE_NAMES) {
88
- Content(` "${fname}" -> F.${fname}Feature\n`)
89
- }
90
-
91
- Content(` _ -> F.baseFeature\n`)
92
- })
93
- })
94
-
95
-
96
- export {
97
- Config
98
- }
@@ -1,13 +0,0 @@
1
- import { cmp } from '@voxgig/sdkgen'
2
-
3
-
4
- // Entities are generic in the Haskell target: there is no per-entity
5
- // generated module. Every entity is created by the config-driven
6
- // F.makeEntity (see SdkClient), so this component emits nothing. It exists
7
- // only so the neutral Entity component can resolve a language delegate.
8
- const Entity = cmp(function Entity(_props: any) {})
9
-
10
-
11
- export {
12
- Entity
13
- }
@@ -1,27 +0,0 @@
1
- import {
2
- Content,
3
- File,
4
- cmp,
5
- } from '@voxgig/sdkgen'
6
-
7
-
8
- const Gitignore = cmp(async function Gitignore(_props: any) {
9
- File({ name: '.gitignore' }, () => {
10
- Content(`# Haskell build output
11
- .hsbuild/
12
- dist-newstyle/
13
- *.hi
14
- *.o
15
-
16
- # IDE / OS
17
- .idea/
18
- .vscode/
19
- .DS_Store
20
- `)
21
- })
22
- })
23
-
24
-
25
- export {
26
- Gitignore
27
- }
@@ -1,123 +0,0 @@
1
- import {
2
- cmp, each,
3
- File, Content, Copy, Folder,
4
- } from '@voxgig/sdkgen'
5
-
6
-
7
- import type {
8
- ModelEntity
9
- } from '@voxgig/apidef'
10
-
11
-
12
- import {
13
- KIT,
14
- getModelPath
15
- } from '@voxgig/apidef'
16
-
17
-
18
- import { Package } from './Package_haskell'
19
- import { Config } from './Config_haskell'
20
- import { Gitignore } from './Gitignore_haskell'
21
- import { hsVarName } from './utility_haskell'
22
-
23
-
24
- const Main = cmp(async function Main(props: any) {
25
-
26
- const { target } = props
27
- const { model } = props.ctx$
28
-
29
- const entity: ModelEntity = getModelPath(model, `main.${KIT}.entity`)
30
-
31
- Package({ target })
32
-
33
- Gitignore({})
34
-
35
- // Copy tm/haskell verbatim: the runtime under src/ (VoxgigStruct, Vregex,
36
- // SdkTypes, SdkHelpers, SdkRuntime, SdkFeatures), the test suite under
37
- // test/, and Makefile/LICENSE/VERSION. The per-feature custom-source
38
- // scaffold under src/feature is excluded (this target does not use it —
39
- // entities are generic and config-driven, so there are no per-entity or
40
- // per-feature generated modules). Placeholder substitution applies.
41
- Copy({
42
- from: 'tm/' + target.name,
43
- exclude: [/src\/feature\//],
44
- replace: {
45
- ...props.ctx$.stdrep,
46
- }
47
- })
48
-
49
- // Generated modules under src/: the API config + feature factory, and the
50
- // public client (SDK constructors + entity accessors).
51
- Folder({ name: 'src' }, () => {
52
-
53
- Config({ target })
54
-
55
- File({ name: 'SdkClient.' + target.ext }, () => {
56
-
57
- let accessors = ''
58
- let exports = ''
59
- each(entity, (e: any) => {
60
- const fn = hsVarName(e.name)
61
- exports += ` , ${fn}\n`
62
- accessors += `-- | The ${e.Name} entity bound to this client.
63
- ${fn} :: Client -> Value -> IO Entity
64
- ${fn} client entopts = F.makeEntity client "${e.name}" entopts
65
-
66
- `
67
- })
68
-
69
- Content(`-- ${model.const.Name} SDK public client (generated by @voxgig/sdkgen).
70
- --
71
- -- SDK constructors (newSdk / testSdk) and one accessor per entity. Entities
72
- -- are generic — every accessor calls the config-driven F.makeEntity, so the
73
- -- operation pipeline is identical for every entity and every API.
74
-
75
- module SdkClient
76
- ( module SdkTypes
77
- , newSdk
78
- , newSdk0
79
- , testSdk
80
- , testSdk0
81
- ${exports} ) where
82
-
83
- import Data.IORef (readIORef)
84
-
85
- import VoxgigStruct (Value (..))
86
- import SdkTypes
87
- import SdkConfig (makeConfig, makeFeature)
88
- import qualified SdkFeatures as F
89
-
90
- -- | Construct a live SDK client from an options map (Noval for defaults).
91
- newSdk :: Value -> IO Client
92
- newSdk options = do
93
- cfg <- makeConfig
94
- F.makeClientBase cfg makeFeature options
95
-
96
- -- | No-argument convenience constructor.
97
- newSdk0 :: IO Client
98
- newSdk0 = newSdk VNoval
99
-
100
- -- | Construct a test-mode SDK: testSdk testopts sdkopts.
101
- testSdk :: Value -> Value -> IO Client
102
- testSdk testopts sdkopts = do
103
- cfg <- makeConfig
104
- F.sdkTest cfg makeFeature testopts sdkopts
105
-
106
- -- | No-argument convenience test constructor.
107
- testSdk0 :: IO Client
108
- testSdk0 = testSdk VNoval VNoval
109
-
110
- -- | The active client mode ("live" or "test").
111
- clientMode :: Client -> IO String
112
- clientMode = readIORef . clMode
113
-
114
- ${accessors}`)
115
- })
116
- })
117
-
118
- })
119
-
120
-
121
- export {
122
- Main
123
- }
@@ -1,60 +0,0 @@
1
- import {
2
- Content,
3
- File,
4
- cmp,
5
- packageVersion,
6
- } from '@voxgig/sdkgen'
7
-
8
-
9
- import type {
10
- Model,
11
- } from '@voxgig/apidef'
12
-
13
-
14
- function pkgName(model: any): string {
15
- const org = (model.origin || 'voxgig-sdk').replace(/-sdk$/, '')
16
- return `${org}-${model.name}-sdk`.toLowerCase().replace(/[^a-z0-9-]/g, '-')
17
- }
18
-
19
-
20
- // The cabal package file (for Hackage publication). The offline test build
21
- // uses the Makefile (stock ghc, boot libraries only: base + containers +
22
- // array + time), so no cabal solve is required to run the suite.
23
- const Package = cmp(async function Package(props: any) {
24
- const ctx$ = props.ctx$
25
- const target = props.target
26
-
27
- const model: Model = ctx$.model
28
-
29
- File({ name: pkgName(model) + '.cabal' }, () => {
30
- Content(`cabal-version: 2.4
31
- name: ${pkgName(model)}
32
- version: ${packageVersion(model, target.name)}
33
- synopsis: ${model.const.Name} SDK for Haskell (generated by @voxgig/sdkgen)
34
- license: MIT
35
- build-type: Simple
36
-
37
- library
38
- default-language: Haskell2010
39
- hs-source-dirs: src
40
- exposed-modules: VoxgigStruct
41
- Vregex
42
- SdkJson
43
- SdkTypes
44
- SdkHelpers
45
- SdkRuntime
46
- SdkFeatures
47
- SdkConfig
48
- SdkClient
49
- build-depends: base >=4.14 && <5
50
- , containers >=0.6 && <0.8
51
- , array >=0.5 && <0.6
52
- , time >=1.9 && <1.15
53
- `)
54
- })
55
- })
56
-
57
-
58
- export {
59
- Package
60
- }
@@ -1,186 +0,0 @@
1
-
2
- import { cmp, each, Content, canonKey, entityIdField, opRequestShape } from '@voxgig/sdkgen'
3
-
4
- import {
5
- KIT,
6
- getModelPath,
7
- } from '@voxgig/apidef'
8
-
9
- import { hsVarName } from './utility_haskell'
10
-
11
-
12
- // A type-correct Haskell `Value` literal for a field's canonical type.
13
- function hsLit(type: any, placeholder: string = 'example'): string {
14
- const k = canonKey(type)
15
- if ('INTEGER' === k || 'NUMBER' === k) return 'VNum 1'
16
- if ('BOOLEAN' === k) return 'VBool True'
17
- if ('ARRAY' === k || 'OBJECT' === k) return 'VNoval'
18
- return `VStr "${placeholder}"`
19
- }
20
-
21
-
22
- // A readable Haskell type name for a field's canonical type. The runtime
23
- // carries every field as a dynamic `Value`; this documents the logical type.
24
- function hsType(type: any): string {
25
- const k = canonKey(type)
26
- if ('STRING' === k) return 'String'
27
- if ('INTEGER' === k) return 'Int'
28
- if ('NUMBER' === k) return 'Double'
29
- if ('BOOLEAN' === k) return 'Bool'
30
- if ('ARRAY' === k) return '[Value]'
31
- return 'Value'
32
- }
33
-
34
-
35
- const OP_DESC: Record<string, { method: string, desc: string }> = {
36
- load: { method: 'eLoad ent match ctrl', desc: 'Load a single entity by match criteria. Resolves to the entity.' },
37
- list: { method: 'eList ent match ctrl', desc: 'List entities, optionally matching the given criteria. Resolves to one entity per record.' },
38
- create: { method: 'eCreate ent data ctrl', desc: 'Create a new entity with the given data. Resolves to the entity.' },
39
- update: { method: 'eUpdate ent data ctrl', desc: 'Update an existing entity. Resolves to the entity.' },
40
- remove: { method: 'eRemove ent match ctrl', desc: 'Remove the matching entity. Resolves to the entity, marked deleted.' },
41
- }
42
-
43
-
44
- const ReadmeEntity = cmp(function ReadmeEntity(props: any) {
45
- const { target } = props
46
- const { model } = props.ctx$
47
-
48
- const entity = getModelPath(model, `main.${KIT}.entity`)
49
-
50
- const publishedEntities = each(entity)
51
- .filter((entity: any) => entity.active !== false)
52
-
53
- if (0 === publishedEntities.length) {
54
- return
55
- }
56
-
57
- Content(`
58
-
59
- ## Entities
60
-
61
- `)
62
-
63
- publishedEntities.map((entity: any) => {
64
- const opnames = Object.keys(entity.op || {})
65
- const fields = entity.fields || []
66
- const idF = entityIdField(entity)
67
- const eFn = hsVarName(entity.name)
68
-
69
- Content(`
70
- ### ${entity.Name}
71
-
72
- `)
73
-
74
- if (entity.short) {
75
- Content(`${entity.short}
76
-
77
- `)
78
- }
79
-
80
- Content(`Create an instance: \`${eFn} <- Sdk.${eFn} sdk VNoval\`
81
-
82
- `)
83
-
84
- if (opnames.length > 0) {
85
- Content(`#### Operations
86
-
87
- | Method | Description |
88
- | --- | --- |
89
- `)
90
- opnames.map((opname: string) => {
91
- const info = OP_DESC[opname]
92
- if (info) {
93
- Content(`| \`${info.method}\` | ${info.desc} |
94
- `)
95
- }
96
- })
97
-
98
- Content(`
99
- `)
100
- }
101
-
102
- if (fields.length > 0) {
103
- Content(`#### Fields
104
-
105
- | Field | Type | Description |
106
- | --- | --- | --- |
107
- `)
108
-
109
- each(fields, (field: any) => {
110
- const desc = field.short || ''
111
- Content(`| \`${field.name}\` | \`${hsType(field.type)}\` | ${desc} |
112
- `)
113
- })
114
-
115
- Content(`
116
- `)
117
- }
118
-
119
- if (opnames.includes('load')) {
120
- const loadItems = opRequestShape(entity, 'load').items
121
- .filter((it: any) => !it.optional || it.name === idF)
122
- .sort((a: any, b: any) =>
123
- (a.name === idF ? 0 : 1) - (b.name === idF ? 0 : 1))
124
- const loadArg = 0 < loadItems.length
125
- ? `[${loadItems.map((it: any) =>
126
- `("${it.name}", ${hsLit(it.type,
127
- it.name === idF ? entity.name + '_id' : it.name)})`).join(', ')}]`
128
- : '[]'
129
- Content(`#### Example: Load
130
-
131
- \`\`\`haskell
132
- ent <- Sdk.${eFn} sdk VNoval
133
- match <- jo ${loadArg}
134
- ctrl <- emptyMap
135
- ${eFn} <- Sdk.eLoad ent match ctrl
136
- -- The op resolves to the ENTITY; the record is inside it.
137
- ${eFn}Data <- Sdk.eDataGet ${eFn}
138
- \`\`\`
139
-
140
- `)
141
- }
142
-
143
- if (opnames.includes('list')) {
144
- Content(`#### Example: List
145
-
146
- \`\`\`haskell
147
- ent <- Sdk.${eFn} sdk VNoval
148
- match <- emptyMap
149
- ctrl <- emptyMap
150
- -- One ENTITY per record.
151
- ${eFn}s <- Sdk.eList ent match ctrl
152
- ${eFn}Datas <- mapM Sdk.eDataGet ${eFn}s
153
- \`\`\`
154
-
155
- `)
156
- }
157
-
158
- if (opnames.includes('create')) {
159
- const createItems = opRequestShape(entity, 'create').items
160
- .filter((it: any) => !it.optional)
161
- Content(`#### Example: Create
162
-
163
- \`\`\`haskell
164
- ent <- Sdk.${eFn} sdk VNoval
165
- d <- jo
166
- [`)
167
- createItems.map((it: any, i: number) => {
168
- const bracket = 0 === i ? ' ' : ', '
169
- Content(`${bracket}("${it.name}", ${hsLit(it.type, 'example_' + it.name)}) -- ${hsType(it.type)}
170
- `)
171
- })
172
- Content(`]
173
- ctrl <- emptyMap
174
- ${eFn} <- Sdk.eCreate ent d ctrl
175
- ${eFn}Data <- Sdk.eDataGet ${eFn}
176
- \`\`\`
177
-
178
- `)
179
- }
180
- })
181
- })
182
-
183
-
184
- export {
185
- ReadmeEntity
186
- }