@voxgig/sdkgen 1.5.1 → 2.0.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.
- package/dist/cmp/AgentGuideContent.js +5 -0
- package/dist/cmp/AgentGuideContent.js.map +1 -1
- package/dist/cmp/Feature.js +13 -0
- package/dist/cmp/Feature.js.map +1 -1
- package/dist/helpers/canonType.d.ts +3 -1
- package/dist/helpers/canonType.js +44 -1
- package/dist/helpers/canonType.js.map +1 -1
- package/dist/helpers/packageMeta.js +7 -0
- package/dist/helpers/packageMeta.js.map +1 -1
- package/dist/sdkgen.d.ts +3 -3
- package/dist/sdkgen.js +4 -1
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/project/.sdk/model/feature/paging.aontu +7 -0
- package/project/.sdk/model/target/py-data.aontu +64 -0
- package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +89 -1
- package/project/.sdk/src/cmp/clojure/Main_clojure.ts +1 -0
- package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +97 -0
- package/project/.sdk/src/cmp/dart/fragment/Main.fragment.dart +78 -0
- package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +84 -0
- package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +87 -0
- package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +75 -0
- package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +85 -0
- package/project/.sdk/src/cmp/ocaml/Main_ocaml.ts +4 -0
- package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +80 -0
- package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +86 -0
- package/project/.sdk/src/cmp/py/Entity_py.ts +9 -2
- package/project/.sdk/src/cmp/py/MainEntity_py.ts +1 -1
- package/project/.sdk/src/cmp/py/Main_py.ts +34 -6
- package/project/.sdk/src/cmp/py/Package_py.ts +6 -9
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +2 -2
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +3 -3
- package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +2 -2
- package/project/.sdk/src/cmp/py/fragment/EntityCreateOp.fragment.py +2 -2
- package/project/.sdk/src/cmp/py/fragment/EntityLoadOp.fragment.py +2 -2
- package/project/.sdk/src/cmp/py/fragment/EntityRemoveOp.fragment.py +2 -2
- package/project/.sdk/src/cmp/py/fragment/EntityUpdateOp.fragment.py +2 -2
- package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +75 -8
- package/project/.sdk/src/cmp/py-data/Main_py-data.ts +987 -0
- package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +71 -0
- package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +95 -0
- package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +86 -0
- package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +75 -0
- package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +95 -0
- package/project/.sdk/tm/c/core/sdk.h +7 -0
- package/project/.sdk/tm/c/feature/paging.c +141 -2
- package/project/.sdk/tm/c/utility/graphql.c +178 -0
- package/project/.sdk/tm/c/utility/make_options.c +1 -1
- package/project/.sdk/tm/c/utility/make_response.c +6 -0
- package/project/.sdk/tm/c/utility/make_spec.c +23 -3
- package/project/.sdk/tm/clojure/src/sdk/client.clj +64 -1
- package/project/.sdk/tm/clojure/src/sdk/core.clj +126 -3
- package/project/.sdk/tm/clojure/src/sdk/features.clj +80 -14
- package/project/.sdk/tm/cpp/core/types.hpp +83 -0
- package/project/.sdk/tm/cpp/feature/paging.hpp +103 -1
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +152 -3
- package/project/.sdk/tm/csharp/core/Utility.cs +4 -0
- package/project/.sdk/tm/csharp/feature/PagingFeature.cs +118 -1
- package/project/.sdk/tm/csharp/utility/Graphql.cs +190 -0
- package/project/.sdk/tm/csharp/utility/MakeOptions.cs +1 -1
- package/project/.sdk/tm/csharp/utility/MakeResponse.cs +7 -0
- package/project/.sdk/tm/csharp/utility/MakeSpec.cs +21 -2
- package/project/.sdk/tm/csharp/utility/Register.cs +2 -0
- package/project/.sdk/tm/dart/lib/Point.dart +7 -0
- package/project/.sdk/tm/dart/lib/feature/paging/PagingFeature.dart +99 -4
- package/project/.sdk/tm/dart/lib/utility/GraphqlUtility.dart +162 -0
- package/project/.sdk/tm/dart/lib/utility/MakeOptionsUtility.dart +1 -1
- package/project/.sdk/tm/dart/lib/utility/MakeResponseUtility.dart +5 -0
- package/project/.sdk/tm/dart/lib/utility/MakeSpecUtility.dart +18 -2
- package/project/.sdk/tm/dart/lib/utility/PrepareMethodUtility.dart +6 -1
- package/project/.sdk/tm/dart/lib/utility/Utility.dart +9 -0
- package/project/.sdk/tm/elixir/lib/projectname/feature/paging.ex +136 -13
- package/project/.sdk/tm/elixir/lib/projectname/utility.ex +187 -3
- package/project/.sdk/tm/go/core/utility_type.go +2 -0
- package/project/.sdk/tm/go/feature/paging_feature.go +87 -1
- package/project/.sdk/tm/go/utility/graphql.go +168 -0
- package/project/.sdk/tm/go/utility/make_options.go +1 -1
- package/project/.sdk/tm/go/utility/make_response.go +6 -0
- package/project/.sdk/tm/go/utility/make_spec.go +19 -2
- package/project/.sdk/tm/go/utility/register.go +2 -0
- package/project/.sdk/tm/haskell/src/SdkFeatures.hs +146 -7
- package/project/.sdk/tm/haskell/src/SdkRuntime.hs +153 -3
- package/project/.sdk/tm/java/core/SdkClient.java +93 -0
- package/project/.sdk/tm/java/core/Utility.java +4 -0
- package/project/.sdk/tm/java/feature/PagingFeature.java +100 -1
- package/project/.sdk/tm/java/utility/Graphql.java +191 -0
- package/project/.sdk/tm/java/utility/MakeOptions.java +1 -1
- package/project/.sdk/tm/java/utility/MakeResponse.java +6 -0
- package/project/.sdk/tm/java/utility/MakeSpec.java +17 -2
- package/project/.sdk/tm/java/utility/Register.java +2 -0
- package/project/.sdk/tm/js/src/Point.js +5 -0
- package/project/.sdk/tm/js/src/feature/paging/PagingFeature.js +82 -3
- package/project/.sdk/tm/js/src/feature/test/TestFeature.js +14 -2
- package/project/.sdk/tm/js/src/utility/GraphqlUtility.js +148 -0
- package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +1 -1
- package/project/.sdk/tm/js/src/utility/MakeResponseUtility.js +7 -0
- package/project/.sdk/tm/js/src/utility/MakeSpecUtility.js +19 -2
- package/project/.sdk/tm/js/src/utility/Utility.js +4 -0
- package/project/.sdk/tm/kotlin/core/SdkClient.kt +84 -0
- package/project/.sdk/tm/kotlin/core/Utility.kt +2 -0
- package/project/.sdk/tm/kotlin/feature/PagingFeature.kt +92 -1
- package/project/.sdk/tm/kotlin/utility/Graphql.kt +145 -0
- package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +1 -1
- package/project/.sdk/tm/kotlin/utility/MakeReqRes.kt +6 -0
- package/project/.sdk/tm/kotlin/utility/MakeSpecUrl.kt +17 -2
- package/project/.sdk/tm/kotlin/utility/Register.kt +2 -0
- package/project/.sdk/tm/lean/src/SdkUtility.lean +134 -1
- package/project/.sdk/tm/lua/feature/paging_feature.lua +97 -2
- package/project/.sdk/tm/lua/utility/graphql.lua +163 -0
- package/project/.sdk/tm/lua/utility/make_options.lua +1 -1
- package/project/.sdk/tm/lua/utility/make_response.lua +6 -0
- package/project/.sdk/tm/lua/utility/make_spec.lua +18 -2
- package/project/.sdk/tm/lua/utility/register.lua +3 -0
- package/project/.sdk/tm/ocaml/sdk_features.ml +164 -20
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +143 -4
- package/project/.sdk/tm/ocaml/sdk_types.ml +2 -0
- package/project/.sdk/tm/perl/feature/paging_feature.pm +91 -3
- package/project/.sdk/tm/perl/utility/graphql.pm +150 -0
- package/project/.sdk/tm/perl/utility/make_options.pm +1 -1
- package/project/.sdk/tm/perl/utility/make_response.pm +6 -0
- package/project/.sdk/tm/perl/utility/make_spec.pm +20 -2
- package/project/.sdk/tm/perl/utility/register.pm +1 -0
- package/project/.sdk/tm/php/core/UtilityType.php +2 -0
- package/project/.sdk/tm/php/feature/PagingFeature.php +106 -4
- package/project/.sdk/tm/php/utility/Graphql.php +176 -0
- package/project/.sdk/tm/php/utility/MakeOptions.php +1 -1
- package/project/.sdk/tm/php/utility/MakeResponse.php +7 -0
- package/project/.sdk/tm/php/utility/MakeSpec.php +20 -2
- package/project/.sdk/tm/php/utility/Register.php +3 -0
- package/project/.sdk/tm/py/pkg/core/__init__.py +0 -0
- package/project/.sdk/tm/py/{core → pkg/core}/context.py +8 -8
- package/project/.sdk/tm/py/{core → pkg/core}/operation.py +1 -1
- package/project/.sdk/tm/py/{core → pkg/core}/response.py +1 -1
- package/project/.sdk/tm/py/{core → pkg/core}/result.py +1 -1
- package/project/.sdk/tm/py/{core → pkg/core}/utility_type.py +2 -0
- package/project/.sdk/tm/py/pkg/entity/__init__.py +0 -0
- package/project/.sdk/tm/py/pkg/feature/__init__.py +0 -0
- package/project/.sdk/tm/py/{feature → pkg/feature}/audit_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/cache_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/clienttrack_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/debug_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/idempotency_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/log_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/metrics_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/netsim_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/paging_feature.py +87 -6
- package/project/.sdk/tm/py/{feature → pkg/feature}/proxy_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/ratelimit_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/rbac_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/retry_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/streaming_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/telemetry_feature.py +1 -1
- package/project/.sdk/tm/py/{feature → pkg/feature}/test_feature.py +2 -2
- package/project/.sdk/tm/py/{feature → pkg/feature}/timeout_feature.py +1 -1
- package/project/.sdk/tm/py/pkg/utility/__init__.py +0 -0
- package/project/.sdk/tm/py/{utility → pkg/utility}/feature_init.py +1 -1
- package/project/.sdk/tm/py/{utility → pkg/utility}/fetcher.py +1 -1
- package/project/.sdk/tm/py/pkg/utility/graphql.py +145 -0
- package/project/.sdk/tm/py/{utility → pkg/utility}/make_context.py +1 -1
- package/project/.sdk/tm/py/{utility → pkg/utility}/make_error.py +5 -5
- package/project/.sdk/tm/py/{utility → pkg/utility}/make_fetch_def.py +2 -2
- package/project/.sdk/tm/py/{utility → pkg/utility}/make_options.py +2 -2
- package/project/.sdk/tm/py/{utility → pkg/utility}/make_point.py +2 -2
- package/project/.sdk/tm/py/{utility → pkg/utility}/make_request.py +2 -2
- package/project/.sdk/tm/py/{utility → pkg/utility}/make_response.py +6 -0
- package/project/.sdk/tm/py/{utility → pkg/utility}/make_spec.py +19 -4
- package/project/.sdk/tm/py/{utility → pkg/utility}/make_url.py +1 -1
- package/project/.sdk/tm/py/{utility → pkg/utility}/param.py +2 -2
- package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_auth.py +1 -1
- package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_headers.py +1 -1
- package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_method.py +1 -1
- package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_params.py +1 -1
- package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_path.py +1 -1
- package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_query.py +1 -1
- package/project/.sdk/tm/py/pkg/utility/register.py +71 -0
- package/project/.sdk/tm/py/{utility → pkg/utility}/transform_request.py +2 -2
- package/project/.sdk/tm/py/{utility → pkg/utility}/transform_response.py +2 -2
- package/project/.sdk/tm/py/test/feature_harness.py +6 -6
- package/project/.sdk/tm/py/test/runner.py +1 -1
- package/project/.sdk/tm/py/test/struct_runner.py +1 -1
- package/project/.sdk/tm/py/test/test_pipeline.py +5 -5
- package/project/.sdk/tm/py/test/test_primary_utility.py +8 -8
- package/project/.sdk/tm/py/test/test_struct_utility.py +3 -3
- package/project/.sdk/tm/py-data/LICENSE +22 -0
- package/project/.sdk/tm/py-data/Makefile +57 -0
- package/project/.sdk/tm/py-data/pkg/auth.py +131 -0
- package/project/.sdk/tm/py-data/pkg/fetch.py +178 -0
- package/project/.sdk/tm/py-data/pkg/frames.py +236 -0
- package/project/.sdk/tm/py-data/src/feature/README.md +8 -0
- package/project/.sdk/tm/py-data/src/feature/debug/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/idempotency/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/log/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/metrics/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/netsim/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/paging/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/proxy/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/ratelimit/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/rbac/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/retry/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/streaming/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/telemetry/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/test/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/src/feature/timeout/.gitkeep +0 -0
- package/project/.sdk/tm/py-data/test/__init__.py +0 -0
- package/project/.sdk/tm/py-data/test/test_auth.py +95 -0
- package/project/.sdk/tm/py-data/test/test_fetch.py +152 -0
- package/project/.sdk/tm/py-data/test/test_frames.py +250 -0
- package/project/.sdk/tm/rb/core/utility_type.rb +1 -0
- package/project/.sdk/tm/rb/feature/paging_feature.rb +89 -3
- package/project/.sdk/tm/rb/utility/graphql.rb +131 -0
- package/project/.sdk/tm/rb/utility/make_options.rb +1 -1
- package/project/.sdk/tm/rb/utility/make_response.rb +6 -0
- package/project/.sdk/tm/rb/utility/make_spec.rb +18 -2
- package/project/.sdk/tm/rb/utility/register.rb +3 -0
- package/project/.sdk/tm/rust/feature/paging.rs +124 -2
- package/project/.sdk/tm/rust/utility/graphql.rs +193 -0
- package/project/.sdk/tm/rust/utility/make_options.rs +1 -1
- package/project/.sdk/tm/rust/utility/make_response.rs +6 -0
- package/project/.sdk/tm/rust/utility/make_spec.rs +32 -4
- package/project/.sdk/tm/rust/utility/mod.rs +1 -0
- package/project/.sdk/tm/scala/core/SdkClient.scala +90 -0
- package/project/.sdk/tm/scala/core/Utility.scala +4 -0
- package/project/.sdk/tm/scala/feature/PagingFeature.scala +104 -3
- package/project/.sdk/tm/scala/utility/Graphql.scala +160 -0
- package/project/.sdk/tm/scala/utility/Make.scala +7 -1
- package/project/.sdk/tm/scala/utility/MakeSpec.scala +22 -2
- package/project/.sdk/tm/scala/utility/Register.scala +2 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Utility.swift +4 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/PagingFeature.swift +86 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Graphql.swift +142 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Make.swift +24 -2
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +1 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Register.swift +2 -0
- package/project/.sdk/tm/ts/src/Point.ts +7 -0
- package/project/.sdk/tm/ts/src/feature/paging/PagingFeature.ts +82 -3
- package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +14 -2
- package/project/.sdk/tm/ts/src/utility/GraphqlUtility.ts +152 -0
- package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +1 -1
- package/project/.sdk/tm/ts/src/utility/MakeResponseUtility.ts +7 -0
- package/project/.sdk/tm/ts/src/utility/MakeSpecUtility.ts +19 -2
- package/project/.sdk/tm/ts/src/utility/Utility.ts +4 -0
- package/project/.sdk/tm/zig/core/utility.zig +198 -3
- package/project/.sdk/tm/zig/feature/paging.zig +128 -1
- package/src/cmp/AgentGuideContent.ts +5 -0
- package/src/cmp/Feature.ts +13 -0
- package/src/helpers/canonType.ts +46 -0
- package/src/helpers/packageMeta.ts +7 -0
- package/src/sdkgen.ts +6 -1
- package/project/.sdk/tm/py/utility/register.py +0 -68
- /package/project/.sdk/tm/py/{core → pkg/core}/control.py +0 -0
- /package/project/.sdk/tm/py/{core → pkg/core}/error.py +0 -0
- /package/project/.sdk/tm/py/{core → pkg/core}/helpers.py +0 -0
- /package/project/.sdk/tm/py/{core → pkg/core}/spec.py +0 -0
- /package/project/.sdk/tm/py/{feature → pkg/feature}/base_feature.py +0 -0
- /package/project/.sdk/tm/py/{utility → pkg/utility}/clean.py +0 -0
- /package/project/.sdk/tm/py/{utility → pkg/utility}/done.py +0 -0
- /package/project/.sdk/tm/py/{utility → pkg/utility}/feature_add.py +0 -0
- /package/project/.sdk/tm/py/{utility → pkg/utility}/feature_hook.py +0 -0
- /package/project/.sdk/tm/py/{utility → pkg/utility}/make_result.py +0 -0
- /package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_body.py +0 -0
- /package/project/.sdk/tm/py/{utility → pkg/utility}/result_basic.py +0 -0
- /package/project/.sdk/tm/py/{utility → pkg/utility}/result_body.py +0 -0
- /package/project/.sdk/tm/py/{utility → pkg/utility}/result_headers.py +0 -0
- /package/project/.sdk/tm/py/{utility → pkg/utility}/voxgig_struct/__init__.py +0 -0
- /package/project/.sdk/tm/py/{utility → pkg/utility}/voxgig_struct/voxgig_struct.py +0 -0
- /package/project/.sdk/tm/{py/core/__init__.py → py-data/src/feature/audit/.gitkeep} +0 -0
- /package/project/.sdk/tm/{py/entity/__init__.py → py-data/src/feature/base/.gitkeep} +0 -0
- /package/project/.sdk/tm/{py/feature/__init__.py → py-data/src/feature/cache/.gitkeep} +0 -0
- /package/project/.sdk/tm/{py/utility/__init__.py → py-data/src/feature/clienttrack/.gitkeep} +0 -0
|
@@ -179,7 +179,41 @@ function ProjectNameSDK:prepare(fetchargs)
|
|
|
179
179
|
end
|
|
180
180
|
|
|
181
181
|
|
|
182
|
+
-- Raw endpoint access is operator-controllable, like every entity op.
|
|
183
|
+
-- Blocking it means denying BOTH the 'direct' and 'graphql' tokens, since
|
|
184
|
+
-- either one reaches the same endpoint.
|
|
182
185
|
function ProjectNameSDK:direct(fetchargs)
|
|
186
|
+
if not self:_op_allowed("direct") then
|
|
187
|
+
return self:_op_denied("direct"), nil
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
return self:_raw_request(fetchargs)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
-- Is this raw-access op permitted by the SDK's allow.op option?
|
|
195
|
+
function ProjectNameSDK:_op_allowed(op)
|
|
196
|
+
local allow = vs.getpath(self.options, "allow.op")
|
|
197
|
+
return type(allow) == "string" and allow:find(op, 1, true) ~= nil
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
function ProjectNameSDK:_op_denied(op)
|
|
202
|
+
local allow = vs.getpath(self.options, "allow.op")
|
|
203
|
+
if type(allow) ~= "string" then allow = "" end
|
|
204
|
+
return {
|
|
205
|
+
ok = false,
|
|
206
|
+
err = "ProjectNameSDK: " .. op .. ": operation not allowed by" ..
|
|
207
|
+
" SDK option allow.op value: \"" .. allow .. "\"",
|
|
208
|
+
}
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
-- Ungated request path shared by direct and graphql, each of which checks its
|
|
213
|
+
-- own allow.op token first. Private, rather than a flag on fetchargs: a
|
|
214
|
+
-- caller-supplied marker would let anyone opt straight back out of the gate
|
|
215
|
+
-- by passing it.
|
|
216
|
+
function ProjectNameSDK:_raw_request(fetchargs)
|
|
183
217
|
local utility = self._utility
|
|
184
218
|
|
|
185
219
|
local fetchdef, err = self:prepare(fetchargs)
|
|
@@ -248,6 +282,57 @@ function ProjectNameSDK:direct(fetchargs)
|
|
|
248
282
|
end
|
|
249
283
|
|
|
250
284
|
|
|
285
|
+
-- Raw GraphQL access: the pressure valve that makes the generated surface's
|
|
286
|
+
-- deliberate omissions (per-call selection sets, typed filter builders,
|
|
287
|
+
-- batching, subscriptions) livable — the whole schema stays reachable.
|
|
288
|
+
--
|
|
289
|
+
-- Thin wrapper over the same prepare/fetch path direct uses, with the one
|
|
290
|
+
-- thing raw direct cannot do for GraphQL: a GraphQL failure rides HTTP 200 as
|
|
291
|
+
-- a top-level `errors` array, so status alone would report a failed query as
|
|
292
|
+
-- ok.
|
|
293
|
+
--
|
|
294
|
+
-- NOTE: like direct, this bypasses the feature pipeline — no retry, ratelimit
|
|
295
|
+
-- or paging features apply.
|
|
296
|
+
function ProjectNameSDK:graphql(query, variables, ctrl)
|
|
297
|
+
if not self:_op_allowed("graphql") then
|
|
298
|
+
return self:_op_denied("graphql"), nil
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
local res, err = self:_raw_request({
|
|
302
|
+
method = "POST",
|
|
303
|
+
headers = { ["content-type"] = "application/json" },
|
|
304
|
+
body = {
|
|
305
|
+
query = query,
|
|
306
|
+
variables = type(variables) == "table" and variables or {},
|
|
307
|
+
},
|
|
308
|
+
ctrl = type(ctrl) == "table" and ctrl or {},
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
if err ~= nil or type(res) ~= "table" then
|
|
312
|
+
return res, err
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
-- Errors are read BEFORE any status check: a GraphQL parse or validation
|
|
316
|
+
-- failure comes back as HTTP 400 carrying the standard { errors = {...} }
|
|
317
|
+
-- body, and the raw path represents a non-2xx as ok=false with no err — so
|
|
318
|
+
-- returning early on status would discard the server's own diagnostics,
|
|
319
|
+
-- which are the only useful part of that response.
|
|
320
|
+
local errors = vs.getpath(res, "data.errors")
|
|
321
|
+
|
|
322
|
+
if type(errors) == "table" and 0 < #errors then
|
|
323
|
+
local msg = vs.getprop(errors[1], "message")
|
|
324
|
+
if type(msg) ~= "string" or msg == "" then
|
|
325
|
+
msg = "graphql error"
|
|
326
|
+
end
|
|
327
|
+
res.ok = false
|
|
328
|
+
res.err = "ProjectNameSDK: graphql: " .. msg
|
|
329
|
+
res.graphql = errors
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
return res, nil
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
|
|
251
336
|
-- <[SLOT]>
|
|
252
337
|
|
|
253
338
|
|
|
@@ -94,6 +94,10 @@ let test_with (testopts : value) (sdkopts : value) : sdk_client =
|
|
|
94
94
|
let direct (client : sdk_client) (fetchargs : value) : value =
|
|
95
95
|
Sdk_features.direct client fetchargs
|
|
96
96
|
|
|
97
|
+
let graphql (client : sdk_client) (query : string) (variables : value)
|
|
98
|
+
(ctrl : value) : value =
|
|
99
|
+
Sdk_features.graphql client query variables ctrl
|
|
100
|
+
|
|
97
101
|
let prepare (client : sdk_client) (fetchargs : value) : value =
|
|
98
102
|
Sdk_features.prepare client fetchargs
|
|
99
103
|
`)
|
|
@@ -172,8 +172,41 @@ sub prepare {
|
|
|
172
172
|
return $fetchdef;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
# Raw endpoint access is operator-controllable, like every entity op.
|
|
176
|
+
# Blocking it means denying BOTH the 'direct' and 'graphql' tokens, since
|
|
177
|
+
# either one reaches the same endpoint.
|
|
175
178
|
sub direct {
|
|
176
179
|
my ($self, $fetchargs) = @_;
|
|
180
|
+
|
|
181
|
+
return $self->_op_denied('direct') unless $self->_op_allowed('direct');
|
|
182
|
+
|
|
183
|
+
return $self->_raw_request($fetchargs);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
# Is this raw-access op permitted by the SDK's allow.op option?
|
|
187
|
+
sub _op_allowed {
|
|
188
|
+
my ($self, $op) = @_;
|
|
189
|
+
my $allow = ProjectNameHelpers::gpath($self->{options}, 'allow.op');
|
|
190
|
+
return (defined $allow && !ref $allow && index($allow, $op) >= 0) ? 1 : 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
sub _op_denied {
|
|
194
|
+
my ($self, $op) = @_;
|
|
195
|
+
my $allow = ProjectNameHelpers::gpath($self->{options}, 'allow.op');
|
|
196
|
+
$allow = '' unless defined $allow && !ref $allow;
|
|
197
|
+
return {
|
|
198
|
+
'ok' => 0,
|
|
199
|
+
'err' => "ProjectNameSDK: $op: operation not allowed by" .
|
|
200
|
+
" SDK option allow.op value: \"$allow\"",
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
# Ungated request path shared by direct and graphql, each of which checks its
|
|
205
|
+
# own allow.op token first. Private, rather than a flag on fetchargs: a
|
|
206
|
+
# caller-supplied marker would let anyone opt straight back out of the gate
|
|
207
|
+
# by passing it.
|
|
208
|
+
sub _raw_request {
|
|
209
|
+
my ($self, $fetchargs) = @_;
|
|
177
210
|
my $utility = $self->{_utility};
|
|
178
211
|
|
|
179
212
|
# direct() is the raw-HTTP escape hatch: it always returns a result hash
|
|
@@ -240,6 +273,53 @@ sub direct {
|
|
|
240
273
|
};
|
|
241
274
|
}
|
|
242
275
|
|
|
276
|
+
# Raw GraphQL access: the pressure valve that makes the generated surface's
|
|
277
|
+
# deliberate omissions (per-call selection sets, typed filter builders,
|
|
278
|
+
# batching, subscriptions) livable — the whole schema stays reachable.
|
|
279
|
+
#
|
|
280
|
+
# Thin wrapper over the same prepare/fetch path direct uses, with the one
|
|
281
|
+
# thing raw direct cannot do for GraphQL: a GraphQL failure rides HTTP 200 as
|
|
282
|
+
# a top-level `errors` array, so status alone would report a failed query as
|
|
283
|
+
# ok.
|
|
284
|
+
#
|
|
285
|
+
# NOTE: like direct, this bypasses the feature pipeline — no retry, ratelimit
|
|
286
|
+
# or paging features apply.
|
|
287
|
+
sub graphql {
|
|
288
|
+
my ($self, $query, $variables, $ctrl) = @_;
|
|
289
|
+
|
|
290
|
+
return $self->_op_denied('graphql') unless $self->_op_allowed('graphql');
|
|
291
|
+
|
|
292
|
+
my $res = $self->_raw_request({
|
|
293
|
+
'method' => 'POST',
|
|
294
|
+
'headers' => { 'content-type' => 'application/json' },
|
|
295
|
+
'body' => {
|
|
296
|
+
'query' => defined $query ? $query : '',
|
|
297
|
+
'variables' => (ref $variables eq 'HASH') ? $variables : {},
|
|
298
|
+
},
|
|
299
|
+
'ctrl' => (ref $ctrl eq 'HASH') ? $ctrl : {},
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
return $res unless ref $res eq 'HASH';
|
|
303
|
+
|
|
304
|
+
# Errors are read BEFORE any status check: a GraphQL parse or validation
|
|
305
|
+
# failure comes back as HTTP 400 carrying the standard { errors: [...] }
|
|
306
|
+
# body, and the raw path represents a non-2xx as ok:0 with no err — so
|
|
307
|
+
# returning early on status would discard the server's own diagnostics,
|
|
308
|
+
# which are the only useful part of that response.
|
|
309
|
+
my $errors = ProjectNameHelpers::gpath($res, 'data.errors');
|
|
310
|
+
|
|
311
|
+
if (ref $errors eq 'ARRAY' && 0 < scalar @$errors) {
|
|
312
|
+
my $first = $errors->[0];
|
|
313
|
+
my $msg = (ref $first eq 'HASH') ? $first->{'message'} : undef;
|
|
314
|
+
$msg = 'graphql error' unless defined $msg && $msg ne '';
|
|
315
|
+
$res->{'ok'} = 0;
|
|
316
|
+
$res->{'err'} = "ProjectNameSDK: graphql: $msg";
|
|
317
|
+
$res->{'graphql'} = $errors;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return $res;
|
|
321
|
+
}
|
|
322
|
+
|
|
243
323
|
# <[SLOT]>
|
|
244
324
|
|
|
245
325
|
sub test {
|
|
@@ -166,7 +166,41 @@ class ProjectNameSDK
|
|
|
166
166
|
return $fetchdef;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
// Raw endpoint access is operator-controllable, like every entity op.
|
|
170
|
+
// Blocking it means denying BOTH the 'direct' and 'graphql' tokens,
|
|
171
|
+
// since either one reaches the same endpoint.
|
|
169
172
|
public function direct(array $fetchargs = []): mixed
|
|
173
|
+
{
|
|
174
|
+
if (!$this->op_allowed("direct")) {
|
|
175
|
+
return $this->op_denied("direct");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return $this->raw_request($fetchargs);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Is this raw-access op permitted by the SDK's allow.op option?
|
|
182
|
+
private function op_allowed(string $op): bool
|
|
183
|
+
{
|
|
184
|
+
$allow_op = Struct::getpath($this->options, "allow.op");
|
|
185
|
+
return is_string($allow_op) && str_contains($allow_op, $op);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private function op_denied(string $op): array
|
|
189
|
+
{
|
|
190
|
+
$allow_op = Struct::getpath($this->options, "allow.op");
|
|
191
|
+
return [
|
|
192
|
+
"ok" => false,
|
|
193
|
+
"err" => new ProjectNameError($op . "_allow",
|
|
194
|
+
"ProjectNameSDK: " . $op . ": operation not allowed by" .
|
|
195
|
+
" SDK option allow.op value: \"" . (string)$allow_op . "\""),
|
|
196
|
+
];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Ungated request path shared by direct and graphql, each of which
|
|
200
|
+
// checks its own allow.op token first. Private, rather than a flag on
|
|
201
|
+
// fetchargs: a caller-supplied marker would let anyone opt straight back
|
|
202
|
+
// out of the gate by passing it.
|
|
203
|
+
private function raw_request(array $fetchargs = []): mixed
|
|
170
204
|
{
|
|
171
205
|
$utility = $this->_utility;
|
|
172
206
|
|
|
@@ -237,6 +271,58 @@ class ProjectNameSDK
|
|
|
237
271
|
];
|
|
238
272
|
}
|
|
239
273
|
|
|
274
|
+
// Raw GraphQL access: the pressure valve that makes the generated
|
|
275
|
+
// surface's deliberate omissions (per-call selection sets, typed filter
|
|
276
|
+
// builders, batching, subscriptions) livable — the whole schema stays
|
|
277
|
+
// reachable.
|
|
278
|
+
//
|
|
279
|
+
// Thin wrapper over the same prepare/fetch path direct uses, with the
|
|
280
|
+
// one thing raw direct cannot do for GraphQL: a GraphQL failure rides
|
|
281
|
+
// HTTP 200 as a top-level `errors` array, so status alone would report
|
|
282
|
+
// a failed query as ok.
|
|
283
|
+
//
|
|
284
|
+
// NOTE: like direct, this bypasses the feature pipeline — no retry,
|
|
285
|
+
// ratelimit or paging features apply.
|
|
286
|
+
public function graphql(string $query, ?array $variables = null, ?array $ctrl = null): mixed
|
|
287
|
+
{
|
|
288
|
+
if (!$this->op_allowed("graphql")) {
|
|
289
|
+
return $this->op_denied("graphql");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
$res = $this->raw_request([
|
|
293
|
+
"method" => "POST",
|
|
294
|
+
"headers" => ["content-type" => "application/json"],
|
|
295
|
+
"body" => ["query" => $query, "variables" => $variables ?? []],
|
|
296
|
+
"ctrl" => $ctrl ?? [],
|
|
297
|
+
]);
|
|
298
|
+
|
|
299
|
+
if (!is_array($res)) {
|
|
300
|
+
return $res;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Errors are read BEFORE any status check: a GraphQL parse or
|
|
304
|
+
// validation failure comes back as HTTP 400 carrying the standard
|
|
305
|
+
// { errors: [...] } body, and the raw path represents a non-2xx as
|
|
306
|
+
// ok:false with no err — so returning early on status would discard
|
|
307
|
+
// the server's own diagnostics, which are the only useful part of
|
|
308
|
+
// that response.
|
|
309
|
+
$errors = Struct::getpath($res, "data.errors");
|
|
310
|
+
|
|
311
|
+
if (is_array($errors) && 0 < count($errors)) {
|
|
312
|
+
$first = is_array($errors[0]) ? $errors[0] : [];
|
|
313
|
+
$msg = $first["message"] ?? "";
|
|
314
|
+
if (!is_string($msg) || "" === $msg) {
|
|
315
|
+
$msg = "graphql error";
|
|
316
|
+
}
|
|
317
|
+
$res["ok"] = false;
|
|
318
|
+
$res["err"] = new ProjectNameError("graphql_error",
|
|
319
|
+
"ProjectNameSDK: graphql: " . $msg);
|
|
320
|
+
$res["graphql"] = $errors;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return $res;
|
|
324
|
+
}
|
|
325
|
+
|
|
240
326
|
// <[SLOT]>
|
|
241
327
|
|
|
242
328
|
public static function test(?array $testopts = null, ?array $sdkopts = null): self
|
|
@@ -41,14 +41,20 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
41
41
|
typeNames.push(opTypeName(entity.Name, opname))
|
|
42
42
|
}
|
|
43
43
|
})
|
|
44
|
-
|
|
44
|
+
// The generated dataclasses live inside the SDK package alongside
|
|
45
|
+
// everything else, so the import is package-qualified.
|
|
46
|
+
const typesModule = model.const.Name.toLowerCase() + '_sdk.' +
|
|
47
|
+
model.const.Name.toLowerCase() + '_types'
|
|
45
48
|
const typeImport =
|
|
46
49
|
'from ' + typesModule + ' import (\n ' +
|
|
47
50
|
typeNames.join(',\n ') + ',\n)'
|
|
48
51
|
|
|
49
52
|
const ff = Path.normalize(__dirname + '/../../../src/cmp/py/fragment/')
|
|
50
53
|
|
|
51
|
-
// Entity files go to entity/
|
|
54
|
+
// Entity files go to <name>_sdk/entity/ — inside the SDK package, not at
|
|
55
|
+
// the language root. See the note in Main_py.ts: a top-level `entity`
|
|
56
|
+
// package is shadowable by any entity.py sitting beside the caller.
|
|
57
|
+
Folder({ name: model.const.Name.toLowerCase() + '_sdk' }, () => {
|
|
52
58
|
Folder({ name: 'entity' }, () => {
|
|
53
59
|
|
|
54
60
|
File({ name: entity.name + '_entity.' + target.ext }, () => {
|
|
@@ -95,6 +101,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
95
101
|
|
|
96
102
|
})
|
|
97
103
|
})
|
|
104
|
+
})
|
|
98
105
|
})
|
|
99
106
|
|
|
100
107
|
|
|
@@ -20,7 +20,7 @@ const MainEntity = cmp(async function MainEntity(props: any) {
|
|
|
20
20
|
Content(`
|
|
21
21
|
def ${entity.Name}(self, data=None) -> "${cls}":
|
|
22
22
|
"""Entity factory: client.${entity.Name}().list() / client.${entity.Name}().load({"id": ...})."""
|
|
23
|
-
from entity.${entity.name}_entity import ${cls}
|
|
23
|
+
from ${model.const.Name.toLowerCase()}_sdk.entity.${entity.name}_entity import ${cls}
|
|
24
24
|
return ${cls}(self, data)
|
|
25
25
|
|
|
26
26
|
`)
|
|
@@ -34,21 +34,47 @@ const Main = cmp(async function Main(props: any) {
|
|
|
34
34
|
const entity: ModelEntity = getModelPath(model, `main.${KIT}.entity`)
|
|
35
35
|
const feature = getModelPath(model, `main.${KIT}.feature`)
|
|
36
36
|
|
|
37
|
+
// The one package directory everything the SDK owns lives in.
|
|
38
|
+
const pkgdir = model.const.Name.toLowerCase() + '_sdk'
|
|
39
|
+
|
|
37
40
|
Package({ target })
|
|
38
41
|
|
|
39
42
|
Gitignore({})
|
|
40
43
|
|
|
41
|
-
//
|
|
44
|
+
// Root-level statics only (Makefile, LICENSE, test/). The runtime
|
|
45
|
+
// packages live under tm/py/pkg and are copied INSIDE the SDK package
|
|
46
|
+
// below.
|
|
42
47
|
Copy({
|
|
43
48
|
from: 'tm/' + target.name,
|
|
44
|
-
exclude: [/src\//],
|
|
49
|
+
exclude: [/src\//, /pkg\//],
|
|
50
|
+
replace: {
|
|
51
|
+
...props.ctx$.stdrep,
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// Everything the SDK owns lives inside ONE package directory.
|
|
56
|
+
//
|
|
57
|
+
// core/, entity/, feature/ and utility/ used to sit at the language root
|
|
58
|
+
// as top-level importable names. `core`, `entity` and `utility` are all
|
|
59
|
+
// real PyPI distributions AND common scratch filenames, and Python puts
|
|
60
|
+
// the working directory first on sys.path — so a single utility.py beside
|
|
61
|
+
// a notebook shadowed ours and the SDK died on
|
|
62
|
+
// `No module named 'utility.voxgig_struct'`. Nesting them behind the
|
|
63
|
+
// model-named package makes that impossible.
|
|
64
|
+
//
|
|
65
|
+
// The public import is unchanged: `from <name>_sdk import <Name>SDK`,
|
|
66
|
+
// because <name>_sdk.py becomes <name>_sdk/__init__.py.
|
|
67
|
+
Folder({ name: pkgdir }, () => {
|
|
68
|
+
|
|
69
|
+
Copy({
|
|
70
|
+
from: 'tm/' + target.name + '/pkg',
|
|
45
71
|
replace: {
|
|
46
72
|
...props.ctx$.stdrep,
|
|
47
73
|
}
|
|
48
74
|
})
|
|
49
75
|
|
|
50
76
|
// Generate main SDK file
|
|
51
|
-
File({ name:
|
|
77
|
+
File({ name: '__init__.' + target.ext }, () => {
|
|
52
78
|
|
|
53
79
|
Fragment(
|
|
54
80
|
{
|
|
@@ -94,7 +120,7 @@ from typing import TYPE_CHECKING
|
|
|
94
120
|
if TYPE_CHECKING:
|
|
95
121
|
`)
|
|
96
122
|
each(entity, (ent: any) => {
|
|
97
|
-
Content(` from entity.${ent.name}_entity import ${entityClassName(ent, entityCollection(model))}
|
|
123
|
+
Content(` from ${model.const.Name.toLowerCase()}_sdk.entity.${ent.name}_entity import ${entityClassName(ent, entityCollection(model))}
|
|
98
124
|
`)
|
|
99
125
|
})
|
|
100
126
|
}
|
|
@@ -119,13 +145,13 @@ if TYPE_CHECKING:
|
|
|
119
145
|
File({ name: 'features.' + target.ext }, () => {
|
|
120
146
|
Content(`# ${model.const.Name} SDK feature factory
|
|
121
147
|
|
|
122
|
-
from feature.base_feature import ${model.const.Name}BaseFeature
|
|
148
|
+
from ${model.const.Name.toLowerCase()}_sdk.feature.base_feature import ${model.const.Name}BaseFeature
|
|
123
149
|
`)
|
|
124
150
|
|
|
125
151
|
each(feature, (feat: any) => {
|
|
126
152
|
if (feat.name !== 'base') {
|
|
127
153
|
const fname = feat.name.charAt(0).toUpperCase() + feat.name.slice(1)
|
|
128
|
-
Content(`from feature.${feat.name}_feature import ${model.const.Name}${fname}Feature
|
|
154
|
+
Content(`from ${model.const.Name.toLowerCase()}_sdk.feature.${feat.name}_feature import ${model.const.Name}${fname}Feature
|
|
129
155
|
`)
|
|
130
156
|
}
|
|
131
157
|
})
|
|
@@ -187,6 +213,8 @@ def _make_feature(name):
|
|
|
187
213
|
})
|
|
188
214
|
})
|
|
189
215
|
|
|
216
|
+
})
|
|
217
|
+
|
|
190
218
|
})
|
|
191
219
|
|
|
192
220
|
|
|
@@ -62,16 +62,13 @@ Homepage = "${repoUrl}"
|
|
|
62
62
|
Repository = "${repoUrl}"
|
|
63
63
|
Issues = "${issuesUrl}"
|
|
64
64
|
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
# Explicit package list — setuptools auto-discovery refuses to pick when
|
|
72
|
-
# multiple top-level dirs (core/entity/feature/utility) are present.
|
|
65
|
+
# ONE package. core/entity/feature/utility were previously top-level packages;
|
|
66
|
+
# those names are real PyPI distributions and common scratch filenames, and
|
|
67
|
+
# Python searches the working directory first, so any of them beside the
|
|
68
|
+
# caller silently shadowed the SDK's own. They now live inside
|
|
69
|
+
# ${model.const.Name.toLowerCase()}_sdk/ where nothing can reach them.
|
|
73
70
|
[tool.setuptools.packages.find]
|
|
74
|
-
include = ["
|
|
71
|
+
include = ["${model.const.Name.toLowerCase()}_sdk*"]
|
|
75
72
|
|
|
76
73
|
# Ship the PEP 561 py.typed marker(s) so the inline type hints reach consumers.
|
|
77
74
|
[tool.setuptools.package-data]
|
|
@@ -137,9 +137,9 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
137
137
|
import json
|
|
138
138
|
import pytest
|
|
139
139
|
|
|
140
|
-
from utility.voxgig_struct import voxgig_struct as vs
|
|
140
|
+
from ${model.const.Name.toLowerCase()}_sdk.utility.voxgig_struct import voxgig_struct as vs
|
|
141
141
|
from ${model.const.Name.toLowerCase()}_sdk import ${model.const.Name}SDK
|
|
142
|
-
from core import helpers
|
|
142
|
+
from ${model.const.Name.toLowerCase()}_sdk.core import helpers
|
|
143
143
|
from test import runner
|
|
144
144
|
|
|
145
145
|
|
|
@@ -94,9 +94,9 @@ import time
|
|
|
94
94
|
|
|
95
95
|
import pytest
|
|
96
96
|
|
|
97
|
-
from utility.voxgig_struct import voxgig_struct as vs
|
|
97
|
+
from ${model.const.Name.toLowerCase()}_sdk.utility.voxgig_struct import voxgig_struct as vs
|
|
98
98
|
from ${model.const.Name.toLowerCase()}_sdk import ${model.const.Name}SDK
|
|
99
|
-
from core import helpers
|
|
99
|
+
from ${model.const.Name.toLowerCase()}_sdk.core import helpers
|
|
100
100
|
|
|
101
101
|
_TEST_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
102
102
|
from test import runner
|
|
@@ -130,7 +130,7 @@ ${hasList ? `
|
|
|
130
130
|
assert len(seen) == 3
|
|
131
131
|
|
|
132
132
|
# Inbound: streaming active -> yields each item from the feature.
|
|
133
|
-
from config import make_config
|
|
133
|
+
from ${model.const.Name.toLowerCase()}_sdk.config import make_config
|
|
134
134
|
cfg = make_config()
|
|
135
135
|
if isinstance(cfg.get("feature"), dict) and "streaming" in cfg["feature"]:
|
|
136
136
|
sdk = ${model.const.Name}SDK.test(
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# ProjectName SDK
|
|
2
2
|
|
|
3
|
-
from utility.voxgig_struct import voxgig_struct as vs
|
|
4
|
-
from core.utility_type import ProjectNameUtility
|
|
5
|
-
from core.spec import ProjectNameSpec
|
|
6
|
-
from core import helpers
|
|
3
|
+
from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
|
|
4
|
+
from projectname_sdk.core.utility_type import ProjectNameUtility
|
|
5
|
+
from projectname_sdk.core.spec import ProjectNameSpec
|
|
6
|
+
from projectname_sdk.core import helpers
|
|
7
7
|
|
|
8
8
|
# Load utility registration (populates Utility._registrar)
|
|
9
|
-
from utility import register
|
|
9
|
+
from projectname_sdk.utility import register
|
|
10
10
|
|
|
11
11
|
# Load features
|
|
12
|
-
from feature.base_feature import ProjectNameBaseFeature
|
|
13
|
-
from features import _make_feature
|
|
12
|
+
from projectname_sdk.feature.base_feature import ProjectNameBaseFeature
|
|
13
|
+
from projectname_sdk.features import _make_feature
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class ProjectNameSDK:
|
|
@@ -23,7 +23,7 @@ class ProjectNameSDK:
|
|
|
23
23
|
utility = ProjectNameUtility()
|
|
24
24
|
self._utility = utility
|
|
25
25
|
|
|
26
|
-
from config import make_config
|
|
26
|
+
from projectname_sdk.config import make_config
|
|
27
27
|
config = make_config()
|
|
28
28
|
|
|
29
29
|
self._rootctx = utility.make_context({
|
|
@@ -155,7 +155,34 @@ class ProjectNameSDK:
|
|
|
155
155
|
|
|
156
156
|
return fetchdef
|
|
157
157
|
|
|
158
|
+
# Raw endpoint access is operator-controllable, like every entity op.
|
|
159
|
+
# Blocking it means denying BOTH the 'direct' and 'graphql' tokens, since
|
|
160
|
+
# either one reaches the same endpoint.
|
|
158
161
|
def direct(self, fetchargs=None):
|
|
162
|
+
if not self._op_allowed("direct"):
|
|
163
|
+
return self._op_denied("direct")
|
|
164
|
+
|
|
165
|
+
return self._raw_request(fetchargs)
|
|
166
|
+
|
|
167
|
+
# Is this raw-access op permitted by the SDK's allow.op option?
|
|
168
|
+
def _op_allowed(self, op):
|
|
169
|
+
allow_op = vs.getpath(self.options, "allow.op")
|
|
170
|
+
return isinstance(allow_op, str) and op in allow_op
|
|
171
|
+
|
|
172
|
+
def _op_denied(self, op):
|
|
173
|
+
allow_op = vs.getpath(self.options, "allow.op")
|
|
174
|
+
return {
|
|
175
|
+
"ok": False,
|
|
176
|
+
"err": Exception(
|
|
177
|
+
"ProjectNameSDK: " + op + ": operation not allowed by"
|
|
178
|
+
' SDK option allow.op value: "' + str(allow_op) + '"'),
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
# Ungated request path shared by direct and graphql, each of which checks
|
|
182
|
+
# its own allow.op token first. Private, rather than a flag on fetchargs:
|
|
183
|
+
# a caller-supplied marker would let anyone opt straight back out of the
|
|
184
|
+
# gate by passing it.
|
|
185
|
+
def _raw_request(self, fetchargs=None):
|
|
159
186
|
utility = self._utility
|
|
160
187
|
|
|
161
188
|
try:
|
|
@@ -222,6 +249,46 @@ class ProjectNameSDK:
|
|
|
222
249
|
"err": ctx.make_error("direct_invalid", "invalid response type"),
|
|
223
250
|
}
|
|
224
251
|
|
|
252
|
+
# Raw GraphQL access: the pressure valve that makes the generated
|
|
253
|
+
# surface's deliberate omissions (per-call selection sets, typed filter
|
|
254
|
+
# builders, batching, subscriptions) livable — the whole schema stays
|
|
255
|
+
# reachable.
|
|
256
|
+
#
|
|
257
|
+
# Thin wrapper over the same prepare/fetch path direct uses, with the one
|
|
258
|
+
# thing raw direct cannot do for GraphQL: a GraphQL failure rides HTTP 200
|
|
259
|
+
# as a top-level `errors` array, so status alone would report a failed
|
|
260
|
+
# query as ok.
|
|
261
|
+
#
|
|
262
|
+
# NOTE: like direct, this bypasses the feature pipeline — no retry,
|
|
263
|
+
# ratelimit or paging features apply.
|
|
264
|
+
def graphql(self, query, variables=None, ctrl=None):
|
|
265
|
+
if not self._op_allowed("graphql"):
|
|
266
|
+
return self._op_denied("graphql")
|
|
267
|
+
|
|
268
|
+
res = self._raw_request({
|
|
269
|
+
"method": "POST",
|
|
270
|
+
"headers": {"content-type": "application/json"},
|
|
271
|
+
"body": {"query": query, "variables": variables or {}},
|
|
272
|
+
"ctrl": ctrl or {},
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
# Errors are read BEFORE any status check: a GraphQL parse or
|
|
276
|
+
# validation failure comes back as HTTP 400 carrying the standard
|
|
277
|
+
# { errors: [...] } body, and the raw path represents a non-2xx as
|
|
278
|
+
# ok:False with no err — so returning early on status would discard
|
|
279
|
+
# the server's own diagnostics, which are the only useful part of
|
|
280
|
+
# that response.
|
|
281
|
+
errors = vs.getpath(res, "data.errors")
|
|
282
|
+
|
|
283
|
+
if isinstance(errors, list) and 0 < len(errors):
|
|
284
|
+
first = errors[0] if isinstance(errors[0], dict) else {}
|
|
285
|
+
msg = first.get("message") or "graphql error"
|
|
286
|
+
res["ok"] = False
|
|
287
|
+
res["err"] = Exception("ProjectNameSDK: graphql: " + str(msg))
|
|
288
|
+
res["graphql"] = errors
|
|
289
|
+
|
|
290
|
+
return res
|
|
291
|
+
|
|
225
292
|
# <[SLOT]>
|
|
226
293
|
|
|
227
294
|
@classmethod
|