@voxgig/sdkgen 1.3.17 → 1.3.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/voxgig-sdkgen +1 -1
- package/dist/cmp/Entity.js +5 -1
- package/dist/cmp/Entity.js.map +1 -1
- package/dist/cmp/Feature.js +2 -1
- package/dist/cmp/Feature.js.map +1 -1
- package/dist/helpers/canonType.js +8 -3
- package/dist/helpers/canonType.js.map +1 -1
- package/dist/helpers/collectDeps.d.ts +1 -1
- package/dist/helpers/collectDeps.js +36 -13
- package/dist/helpers/collectDeps.js.map +1 -1
- package/dist/helpers/naming.d.ts +3 -1
- package/dist/helpers/naming.js +53 -0
- package/dist/helpers/naming.js.map +1 -1
- package/dist/helpers/opShape.d.ts +3 -1
- package/dist/helpers/opShape.js +87 -8
- package/dist/helpers/opShape.js.map +1 -1
- package/dist/sdkgen.d.ts +3 -3
- package/dist/sdkgen.js +6 -2
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +15 -10
- package/project/.sdk/model/target/cpp.aontu +4 -4
- package/project/.sdk/model/target/go-cli.aontu +17 -17
- package/project/.sdk/model/target/go-mcp.aontu +11 -11
- package/project/.sdk/model/target/go.aontu +1 -1
- package/project/.sdk/model/target/java.aontu +4 -4
- package/project/.sdk/model/target/kotlin.aontu +4 -4
- package/project/.sdk/model/target/lean.aontu +51 -0
- package/project/.sdk/model/target/scala.aontu +4 -4
- package/project/.sdk/src/cmp/c/EntityTypes_c.ts +3 -4
- package/project/.sdk/src/cmp/c/Entity_c.ts +3 -3
- package/project/.sdk/src/cmp/c/ReadmeExamplesTest_c.ts +24 -7
- package/project/.sdk/src/cmp/c/TestDirect_c.ts +3 -3
- package/project/.sdk/src/cmp/c/TestEntity_c.ts +1 -1
- package/project/.sdk/src/cmp/clojure/Entity_clojure.ts +1 -1
- package/project/.sdk/src/cmp/clojure/ReadmeExamplesTest_clojure.ts +19 -8
- package/project/.sdk/src/cmp/cpp/EntityTypes_cpp.ts +2 -2
- package/project/.sdk/src/cmp/cpp/Entity_cpp.ts +3 -3
- package/project/.sdk/src/cmp/cpp/MainEntity_cpp.ts +2 -2
- package/project/.sdk/src/cmp/cpp/ReadmeExamplesTest_cpp.ts +136 -0
- package/project/.sdk/src/cmp/cpp/TestDirect_cpp.ts +3 -3
- package/project/.sdk/src/cmp/cpp/Test_cpp.ts +4 -0
- package/project/.sdk/src/cmp/csharp/EntityTypes_csharp.ts +2 -3
- package/project/.sdk/src/cmp/csharp/Entity_csharp.ts +3 -3
- package/project/.sdk/src/cmp/csharp/MainEntity_csharp.ts +2 -2
- package/project/.sdk/src/cmp/csharp/Package_csharp.ts +1 -1
- package/project/.sdk/src/cmp/csharp/ReadmeExamplesTest_csharp.ts +13 -1
- package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +3 -3
- package/project/.sdk/src/cmp/dart/EntityTypes_dart.ts +2 -3
- package/project/.sdk/src/cmp/dart/Entity_dart.ts +3 -3
- package/project/.sdk/src/cmp/dart/MainEntity_dart.ts +2 -2
- package/project/.sdk/src/cmp/dart/Main_dart.ts +3 -3
- package/project/.sdk/src/cmp/dart/Package_dart.ts +1 -1
- package/project/.sdk/src/cmp/dart/TestDirect_dart.ts +4 -4
- package/project/.sdk/src/cmp/elixir/EntityTypes_elixir.ts +2 -3
- package/project/.sdk/src/cmp/elixir/Entity_elixir.ts +1 -1
- package/project/.sdk/src/cmp/elixir/ReadmeExamplesTest_elixir.ts +21 -3
- package/project/.sdk/src/cmp/go/Config_go.ts +4 -1
- package/project/.sdk/src/cmp/go/EntityTypes_go.ts +110 -18
- package/project/.sdk/src/cmp/go/Entity_go.ts +3 -3
- package/project/.sdk/src/cmp/go/Main_go.ts +7 -6
- package/project/.sdk/src/cmp/go/Package_go.ts +1 -1
- package/project/.sdk/src/cmp/go/TestDirect_go.ts +3 -3
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +1 -1
- package/project/.sdk/src/cmp/go/utility_go.ts +25 -0
- package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +9 -1
- package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +9 -1
- package/project/.sdk/src/cmp/haskell/ReadmeExamplesTest_haskell.ts +28 -18
- package/project/.sdk/src/cmp/java/EntityTypes_java.ts +2 -3
- package/project/.sdk/src/cmp/java/Entity_java.ts +3 -3
- package/project/.sdk/src/cmp/java/MainEntity_java.ts +2 -2
- package/project/.sdk/src/cmp/java/Package_java.ts +1 -1
- package/project/.sdk/src/cmp/java/ReadmeExamplesTest_java.ts +23 -1
- package/project/.sdk/src/cmp/java/TestDirect_java.ts +3 -3
- package/project/.sdk/src/cmp/js/EntityTypes_js.ts +2 -3
- package/project/.sdk/src/cmp/js/Entity_js.ts +3 -3
- package/project/.sdk/src/cmp/js/MainEntity_js.ts +2 -2
- package/project/.sdk/src/cmp/js/Main_js.ts +2 -2
- package/project/.sdk/src/cmp/js/TestDirect_js.ts +4 -4
- package/project/.sdk/src/cmp/kotlin/EntityTypes_kotlin.ts +2 -3
- package/project/.sdk/src/cmp/kotlin/Entity_kotlin.ts +3 -3
- package/project/.sdk/src/cmp/kotlin/MainEntity_kotlin.ts +2 -2
- package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +1 -1
- package/project/.sdk/src/cmp/kotlin/ReadmeExamplesTest_kotlin.ts +27 -2
- package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +3 -3
- package/project/.sdk/src/cmp/lean/Config_lean.ts +88 -0
- package/project/.sdk/src/cmp/lean/Entity_lean.ts +9 -0
- package/project/.sdk/src/cmp/lean/Gitignore_lean.ts +18 -0
- package/project/.sdk/src/cmp/lean/Main_lean.ts +120 -0
- package/project/.sdk/src/cmp/lean/Package_lean.ts +68 -0
- package/project/.sdk/src/cmp/lean/ReadmeEntity_lean.ts +29 -0
- package/project/.sdk/src/cmp/lean/ReadmeExplanation_lean.ts +19 -0
- package/project/.sdk/src/cmp/lean/ReadmeHowto_lean.ts +25 -0
- package/project/.sdk/src/cmp/lean/ReadmeInstall_lean.ts +38 -0
- package/project/.sdk/src/cmp/lean/ReadmeIntro_lean.ts +25 -0
- package/project/.sdk/src/cmp/lean/ReadmeModel_lean.ts +24 -0
- package/project/.sdk/src/cmp/lean/ReadmeOptions_lean.ts +22 -0
- package/project/.sdk/src/cmp/lean/ReadmeQuick_lean.ts +50 -0
- package/project/.sdk/src/cmp/lean/ReadmeRef_lean.ts +16 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopHowto_lean.ts +16 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopQuick_lean.ts +23 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopTest_lean.ts +18 -0
- package/project/.sdk/src/cmp/lean/Test_lean.ts +207 -0
- package/project/.sdk/src/cmp/lean/utility_lean.ts +78 -0
- package/project/.sdk/src/cmp/lua/EntityTypes_lua.ts +2 -3
- package/project/.sdk/src/cmp/lua/Entity_lua.ts +3 -3
- package/project/.sdk/src/cmp/lua/Package_lua.ts +1 -1
- package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +3 -3
- package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +1 -1
- package/project/.sdk/src/cmp/ocaml/ReadmeExamplesTest_ocaml.ts +29 -14
- package/project/.sdk/src/cmp/perl/Entity_perl.ts +3 -3
- package/project/.sdk/src/cmp/perl/MainEntity_perl.ts +2 -2
- package/project/.sdk/src/cmp/perl/Package_perl.ts +1 -1
- package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +3 -3
- package/project/.sdk/src/cmp/php/EntityTypes_php.ts +2 -3
- package/project/.sdk/src/cmp/php/Entity_php.ts +3 -3
- package/project/.sdk/src/cmp/php/MainEntity_php.ts +2 -2
- package/project/.sdk/src/cmp/php/Package_php.ts +1 -1
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +3 -3
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +1 -1
- package/project/.sdk/src/cmp/py/EntityTypes_py.ts +2 -3
- package/project/.sdk/src/cmp/py/Entity_py.ts +3 -3
- package/project/.sdk/src/cmp/py/MainEntity_py.ts +2 -2
- package/project/.sdk/src/cmp/py/Main_py.ts +2 -2
- package/project/.sdk/src/cmp/py/Package_py.ts +1 -1
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +3 -3
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +1 -1
- package/project/.sdk/src/cmp/rb/EntityTypes_rb.ts +15 -5
- package/project/.sdk/src/cmp/rb/Entity_rb.ts +3 -3
- package/project/.sdk/src/cmp/rb/MainEntity_rb.ts +2 -2
- package/project/.sdk/src/cmp/rb/Package_rb.ts +2 -2
- package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +3 -3
- package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +1 -1
- package/project/.sdk/src/cmp/rust/EntityBase_rust.ts +2 -2
- package/project/.sdk/src/cmp/rust/EntityTypes_rust.ts +3 -4
- package/project/.sdk/src/cmp/rust/Entity_rust.ts +3 -3
- package/project/.sdk/src/cmp/rust/MainEntity_rust.ts +2 -2
- package/project/.sdk/src/cmp/rust/Package_rust.ts +1 -1
- package/project/.sdk/src/cmp/rust/ReadmeExamplesTest_rust.ts +22 -10
- package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +3 -3
- package/project/.sdk/src/cmp/scala/EntityTypes_scala.ts +2 -3
- package/project/.sdk/src/cmp/scala/Entity_scala.ts +3 -3
- package/project/.sdk/src/cmp/scala/MainEntity_scala.ts +2 -2
- package/project/.sdk/src/cmp/scala/ReadmeExamplesTest_scala.ts +22 -3
- package/project/.sdk/src/cmp/scala/TestDirect_scala.ts +3 -3
- package/project/.sdk/src/cmp/scala/Test_scala.ts +1 -1
- package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +3 -4
- package/project/.sdk/src/cmp/swift/Entity_swift.ts +3 -3
- package/project/.sdk/src/cmp/swift/MainEntity_swift.ts +2 -2
- package/project/.sdk/src/cmp/swift/Package_swift.ts +1 -1
- package/project/.sdk/src/cmp/swift/ReadmeExamplesTest_swift.ts +18 -1
- package/project/.sdk/src/cmp/swift/TestDirect_swift.ts +1 -1
- package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +2 -3
- package/project/.sdk/src/cmp/ts/Entity_ts.ts +3 -3
- package/project/.sdk/src/cmp/ts/MainEntity_ts.ts +2 -2
- package/project/.sdk/src/cmp/ts/Main_ts.ts +2 -2
- package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +4 -4
- package/project/.sdk/src/cmp/zig/Entity_zig.ts +3 -3
- package/project/.sdk/src/cmp/zig/MainEntity_zig.ts +2 -2
- package/project/.sdk/src/cmp/zig/Package_zig.ts +10 -2
- package/project/.sdk/tm/cpp/test/primary_utility_test.cpp +8 -16
- package/project/.sdk/tm/csharp/test/PrimaryUtilityTest.cs +10 -28
- package/project/.sdk/tm/dart/test/primary_test.dart +7 -0
- package/project/.sdk/tm/go/feature/test_feature.go +33 -1
- package/project/.sdk/tm/go/test/primary_utility_test.go +41 -42
- package/project/.sdk/tm/go/test/runner_test.go +30 -1
- package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +7 -24
- package/project/.sdk/tm/js/src/feature/test/TestFeature.js +18 -1
- package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +8 -0
- package/project/.sdk/tm/kotlin/test/PrimaryUtilityTest.kt +7 -20
- package/project/.sdk/tm/lean/LICENSE +21 -0
- package/project/.sdk/tm/lean/VERSION +1 -0
- package/project/.sdk/tm/lean/src/SdkFeature.lean +171 -0
- package/project/.sdk/tm/lean/src/SdkFeatures.lean +602 -0
- package/project/.sdk/tm/lean/src/SdkJson.lean +134 -0
- package/project/.sdk/tm/lean/src/SdkRuntime.lean +356 -0
- package/project/.sdk/tm/lean/src/SdkUtility.lean +617 -0
- package/project/.sdk/tm/lean/src/VoxgigStruct.lean +2880 -0
- package/project/.sdk/tm/lean/src/Vregex.lean +412 -0
- package/project/.sdk/tm/lean/src/feature/README.md +5 -0
- package/project/.sdk/tm/lean/src/feature/audit/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/base/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/cache/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/clienttrack/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/debug/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/idempotency/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/log/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/metrics/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/netsim/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/paging/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/proxy/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/ratelimit/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/rbac/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/retry/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/streaming/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/telemetry/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/test/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/timeout/.gitkeep +0 -0
- package/project/.sdk/tm/lean/test/StructCorpus.lean +697 -0
- package/project/.sdk/tm/lean/test/TFeature.lean +268 -0
- package/project/.sdk/tm/lean/test/TPrimaryUtility.lean +349 -0
- package/project/.sdk/tm/lua/test/primary_utility_test.lua +10 -8
- package/project/.sdk/tm/perl/t/primary_utility.t +8 -17
- package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +9 -7
- package/project/.sdk/tm/py/feature/test_feature.py +28 -1
- package/project/.sdk/tm/py/test/test_primary_utility.py +13 -18
- package/project/.sdk/tm/rb/feature/test_feature.rb +24 -1
- package/project/.sdk/tm/rb/test/primary_utility_test.rb +7 -8
- package/project/.sdk/tm/rust/tests/common/mod.rs +37 -1
- package/project/.sdk/tm/rust/tests/primary_utility_test.rs +12 -26
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PrimaryUtilityTest.swift +7 -8
- package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +18 -1
- package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +65 -21
- package/src/cmp/Entity.ts +5 -1
- package/src/cmp/Feature.ts +2 -1
- package/src/helpers/canonType.ts +8 -3
- package/src/helpers/collectDeps.ts +39 -12
- package/src/helpers/naming.ts +59 -0
- package/src/helpers/opShape.ts +99 -12
- package/src/sdkgen.ts +7 -3
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
/- ProjectName SDK request-shaping utilities (the primary utility layer).
|
|
2
|
+
|
|
3
|
+
These are the language-neutral pipeline utilities the shared test corpus
|
|
4
|
+
(.sdk/test/test.json, section `primary`) exercises in every target. The
|
|
5
|
+
context is a struct `Value` map: heap-backed and reference-stable, so the
|
|
6
|
+
utilities mutate it in place exactly as the IORef/pointer-based donors do,
|
|
7
|
+
and nested `ctx.spec` / `ctx.result` handles stay live across calls. -/
|
|
8
|
+
|
|
9
|
+
import VoxgigStruct
|
|
10
|
+
import SdkJson
|
|
11
|
+
|
|
12
|
+
open VoxgigStruct
|
|
13
|
+
|
|
14
|
+
namespace SdkUtility
|
|
15
|
+
|
|
16
|
+
-- ---------------------------------------------------------------------------
|
|
17
|
+
-- Value helpers
|
|
18
|
+
-- ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
def gp (v : Value) (k : String) : SIO Value := getprop v (.str k) .noval
|
|
21
|
+
|
|
22
|
+
def sp (v : Value) (k : String) (x : Value) : SIO Unit := do
|
|
23
|
+
let _ ← setprop v (.str k) x
|
|
24
|
+
|
|
25
|
+
def dp (v : Value) (k : String) : SIO Unit := do
|
|
26
|
+
let _ ← delprop v (.str k)
|
|
27
|
+
|
|
28
|
+
def vs : Value → String
|
|
29
|
+
| .str s => s
|
|
30
|
+
| _ => ""
|
|
31
|
+
|
|
32
|
+
def isNov : Value → Bool
|
|
33
|
+
| .noval => true
|
|
34
|
+
| _ => false
|
|
35
|
+
|
|
36
|
+
def isMapV : Value → Bool
|
|
37
|
+
| .map _ => true
|
|
38
|
+
| _ => false
|
|
39
|
+
|
|
40
|
+
def truthy : Value → Bool
|
|
41
|
+
| .bool b => b
|
|
42
|
+
| _ => false
|
|
43
|
+
|
|
44
|
+
def gpS (v : Value) (k : String) : SIO String := do pure (vs (← gp v k))
|
|
45
|
+
|
|
46
|
+
/-- Field as a map, creating AND attaching an empty map when absent. -/
|
|
47
|
+
def gpMap (v : Value) (k : String) : SIO Value := do
|
|
48
|
+
match (← gp v k) with
|
|
49
|
+
| .map i => pure (.map i)
|
|
50
|
+
| _ => do
|
|
51
|
+
let m ← emptyMap
|
|
52
|
+
sp v k m
|
|
53
|
+
pure m
|
|
54
|
+
|
|
55
|
+
/-- A map view of a value (empty map when it is not a map); does not attach. -/
|
|
56
|
+
def asMap (v : Value) : SIO Value := do
|
|
57
|
+
match v with
|
|
58
|
+
| .map i => pure (.map i)
|
|
59
|
+
| _ => emptyMap
|
|
60
|
+
|
|
61
|
+
/-- An SDK error value: a struct map tagged `__sdkerr__`. -/
|
|
62
|
+
def mkErr (code msg : String) : SIO Value :=
|
|
63
|
+
newMap #[("__sdkerr__", .bool true), ("code", .str code), ("message", .str msg)]
|
|
64
|
+
|
|
65
|
+
def isErrV (v : Value) : SIO Bool := do
|
|
66
|
+
match v with
|
|
67
|
+
| .map _ => pure (truthy (← gp v "__sdkerr__"))
|
|
68
|
+
| _ => pure false
|
|
69
|
+
|
|
70
|
+
-- ---------------------------------------------------------------------------
|
|
71
|
+
-- Operation naming
|
|
72
|
+
-- ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
def opMethodOf : String → String
|
|
75
|
+
| "create" => "POST"
|
|
76
|
+
| "update" => "PUT"
|
|
77
|
+
| "remove" => "DELETE"
|
|
78
|
+
| "patch" => "PATCH"
|
|
79
|
+
| _ => "GET"
|
|
80
|
+
|
|
81
|
+
def opInputOf : String → String
|
|
82
|
+
| "create" => "data"
|
|
83
|
+
| "update" => "data"
|
|
84
|
+
| _ => "match"
|
|
85
|
+
|
|
86
|
+
/-- The operation name: `ctx.opname`, falling back to `ctx.op.name`. -/
|
|
87
|
+
def opnameOf (ctx : Value) : SIO String := do
|
|
88
|
+
let n ← gpS ctx "opname"
|
|
89
|
+
if n != "" then pure n
|
|
90
|
+
else do gpS (← gp ctx "op") "name"
|
|
91
|
+
|
|
92
|
+
-- ---------------------------------------------------------------------------
|
|
93
|
+
-- makeOptions / makeContext / operator / makeError / done
|
|
94
|
+
-- ---------------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
def defaultOptions : SIO Value := do
|
|
97
|
+
let hdr ← newMap #[("content-type", .str "application/json")]
|
|
98
|
+
let ent ← emptyMap
|
|
99
|
+
newMap #[("base", .str "http://localhost:8000"), ("prefix", .str ""),
|
|
100
|
+
("suffix", .str ""), ("headers", hdr), ("entity", ent)]
|
|
101
|
+
|
|
102
|
+
/-- Defaults <- config.options <- options, then every entity gets an alias map. -/
|
|
103
|
+
def makeOptions (config options : Value) : SIO Value := do
|
|
104
|
+
let base ← defaultOptions
|
|
105
|
+
let copts ← asMap (← gp config "options")
|
|
106
|
+
let uopts ← asMap options
|
|
107
|
+
let parts ← newList #[base, copts, uopts]
|
|
108
|
+
let out ← merge parts
|
|
109
|
+
let ent ← gpMap out "entity"
|
|
110
|
+
for k in (← keysof ent) do
|
|
111
|
+
let e ← gp ent k
|
|
112
|
+
match e with
|
|
113
|
+
| .map _ =>
|
|
114
|
+
match (← gp e "alias") with
|
|
115
|
+
| .map _ => pure ()
|
|
116
|
+
| _ => do
|
|
117
|
+
let a ← emptyMap
|
|
118
|
+
sp e "alias" a
|
|
119
|
+
| _ => pure ()
|
|
120
|
+
pure out
|
|
121
|
+
|
|
122
|
+
def makeContext (ctxmap : Value) : SIO Value := do
|
|
123
|
+
let ctx ← if isMapV ctxmap then pure ctxmap else emptyMap
|
|
124
|
+
let opname ← opnameOf ctx
|
|
125
|
+
let op ← gpMap ctx "op"
|
|
126
|
+
if (← gpS op "name") == "" then sp op "name" (.str opname)
|
|
127
|
+
if (← gpS op "input") == "" then sp op "input" (.str (opInputOf opname))
|
|
128
|
+
pure ctx
|
|
129
|
+
|
|
130
|
+
/-- The Operation record (entity/name/input/points) as a plain map. -/
|
|
131
|
+
def operator (inv : Value) : SIO Value := do
|
|
132
|
+
let ent ← gp inv "entity"
|
|
133
|
+
let nm ← gp inv "name"
|
|
134
|
+
let inp ← gp inv "input"
|
|
135
|
+
let pts ← match (← gp inv "points") with
|
|
136
|
+
| .list i => pure (Value.list i)
|
|
137
|
+
| _ => emptyList
|
|
138
|
+
newMap #[("entity", ent), ("name", nm), ("input", inp), ("points", pts)]
|
|
139
|
+
|
|
140
|
+
def sdkNameOf (ctx : Value) : SIO String := do
|
|
141
|
+
let cfg ← gp ctx "config"
|
|
142
|
+
gpS (← gp cfg "main") "name"
|
|
143
|
+
|
|
144
|
+
/-- "<Name>SDK: <opname>: <message>", with the neutral fallbacks. -/
|
|
145
|
+
def makeError (ctx : Value) (errv : Value) : SIO Value := do
|
|
146
|
+
let nm ← sdkNameOf ctx
|
|
147
|
+
let opn ← opnameOf ctx
|
|
148
|
+
let opname := if opn == "" then "unknown operation" else opn
|
|
149
|
+
let m1 ← match errv with
|
|
150
|
+
| .map _ => gpS errv "message"
|
|
151
|
+
| _ => pure ""
|
|
152
|
+
let rerr ← gp (← gp ctx "result") "err"
|
|
153
|
+
let m2 ← match rerr with
|
|
154
|
+
| .map _ => gpS rerr "message"
|
|
155
|
+
| _ => pure ""
|
|
156
|
+
let msg := if m1 != "" then m1 else if m2 != "" then m2 else "unknown error"
|
|
157
|
+
mkErr "sdk_error" (nm ++ "SDK: " ++ opname ++ ": " ++ msg)
|
|
158
|
+
|
|
159
|
+
/-- Terminal step: the result payload, or the pipeline error. -/
|
|
160
|
+
def done (ctx : Value) : SIO (Value × Option Value) := do
|
|
161
|
+
let res ← gp ctx "result"
|
|
162
|
+
if truthy (← gp res "ok") then pure ((← gp res "resdata"), none)
|
|
163
|
+
else do
|
|
164
|
+
let e ← makeError ctx .noval
|
|
165
|
+
pure (.noval, some e)
|
|
166
|
+
|
|
167
|
+
-- ---------------------------------------------------------------------------
|
|
168
|
+
-- param / prepare*
|
|
169
|
+
-- ---------------------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
/-- Resolve a parameter by name across reqmatch/match/reqdata/data, honouring
|
|
172
|
+
the point's alias map (and recording the reverse alias on the spec). -/
|
|
173
|
+
def param (ctx : Value) (paramdef : Value) : SIO Value := do
|
|
174
|
+
let point ← gp ctx "point"
|
|
175
|
+
let specV ← gp ctx "spec"
|
|
176
|
+
let mtch ← gp ctx "match"
|
|
177
|
+
let reqmatch ← gp ctx "reqmatch"
|
|
178
|
+
let dat ← gp ctx "data"
|
|
179
|
+
let reqdata ← gp ctx "reqdata"
|
|
180
|
+
let key ← match paramdef with
|
|
181
|
+
| .str s => pure s
|
|
182
|
+
| _ => gpS paramdef "name"
|
|
183
|
+
let aliasV ← gp point "alias"
|
|
184
|
+
let akey ← match aliasV with
|
|
185
|
+
| .map _ => gpS aliasV key
|
|
186
|
+
| _ => pure ""
|
|
187
|
+
let v1 ← gp reqmatch key
|
|
188
|
+
let v2 ← if isNov v1 then gp mtch key else pure v1
|
|
189
|
+
let v3 ← if isNov v2 && akey != "" then do
|
|
190
|
+
match specV with
|
|
191
|
+
| .map _ => do
|
|
192
|
+
let sa ← gpMap specV "alias"
|
|
193
|
+
sp sa akey (.str key)
|
|
194
|
+
| _ => pure ()
|
|
195
|
+
gp reqmatch akey
|
|
196
|
+
else pure v2
|
|
197
|
+
let v4 ← if isNov v3 then gp reqdata key else pure v3
|
|
198
|
+
let v5 ← if isNov v4 then gp dat key else pure v4
|
|
199
|
+
if isNov v5 && akey != "" then do
|
|
200
|
+
let a ← gp reqdata akey
|
|
201
|
+
if isNov a then gp dat akey else pure a
|
|
202
|
+
else pure v5
|
|
203
|
+
|
|
204
|
+
/-- Path params declared by the point's args, resolved through `param`. -/
|
|
205
|
+
def prepareParams (ctx : Value) : SIO Value := do
|
|
206
|
+
let point ← gp ctx "point"
|
|
207
|
+
let args ← gp point "args"
|
|
208
|
+
let out ← emptyMap
|
|
209
|
+
match (← gp args "params") with
|
|
210
|
+
| .list i =>
|
|
211
|
+
for pd in (← listItems i) do
|
|
212
|
+
let v ← param ctx pd
|
|
213
|
+
if !(isNov v) then do
|
|
214
|
+
let nm ← match pd with
|
|
215
|
+
| .str s => pure s
|
|
216
|
+
| _ => gpS pd "name"
|
|
217
|
+
if nm != "" then sp out nm v
|
|
218
|
+
| _ => pure ()
|
|
219
|
+
pure out
|
|
220
|
+
|
|
221
|
+
/-- Everything in reqmatch that is NOT a declared path param becomes query. -/
|
|
222
|
+
def prepareQuery (ctx : Value) : SIO Value := do
|
|
223
|
+
let point ← gp ctx "point"
|
|
224
|
+
let reqmatch ← asMap (← gp ctx "reqmatch")
|
|
225
|
+
let names ← match (← gp point "params") with
|
|
226
|
+
| .list i => do pure ((← listItems i).map vs)
|
|
227
|
+
| _ => pure #[]
|
|
228
|
+
let out ← emptyMap
|
|
229
|
+
for k in (← keysof reqmatch) do
|
|
230
|
+
let v ← gp reqmatch k
|
|
231
|
+
if !(isNov v) && !(names.contains k) then sp out k v
|
|
232
|
+
pure out
|
|
233
|
+
|
|
234
|
+
def preparePath (ctx : Value) : SIO String := do
|
|
235
|
+
let point ← gp ctx "point"
|
|
236
|
+
match (← gp point "parts") with
|
|
237
|
+
| .list i => do
|
|
238
|
+
let segs := (← listItems i).map vs
|
|
239
|
+
pure ("/" ++ String.intercalate "/" segs.toList)
|
|
240
|
+
| _ => pure ""
|
|
241
|
+
|
|
242
|
+
def prepareMethod (ctx : Value) : SIO String := do
|
|
243
|
+
pure (opMethodOf (← opnameOf ctx))
|
|
244
|
+
|
|
245
|
+
def prepareHeaders (ctx : Value) : SIO Value := do
|
|
246
|
+
let options ← gp ctx "options"
|
|
247
|
+
match (← gp options "headers") with
|
|
248
|
+
| .map i => clone (.map i)
|
|
249
|
+
| _ => newMap #[("content-type", .str "application/json")]
|
|
250
|
+
|
|
251
|
+
/-- apikey (with the configured auth prefix) becomes the authorization header. -/
|
|
252
|
+
def prepareAuth (ctx : Value) : SIO (Value × Option Value) := do
|
|
253
|
+
let specV ← gp ctx "spec"
|
|
254
|
+
match specV with
|
|
255
|
+
| .map _ => do
|
|
256
|
+
let headers ← gpMap specV "headers"
|
|
257
|
+
let options ← gp ctx "options"
|
|
258
|
+
let apikey ← gpS options "apikey"
|
|
259
|
+
if apikey == "" then do
|
|
260
|
+
dp headers "authorization"
|
|
261
|
+
pure (specV, none)
|
|
262
|
+
else do
|
|
263
|
+
let pfx ← gpS (← gp options "auth") "prefix"
|
|
264
|
+
let authval := if pfx != "" then pfx ++ " " ++ apikey else apikey
|
|
265
|
+
sp headers "authorization" (.str authval)
|
|
266
|
+
pure (specV, none)
|
|
267
|
+
| _ => do
|
|
268
|
+
let e ← mkErr "auth_no_spec" "Expected context spec property to be defined."
|
|
269
|
+
pure (.noval, some e)
|
|
270
|
+
|
|
271
|
+
-- ---------------------------------------------------------------------------
|
|
272
|
+
-- transforms
|
|
273
|
+
-- ---------------------------------------------------------------------------
|
|
274
|
+
|
|
275
|
+
def transformRequest (ctx : Value) : SIO Value := do
|
|
276
|
+
let specV ← gp ctx "spec"
|
|
277
|
+
match specV with
|
|
278
|
+
| .map _ => sp specV "step" (.str "reqform")
|
|
279
|
+
| _ => pure ()
|
|
280
|
+
let point ← gp ctx "point"
|
|
281
|
+
let reqdata ← gp ctx "reqdata"
|
|
282
|
+
match (← gp point "transform") with
|
|
283
|
+
| .map i => do
|
|
284
|
+
let reqform ← gp (.map i) "req"
|
|
285
|
+
if isNov reqform then pure reqdata
|
|
286
|
+
else do
|
|
287
|
+
let input ← newMap #[("reqdata", reqdata)]
|
|
288
|
+
transform input reqform
|
|
289
|
+
| _ => pure reqdata
|
|
290
|
+
|
|
291
|
+
def transformResponse (ctx : Value) : SIO Value := do
|
|
292
|
+
let specV ← gp ctx "spec"
|
|
293
|
+
match specV with
|
|
294
|
+
| .map _ => sp specV "step" (.str "resform")
|
|
295
|
+
| _ => pure ()
|
|
296
|
+
let resultV ← gp ctx "result"
|
|
297
|
+
match resultV with
|
|
298
|
+
| .map _ => do
|
|
299
|
+
if !(truthy (← gp resultV "ok")) then pure .noval
|
|
300
|
+
else do
|
|
301
|
+
let point ← gp ctx "point"
|
|
302
|
+
match (← gp point "transform") with
|
|
303
|
+
| .map i => do
|
|
304
|
+
let resform ← gp (.map i) "res"
|
|
305
|
+
if isNov resform then pure .noval
|
|
306
|
+
else do
|
|
307
|
+
let ok ← gp resultV "ok"
|
|
308
|
+
let status ← gp resultV "status"
|
|
309
|
+
let stt ← gp resultV "statusText"
|
|
310
|
+
let hdr ← gp resultV "headers"
|
|
311
|
+
let body ← gp resultV "body"
|
|
312
|
+
let resdata ← gp resultV "resdata"
|
|
313
|
+
let resmatch ← gp resultV "resmatch"
|
|
314
|
+
let input ← newMap #[("ok", ok), ("status", status), ("statusText", stt),
|
|
315
|
+
("headers", hdr), ("body", body),
|
|
316
|
+
("resdata", resdata), ("resmatch", resmatch)]
|
|
317
|
+
transform input resform
|
|
318
|
+
| _ => pure .noval
|
|
319
|
+
| _ => pure .noval
|
|
320
|
+
|
|
321
|
+
/-- The request body: only data-input operations carry one. -/
|
|
322
|
+
def prepareBody (ctx : Value) : SIO Value := do
|
|
323
|
+
if opInputOf (← opnameOf ctx) == "data" then transformRequest ctx
|
|
324
|
+
else pure .noval
|
|
325
|
+
|
|
326
|
+
-- ---------------------------------------------------------------------------
|
|
327
|
+
-- result assembly
|
|
328
|
+
-- ---------------------------------------------------------------------------
|
|
329
|
+
|
|
330
|
+
def resultBasic (ctx : Value) : SIO Unit := do
|
|
331
|
+
let responseV ← gp ctx "response"
|
|
332
|
+
let resultV ← gp ctx "result"
|
|
333
|
+
match responseV, resultV with
|
|
334
|
+
| .map _, .map _ => do
|
|
335
|
+
let st ← gp responseV "status"
|
|
336
|
+
let stt ← gp responseV "statusText"
|
|
337
|
+
sp resultV "status" st
|
|
338
|
+
sp resultV "statusText" stt
|
|
339
|
+
let status := jsNumber st
|
|
340
|
+
if status >= 400.0 then do
|
|
341
|
+
let msg := "request: " ++ numToString status ++ ": " ++ vs stt
|
|
342
|
+
let prev ← gp resultV "err"
|
|
343
|
+
let pm ← match prev with
|
|
344
|
+
| .map _ => gpS prev "message"
|
|
345
|
+
| _ => pure ""
|
|
346
|
+
let full := if pm != "" then pm ++ ": " ++ msg else msg
|
|
347
|
+
let e ← mkErr "request_status" full
|
|
348
|
+
sp resultV "err" e
|
|
349
|
+
else pure ()
|
|
350
|
+
| _, _ => pure ()
|
|
351
|
+
|
|
352
|
+
/-- Response headers land on the result with lower-cased keys. -/
|
|
353
|
+
def resultHeaders (ctx : Value) : SIO Unit := do
|
|
354
|
+
let resultV ← gp ctx "result"
|
|
355
|
+
match resultV with
|
|
356
|
+
| .map _ => do
|
|
357
|
+
let out ← emptyMap
|
|
358
|
+
let responseV ← gp ctx "response"
|
|
359
|
+
match responseV with
|
|
360
|
+
| .map _ => do
|
|
361
|
+
match (← gp responseV "headers") with
|
|
362
|
+
| .map i =>
|
|
363
|
+
for k in (← keysof (.map i)) do
|
|
364
|
+
let v ← gp (.map i) k
|
|
365
|
+
sp out k.toLower v
|
|
366
|
+
| _ => pure ()
|
|
367
|
+
| _ => pure ()
|
|
368
|
+
sp resultV "headers" out
|
|
369
|
+
| _ => pure ()
|
|
370
|
+
|
|
371
|
+
def resultBody (ctx : Value) : SIO Unit := do
|
|
372
|
+
let responseV ← gp ctx "response"
|
|
373
|
+
let resultV ← gp ctx "result"
|
|
374
|
+
match responseV, resultV with
|
|
375
|
+
| .map _, .map _ => do
|
|
376
|
+
let body ← gp responseV "body"
|
|
377
|
+
if !(isNov body) then sp resultV "body" body
|
|
378
|
+
| _, _ => pure ()
|
|
379
|
+
|
|
380
|
+
-- ---------------------------------------------------------------------------
|
|
381
|
+
-- spec / url / request / response
|
|
382
|
+
-- ---------------------------------------------------------------------------
|
|
383
|
+
|
|
384
|
+
def makeSpec (ctx : Value) : SIO (Value × Option Value) := do
|
|
385
|
+
let options ← gp ctx "options"
|
|
386
|
+
let base ← gpS options "base"
|
|
387
|
+
let pfx ← gpS options "prefix"
|
|
388
|
+
let suffix ← gpS options "suffix"
|
|
389
|
+
let point ← gp ctx "point"
|
|
390
|
+
let parts ← match (← gp point "parts") with
|
|
391
|
+
| .list i => pure (Value.list i)
|
|
392
|
+
| _ => emptyList
|
|
393
|
+
let aliasm ← emptyMap
|
|
394
|
+
let spec ← newMap #[("base", .str base), ("prefix", .str pfx),
|
|
395
|
+
("suffix", .str suffix), ("parts", parts),
|
|
396
|
+
("alias", aliasm), ("step", .str "start")]
|
|
397
|
+
sp ctx "spec" spec
|
|
398
|
+
sp spec "method" (.str (← prepareMethod ctx))
|
|
399
|
+
sp spec "path" (.str (← preparePath ctx))
|
|
400
|
+
sp spec "params" (← prepareParams ctx)
|
|
401
|
+
sp spec "query" (← prepareQuery ctx)
|
|
402
|
+
sp spec "headers" (← prepareHeaders ctx)
|
|
403
|
+
pure (spec, none)
|
|
404
|
+
|
|
405
|
+
/-- base/prefix/path/suffix joined, `{param}` substituted, query appended. -/
|
|
406
|
+
def makeUrl (ctx : Value) : SIO (Value × Option Value) := do
|
|
407
|
+
let specV ← gp ctx "spec"
|
|
408
|
+
match specV with
|
|
409
|
+
| .map _ => do
|
|
410
|
+
let base ← gpS specV "base"
|
|
411
|
+
let pfx ← gpS specV "prefix"
|
|
412
|
+
let path ← gpS specV "path"
|
|
413
|
+
let suffix ← gpS specV "suffix"
|
|
414
|
+
let arr ← newList #[.str base, .str pfx, .str path, .str suffix]
|
|
415
|
+
let url0 ← joinurl arr
|
|
416
|
+
let resmatch ← emptyMap
|
|
417
|
+
let mut url := url0
|
|
418
|
+
let params ← gp specV "params"
|
|
419
|
+
for k in (← keysof params) do
|
|
420
|
+
let v ← gp params k
|
|
421
|
+
if !(isNov v) then do
|
|
422
|
+
let enc ← escurl (.str (vs v))
|
|
423
|
+
sp resmatch k v
|
|
424
|
+
url := url.replace ("{" ++ k ++ "}") (vs enc)
|
|
425
|
+
let query ← gp specV "query"
|
|
426
|
+
let mut qsep := "?"
|
|
427
|
+
for k in (← keysof query) do
|
|
428
|
+
let v ← gp query k
|
|
429
|
+
if !(isNov v) then do
|
|
430
|
+
let ek ← escurl (.str k)
|
|
431
|
+
let ev ← escurl (.str (vs v))
|
|
432
|
+
sp resmatch k v
|
|
433
|
+
url := url ++ qsep ++ vs ek ++ "=" ++ vs ev
|
|
434
|
+
qsep := "&"
|
|
435
|
+
let resultV ← gp ctx "result"
|
|
436
|
+
match resultV with
|
|
437
|
+
| .map _ => sp resultV "resmatch" resmatch
|
|
438
|
+
| _ => pure ()
|
|
439
|
+
pure (.str url, none)
|
|
440
|
+
| _ => do
|
|
441
|
+
let e ← mkErr "url_no_spec" "Expected context spec property to be defined."
|
|
442
|
+
pure (.str "", some e)
|
|
443
|
+
|
|
444
|
+
/-- Prepare the transport call: the response/result carriers must exist. -/
|
|
445
|
+
def makeRequest (ctx : Value) : SIO (Value × Option Value) := do
|
|
446
|
+
let specV ← gp ctx "spec"
|
|
447
|
+
match specV with
|
|
448
|
+
| .map _ => sp specV "step" (.str "request")
|
|
449
|
+
| _ => pure ()
|
|
450
|
+
let _ ← gpMap ctx "response"
|
|
451
|
+
let _ ← gpMap ctx "result"
|
|
452
|
+
pure ((← gp ctx "response"), none)
|
|
453
|
+
|
|
454
|
+
/-- The initial result carrier the pipeline fills in. -/
|
|
455
|
+
def makeResult (ctx : Value) : SIO Value := do
|
|
456
|
+
let resmatch ← emptyMap
|
|
457
|
+
let res ← newMap #[("ok", .bool false), ("status", .num (-1.0)),
|
|
458
|
+
("statusText", .str ""), ("resmatch", resmatch)]
|
|
459
|
+
sp ctx "result" res
|
|
460
|
+
pure res
|
|
461
|
+
|
|
462
|
+
/-- Select the endpoint for this operation: the single point, else the first
|
|
463
|
+
whose `select.exist` keys are all present and whose `$action` agrees. -/
|
|
464
|
+
def makePoint (ctx : Value) : SIO Value := do
|
|
465
|
+
let op ← gp ctx "op"
|
|
466
|
+
let matchV ← gp ctx "reqmatch"
|
|
467
|
+
let dataV ← gp ctx "reqdata"
|
|
468
|
+
let pts ← match (← gp op "points") with
|
|
469
|
+
| .list i => listItems i
|
|
470
|
+
| _ => pure #[]
|
|
471
|
+
if pts.size == 0 then pure .noval
|
|
472
|
+
else if pts.size == 1 then do
|
|
473
|
+
sp ctx "point" (pts[0]!)
|
|
474
|
+
pure (pts[0]!)
|
|
475
|
+
else do
|
|
476
|
+
let mut chosen : Value := .noval
|
|
477
|
+
for pt in pts do
|
|
478
|
+
if isNov chosen then
|
|
479
|
+
let sel ← gp pt "select"
|
|
480
|
+
let mut ok := true
|
|
481
|
+
match (← gp sel "exist") with
|
|
482
|
+
| .list i =>
|
|
483
|
+
for ek in (← listItems i) do
|
|
484
|
+
let k := vs ek
|
|
485
|
+
if isNov (← gp matchV k) && isNov (← gp dataV k) then ok := false
|
|
486
|
+
| _ => pure ()
|
|
487
|
+
if ok && ((← gp sel "$action") == (← gp matchV "$action")) then
|
|
488
|
+
chosen := pt
|
|
489
|
+
if !(isNov chosen) then sp ctx "point" chosen
|
|
490
|
+
pure chosen
|
|
491
|
+
|
|
492
|
+
/-- The transport payload: method, headers and (for data ops) the body. -/
|
|
493
|
+
def makeFetchDef (ctx : Value) : SIO Value := do
|
|
494
|
+
let specV ← gp ctx "spec"
|
|
495
|
+
let method ← gpS specV "method"
|
|
496
|
+
let headers ← asMap (← gp specV "headers")
|
|
497
|
+
let out ← newMap #[("method", .str method), ("headers", headers)]
|
|
498
|
+
let body ← gp specV "body"
|
|
499
|
+
if !(isNov body) then sp out "body" body
|
|
500
|
+
pure out
|
|
501
|
+
|
|
502
|
+
/-- Remove configured sensitive keys (options.clean.keys) from a value. -/
|
|
503
|
+
def clean (ctx : Value) (v : Value) : SIO Value := do
|
|
504
|
+
let options ← gp ctx "options"
|
|
505
|
+
let keysStr ← gpS (← gp options "clean") "keys"
|
|
506
|
+
let drop := if keysStr == "" then #[] else (keysStr.splitOn ",").toArray
|
|
507
|
+
let out ← clone v
|
|
508
|
+
match out with
|
|
509
|
+
| .map _ =>
|
|
510
|
+
for k in drop do
|
|
511
|
+
if k != "" then dp out k
|
|
512
|
+
| _ => pure ()
|
|
513
|
+
pure out
|
|
514
|
+
|
|
515
|
+
/-- The transport step. In test mode the client answers from its own store, so
|
|
516
|
+
this is only reached for live calls; the concrete send is injected by the
|
|
517
|
+
runtime (SdkRuntime.curlFetch) to keep this layer transport-agnostic. -/
|
|
518
|
+
def fetcher (ctx : Value) (url : String) (fetchdef : Value) : SIO Value := do
|
|
519
|
+
let out ← emptyMap
|
|
520
|
+
sp out "url" (.str url)
|
|
521
|
+
sp out "fetchdef" fetchdef
|
|
522
|
+
sp ctx "fetch" out
|
|
523
|
+
pure out
|
|
524
|
+
|
|
525
|
+
-- ---------------------------------------------------------------------------
|
|
526
|
+
-- features
|
|
527
|
+
-- ---------------------------------------------------------------------------
|
|
528
|
+
|
|
529
|
+
/-- The client's ordered feature list. -/
|
|
530
|
+
def featureList (client : Value) : SIO Value := do
|
|
531
|
+
match (← gp client "features") with
|
|
532
|
+
| .list i => pure (Value.list i)
|
|
533
|
+
| _ => do
|
|
534
|
+
let l ← emptyList
|
|
535
|
+
sp client "features" l
|
|
536
|
+
pure l
|
|
537
|
+
|
|
538
|
+
/-- Add a feature, honouring `__before__` / `__after__` / `__replace__`
|
|
539
|
+
placement against the named feature (append by default). -/
|
|
540
|
+
def featureAdd (client : Value) (feat : Value) : SIO Unit := do
|
|
541
|
+
let feats ← featureList client
|
|
542
|
+
let items ← match feats with
|
|
543
|
+
| .list i => listItems i
|
|
544
|
+
| _ => pure #[]
|
|
545
|
+
let nm ← gpS feat "name"
|
|
546
|
+
let before ← gpS feat "__before__"
|
|
547
|
+
let after ← gpS feat "__after__"
|
|
548
|
+
let replace ← gpS feat "__replace__"
|
|
549
|
+
let mut out : Array Value := #[]
|
|
550
|
+
let mut placed := false
|
|
551
|
+
for f in items do
|
|
552
|
+
let fn ← gpS f "name"
|
|
553
|
+
if replace != "" && fn == replace then
|
|
554
|
+
out := out.push feat
|
|
555
|
+
placed := true
|
|
556
|
+
else if before != "" && fn == before then
|
|
557
|
+
out := out.push feat
|
|
558
|
+
out := out.push f
|
|
559
|
+
placed := true
|
|
560
|
+
else if after != "" && fn == after then
|
|
561
|
+
out := out.push f
|
|
562
|
+
out := out.push feat
|
|
563
|
+
placed := true
|
|
564
|
+
else if fn == nm then
|
|
565
|
+
out := out.push feat
|
|
566
|
+
placed := true
|
|
567
|
+
else
|
|
568
|
+
out := out.push f
|
|
569
|
+
if !placed then out := out.push feat
|
|
570
|
+
sp client "features" (← newList out)
|
|
571
|
+
|
|
572
|
+
/-- Initialise every active feature (idempotent: marks `inited`). -/
|
|
573
|
+
def featureInit (client : Value) (ctx : Value) : SIO Unit := do
|
|
574
|
+
let feats ← featureList client
|
|
575
|
+
match feats with
|
|
576
|
+
| .list i =>
|
|
577
|
+
for f in (← listItems i) do
|
|
578
|
+
if truthy (← gp f "active") && !(truthy (← gp f "inited")) then do
|
|
579
|
+
sp f "inited" (.bool true)
|
|
580
|
+
sp f "ctx" ctx
|
|
581
|
+
| _ => pure ()
|
|
582
|
+
|
|
583
|
+
/-- Dispatch a pipeline stage to every active feature that defines the hook. -/
|
|
584
|
+
def featureHook (client : Value) (stage : String) (ctx : Value) : SIO Unit := do
|
|
585
|
+
let feats ← featureList client
|
|
586
|
+
match feats with
|
|
587
|
+
| .list i =>
|
|
588
|
+
for f in (← listItems i) do
|
|
589
|
+
if truthy (← gp f "active") then do
|
|
590
|
+
let hooks ← gp f "hooks"
|
|
591
|
+
let h ← gp hooks stage
|
|
592
|
+
match h with
|
|
593
|
+
| .func fid => do
|
|
594
|
+
let inj ← getDummyInj
|
|
595
|
+
let _ ← callFunc fid inj ctx stage ctx
|
|
596
|
+
pure ()
|
|
597
|
+
| _ => pure ()
|
|
598
|
+
| _ => pure ()
|
|
599
|
+
|
|
600
|
+
/-- Fold the transport response into the result (basic/headers/body/resform). -/
|
|
601
|
+
def makeResponse (ctx : Value) : SIO (Value × Option Value) := do
|
|
602
|
+
let specV ← gp ctx "spec"
|
|
603
|
+
let responseV ← gp ctx "response"
|
|
604
|
+
let resultV ← gp ctx "result"
|
|
605
|
+
match specV, responseV, resultV with
|
|
606
|
+
| .map _, .map _, .map _ => do
|
|
607
|
+
sp specV "step" (.str "response")
|
|
608
|
+
resultBasic ctx
|
|
609
|
+
resultHeaders ctx
|
|
610
|
+
resultBody ctx
|
|
611
|
+
let _ ← transformResponse ctx
|
|
612
|
+
let errv ← gp resultV "err"
|
|
613
|
+
if !(← isErrV errv) then sp resultV "ok" (.bool true)
|
|
614
|
+
pure (responseV, none)
|
|
615
|
+
| _, _, _ => pure (.noval, none)
|
|
616
|
+
|
|
617
|
+
end SdkUtility
|