@voxgig/sdkgen-langpack 0.0.1

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 (300) hide show
  1. package/.sdk/model/target/dart.aon +63 -0
  2. package/.sdk/model/target/haskell.aon +72 -0
  3. package/.sdk/model/target/lean.aon +91 -0
  4. package/.sdk/src/cmp/dart/Config_dart.ts +248 -0
  5. package/.sdk/src/cmp/dart/EntityBase_dart.ts +34 -0
  6. package/.sdk/src/cmp/dart/EntityOperation_dart.ts +43 -0
  7. package/.sdk/src/cmp/dart/EntityTypes_dart.ts +207 -0
  8. package/.sdk/src/cmp/dart/Entity_dart.ts +87 -0
  9. package/.sdk/src/cmp/dart/Gitignore_dart.ts +34 -0
  10. package/.sdk/src/cmp/dart/MainEntity_dart.ts +33 -0
  11. package/.sdk/src/cmp/dart/Main_dart.ts +178 -0
  12. package/.sdk/src/cmp/dart/Package_dart.ts +82 -0
  13. package/.sdk/src/cmp/dart/ReadmeEntity_dart.ts +177 -0
  14. package/.sdk/src/cmp/dart/ReadmeExamplesTest_dart.ts +238 -0
  15. package/.sdk/src/cmp/dart/ReadmeExplanation_dart.ts +53 -0
  16. package/.sdk/src/cmp/dart/ReadmeHowto_dart.ts +152 -0
  17. package/.sdk/src/cmp/dart/ReadmeInstall_dart.ts +59 -0
  18. package/.sdk/src/cmp/dart/ReadmeIntro_dart.ts +65 -0
  19. package/.sdk/src/cmp/dart/ReadmeModel_dart.ts +151 -0
  20. package/.sdk/src/cmp/dart/ReadmeOptions_dart.ts +63 -0
  21. package/.sdk/src/cmp/dart/ReadmeQuick_dart.ts +225 -0
  22. package/.sdk/src/cmp/dart/ReadmeRef_dart.ts +397 -0
  23. package/.sdk/src/cmp/dart/ReadmeTopHowto_dart.ts +24 -0
  24. package/.sdk/src/cmp/dart/ReadmeTopQuick_dart.ts +106 -0
  25. package/.sdk/src/cmp/dart/ReadmeTopTest_dart.ts +78 -0
  26. package/.sdk/src/cmp/dart/SdkError_dart.ts +42 -0
  27. package/.sdk/src/cmp/dart/TestDirect_dart.ts +516 -0
  28. package/.sdk/src/cmp/dart/TestEntity_dart.ts +628 -0
  29. package/.sdk/src/cmp/dart/Test_dart.ts +138 -0
  30. package/.sdk/src/cmp/dart/fragment/Config.data.fragment.dart +98 -0
  31. package/.sdk/src/cmp/dart/fragment/Config.fragment.dart +70 -0
  32. package/.sdk/src/cmp/dart/fragment/Direct.test.fragment.dart +25 -0
  33. package/.sdk/src/cmp/dart/fragment/Entity.fragment.dart +29 -0
  34. package/.sdk/src/cmp/dart/fragment/Entity.test.fragment.dart +28 -0
  35. package/.sdk/src/cmp/dart/fragment/EntityBase.fragment.dart +302 -0
  36. package/.sdk/src/cmp/dart/fragment/EntityCreateOp.fragment.dart +98 -0
  37. package/.sdk/src/cmp/dart/fragment/EntityListOp.fragment.dart +90 -0
  38. package/.sdk/src/cmp/dart/fragment/EntityLoadOp.fragment.dart +102 -0
  39. package/.sdk/src/cmp/dart/fragment/EntityRemoveOp.fragment.dart +108 -0
  40. package/.sdk/src/cmp/dart/fragment/EntityUpdateOp.fragment.dart +102 -0
  41. package/.sdk/src/cmp/dart/fragment/Main.fragment.dart +339 -0
  42. package/.sdk/src/cmp/dart/fragment/SdkError.fragment.dart +26 -0
  43. package/.sdk/src/cmp/dart/tsconfig.json +15 -0
  44. package/.sdk/src/cmp/dart/utility_dart.ts +155 -0
  45. package/.sdk/src/cmp/haskell/Config_haskell.ts +98 -0
  46. package/.sdk/src/cmp/haskell/Entity_haskell.ts +13 -0
  47. package/.sdk/src/cmp/haskell/Gitignore_haskell.ts +27 -0
  48. package/.sdk/src/cmp/haskell/Main_haskell.ts +123 -0
  49. package/.sdk/src/cmp/haskell/Package_haskell.ts +60 -0
  50. package/.sdk/src/cmp/haskell/ReadmeEntity_haskell.ts +186 -0
  51. package/.sdk/src/cmp/haskell/ReadmeExamplesTest_haskell.ts +135 -0
  52. package/.sdk/src/cmp/haskell/ReadmeExplanation_haskell.ts +48 -0
  53. package/.sdk/src/cmp/haskell/ReadmeHowto_haskell.ts +168 -0
  54. package/.sdk/src/cmp/haskell/ReadmeInstall_haskell.ts +51 -0
  55. package/.sdk/src/cmp/haskell/ReadmeIntro_haskell.ts +67 -0
  56. package/.sdk/src/cmp/haskell/ReadmeModel_haskell.ts +162 -0
  57. package/.sdk/src/cmp/haskell/ReadmeOptions_haskell.ts +74 -0
  58. package/.sdk/src/cmp/haskell/ReadmeQuick_haskell.ts +241 -0
  59. package/.sdk/src/cmp/haskell/ReadmeRef_haskell.ts +408 -0
  60. package/.sdk/src/cmp/haskell/ReadmeTopHowto_haskell.ts +31 -0
  61. package/.sdk/src/cmp/haskell/ReadmeTopQuick_haskell.ts +104 -0
  62. package/.sdk/src/cmp/haskell/ReadmeTopTest_haskell.ts +80 -0
  63. package/.sdk/src/cmp/haskell/Test_haskell.ts +297 -0
  64. package/.sdk/src/cmp/haskell/tsconfig.json +15 -0
  65. package/.sdk/src/cmp/haskell/utility_haskell.ts +166 -0
  66. package/.sdk/src/cmp/lean/Config_lean.ts +93 -0
  67. package/.sdk/src/cmp/lean/Entity_lean.ts +9 -0
  68. package/.sdk/src/cmp/lean/Gitignore_lean.ts +18 -0
  69. package/.sdk/src/cmp/lean/Main_lean.ts +120 -0
  70. package/.sdk/src/cmp/lean/Package_lean.ts +93 -0
  71. package/.sdk/src/cmp/lean/ReadmeEntity_lean.ts +29 -0
  72. package/.sdk/src/cmp/lean/ReadmeExplanation_lean.ts +19 -0
  73. package/.sdk/src/cmp/lean/ReadmeHowto_lean.ts +25 -0
  74. package/.sdk/src/cmp/lean/ReadmeInstall_lean.ts +39 -0
  75. package/.sdk/src/cmp/lean/ReadmeIntro_lean.ts +25 -0
  76. package/.sdk/src/cmp/lean/ReadmeModel_lean.ts +24 -0
  77. package/.sdk/src/cmp/lean/ReadmeOptions_lean.ts +22 -0
  78. package/.sdk/src/cmp/lean/ReadmeQuick_lean.ts +50 -0
  79. package/.sdk/src/cmp/lean/ReadmeRef_lean.ts +40 -0
  80. package/.sdk/src/cmp/lean/ReadmeTopHowto_lean.ts +16 -0
  81. package/.sdk/src/cmp/lean/ReadmeTopQuick_lean.ts +23 -0
  82. package/.sdk/src/cmp/lean/ReadmeTopTest_lean.ts +19 -0
  83. package/.sdk/src/cmp/lean/Test_lean.ts +261 -0
  84. package/.sdk/src/cmp/lean/utility_lean.ts +129 -0
  85. package/.sdk/tm/dart/LICENSE +22 -0
  86. package/.sdk/tm/dart/Makefile +50 -0
  87. package/.sdk/tm/dart/lib/Context.dart +150 -0
  88. package/.sdk/tm/dart/lib/Control.dart +15 -0
  89. package/.sdk/tm/dart/lib/Operation.dart +31 -0
  90. package/.sdk/tm/dart/lib/Point.dart +51 -0
  91. package/.sdk/tm/dart/lib/Response.dart +32 -0
  92. package/.sdk/tm/dart/lib/Result.dart +39 -0
  93. package/.sdk/tm/dart/lib/Spec.dart +49 -0
  94. package/.sdk/tm/dart/lib/feature/audit/AuditFeature.dart +103 -0
  95. package/.sdk/tm/dart/lib/feature/base/BaseFeature.dart +76 -0
  96. package/.sdk/tm/dart/lib/feature/cache/CacheFeature.dart +152 -0
  97. package/.sdk/tm/dart/lib/feature/clienttrack/ClienttrackFeature.dart +104 -0
  98. package/.sdk/tm/dart/lib/feature/cost/CostFeature.dart +446 -0
  99. package/.sdk/tm/dart/lib/feature/debug/DebugFeature.dart +153 -0
  100. package/.sdk/tm/dart/lib/feature/idempotency/IdempotencyFeature.dart +92 -0
  101. package/.sdk/tm/dart/lib/feature/log/LogFeature.dart +85 -0
  102. package/.sdk/tm/dart/lib/feature/metrics/MetricsFeature.dart +103 -0
  103. package/.sdk/tm/dart/lib/feature/netsim/NetsimFeature.dart +186 -0
  104. package/.sdk/tm/dart/lib/feature/paging/PagingFeature.dart +240 -0
  105. package/.sdk/tm/dart/lib/feature/proxy/ProxyFeature.dart +118 -0
  106. package/.sdk/tm/dart/lib/feature/ratelimit/RatelimitFeature.dart +103 -0
  107. package/.sdk/tm/dart/lib/feature/rbac/RbacFeature.dart +121 -0
  108. package/.sdk/tm/dart/lib/feature/retry/RetryFeature.dart +155 -0
  109. package/.sdk/tm/dart/lib/feature/secrets/SecretsFeature.dart +649 -0
  110. package/.sdk/tm/dart/lib/feature/secrets/plugin/capability.dart +105 -0
  111. package/.sdk/tm/dart/lib/feature/secrets/plugin/catalog.dart +46 -0
  112. package/.sdk/tm/dart/lib/feature/secrets/plugin/config.dart +297 -0
  113. package/.sdk/tm/dart/lib/feature/secrets/plugin/depend.dart +198 -0
  114. package/.sdk/tm/dart/lib/feature/secrets/plugin/env.dart +144 -0
  115. package/.sdk/tm/dart/lib/feature/secrets/plugin/export.dart +58 -0
  116. package/.sdk/tm/dart/lib/feature/secrets/plugin/graph.dart +160 -0
  117. package/.sdk/tm/dart/lib/feature/secrets/plugin/host.dart +1067 -0
  118. package/.sdk/tm/dart/lib/feature/secrets/plugin/order.dart +172 -0
  119. package/.sdk/tm/dart/lib/feature/secrets/plugin/plugin.dart +23 -0
  120. package/.sdk/tm/dart/lib/feature/secrets/plugin/point.dart +117 -0
  121. package/.sdk/tm/dart/lib/feature/secrets/plugin/ref.dart +105 -0
  122. package/.sdk/tm/dart/lib/feature/secrets/plugin/resolve.dart +58 -0
  123. package/.sdk/tm/dart/lib/feature/secrets/plugin/types.dart +201 -0
  124. package/.sdk/tm/dart/lib/feature/secrets/plugin/version.dart +116 -0
  125. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/aws.dart +285 -0
  126. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/azuresecrets.dart +178 -0
  127. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/boru.dart +145 -0
  128. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/crypto.dart +194 -0
  129. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/doppler.dart +101 -0
  130. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/gcpsecrets.dart +143 -0
  131. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/hashicorp.dart +190 -0
  132. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/httpjson.dart +363 -0
  133. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/infisical.dart +149 -0
  134. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/onepassword.dart +146 -0
  135. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/secretspec.dart +116 -0
  136. package/.sdk/tm/dart/lib/feature/secrets/sekreto/plugins/sigv4.dart +237 -0
  137. package/.sdk/tm/dart/lib/feature/secrets/sekreto/src/addr.dart +138 -0
  138. package/.sdk/tm/dart/lib/feature/secrets/sekreto/src/json.dart +276 -0
  139. package/.sdk/tm/dart/lib/feature/secrets/sekreto/src/provider.dart +31 -0
  140. package/.sdk/tm/dart/lib/feature/secrets/sekreto/src/providers.dart +243 -0
  141. package/.sdk/tm/dart/lib/feature/secrets/sekreto/src/sekreto.dart +730 -0
  142. package/.sdk/tm/dart/lib/feature/secrets/sekreto/src/spec.dart +200 -0
  143. package/.sdk/tm/dart/lib/feature/secrets/sekreto/src/support.dart +217 -0
  144. package/.sdk/tm/dart/lib/feature/streaming/StreamingFeature.dart +97 -0
  145. package/.sdk/tm/dart/lib/feature/telemetry/TelemetryFeature.dart +136 -0
  146. package/.sdk/tm/dart/lib/feature/test/TestFeature.dart +328 -0
  147. package/.sdk/tm/dart/lib/feature/timeout/TimeoutFeature.dart +104 -0
  148. package/.sdk/tm/dart/lib/utility/CleanUtility.dart +12 -0
  149. package/.sdk/tm/dart/lib/utility/DoneUtility.dart +18 -0
  150. package/.sdk/tm/dart/lib/utility/ErrUtility.dart +46 -0
  151. package/.sdk/tm/dart/lib/utility/FeatureAddUtility.dart +35 -0
  152. package/.sdk/tm/dart/lib/utility/FeatureHookUtility.dart +20 -0
  153. package/.sdk/tm/dart/lib/utility/FeatureInitUtility.dart +9 -0
  154. package/.sdk/tm/dart/lib/utility/FetcherUtility.dart +104 -0
  155. package/.sdk/tm/dart/lib/utility/GraphqlUtility.dart +162 -0
  156. package/.sdk/tm/dart/lib/utility/MakeContextUtility.dart +6 -0
  157. package/.sdk/tm/dart/lib/utility/MakeErrorUtility.dart +71 -0
  158. package/.sdk/tm/dart/lib/utility/MakeFetchDefUtility.dart +42 -0
  159. package/.sdk/tm/dart/lib/utility/MakeOptionsUtility.dart +233 -0
  160. package/.sdk/tm/dart/lib/utility/MakePointUtility.dart +130 -0
  161. package/.sdk/tm/dart/lib/utility/MakeRequestUtility.dart +66 -0
  162. package/.sdk/tm/dart/lib/utility/MakeResponseUtility.dart +59 -0
  163. package/.sdk/tm/dart/lib/utility/MakeResultUtility.dart +49 -0
  164. package/.sdk/tm/dart/lib/utility/MakeSpecUtility.dart +77 -0
  165. package/.sdk/tm/dart/lib/utility/MakeUrlUtility.dart +51 -0
  166. package/.sdk/tm/dart/lib/utility/ParamUtility.dart +56 -0
  167. package/.sdk/tm/dart/lib/utility/PrepareAuthUtility.dart +46 -0
  168. package/.sdk/tm/dart/lib/utility/PrepareBodyUtility.dart +19 -0
  169. package/.sdk/tm/dart/lib/utility/PrepareHeadersUtility.dart +11 -0
  170. package/.sdk/tm/dart/lib/utility/PrepareMethodUtility.dart +30 -0
  171. package/.sdk/tm/dart/lib/utility/PrepareParamsUtility.dart +23 -0
  172. package/.sdk/tm/dart/lib/utility/PreparePathUtility.dart +9 -0
  173. package/.sdk/tm/dart/lib/utility/PrepareQueryUtility.dart +18 -0
  174. package/.sdk/tm/dart/lib/utility/ResultBasicUtility.dart +29 -0
  175. package/.sdk/tm/dart/lib/utility/ResultBodyUtility.dart +15 -0
  176. package/.sdk/tm/dart/lib/utility/ResultHeadersUtility.dart +18 -0
  177. package/.sdk/tm/dart/lib/utility/StructUtility.dart +127 -0
  178. package/.sdk/tm/dart/lib/utility/TransformRequestUtility.dart +28 -0
  179. package/.sdk/tm/dart/lib/utility/TransformResponseUtility.dart +44 -0
  180. package/.sdk/tm/dart/lib/utility/Utility.dart +239 -0
  181. package/.sdk/tm/dart/lib/utility/voxgig_struct.dart +2462 -0
  182. package/.sdk/tm/dart/src/feature/README.md +3 -0
  183. package/.sdk/tm/dart/src/feature/audit/.gitkeep +0 -0
  184. package/.sdk/tm/dart/src/feature/base/.gitkeep +0 -0
  185. package/.sdk/tm/dart/src/feature/cache/.gitkeep +0 -0
  186. package/.sdk/tm/dart/src/feature/clienttrack/.gitkeep +0 -0
  187. package/.sdk/tm/dart/src/feature/cost/.gitkeep +0 -0
  188. package/.sdk/tm/dart/src/feature/debug/.gitkeep +0 -0
  189. package/.sdk/tm/dart/src/feature/idempotency/.gitkeep +0 -0
  190. package/.sdk/tm/dart/src/feature/log/.gitkeep +0 -0
  191. package/.sdk/tm/dart/src/feature/metrics/.gitkeep +0 -0
  192. package/.sdk/tm/dart/src/feature/netsim/.gitkeep +0 -0
  193. package/.sdk/tm/dart/src/feature/paging/.gitkeep +0 -0
  194. package/.sdk/tm/dart/src/feature/proxy/.gitkeep +0 -0
  195. package/.sdk/tm/dart/src/feature/ratelimit/.gitkeep +0 -0
  196. package/.sdk/tm/dart/src/feature/rbac/.gitkeep +0 -0
  197. package/.sdk/tm/dart/src/feature/retry/.gitkeep +0 -0
  198. package/.sdk/tm/dart/src/feature/secrets/.gitkeep +0 -0
  199. package/.sdk/tm/dart/src/feature/streaming/.gitkeep +0 -0
  200. package/.sdk/tm/dart/src/feature/telemetry/.gitkeep +0 -0
  201. package/.sdk/tm/dart/src/feature/test/.gitkeep +0 -0
  202. package/.sdk/tm/dart/src/feature/timeout/.gitkeep +0 -0
  203. package/.sdk/tm/dart/test/custom_test.dart +65 -0
  204. package/.sdk/tm/dart/test/exists_test.dart +12 -0
  205. package/.sdk/tm/dart/test/feature/harness.dart +347 -0
  206. package/.sdk/tm/dart/test/feature/secrets/secrets_test.dart +1107 -0
  207. package/.sdk/tm/dart/test/feature_test.dart +1193 -0
  208. package/.sdk/tm/dart/test/harness.dart +153 -0
  209. package/.sdk/tm/dart/test/netsim_test.dart +48 -0
  210. package/.sdk/tm/dart/test/omni.dart +520 -0
  211. package/.sdk/tm/dart/test/omni_smoke_test.dart +143 -0
  212. package/.sdk/tm/dart/test/pipeline_test.dart +608 -0
  213. package/.sdk/tm/dart/test/primary_test.dart +476 -0
  214. package/.sdk/tm/dart/test/sdk-test-control.json +19 -0
  215. package/.sdk/tm/dart/test/struct_test.dart +468 -0
  216. package/.sdk/tm/dart/test/utility.dart +198 -0
  217. package/.sdk/tm/dart/test/vendor/omni/omni.dart +7 -0
  218. package/.sdk/tm/dart/test/vendor/omni/runner.dart +653 -0
  219. package/.sdk/tm/dart/test/vendor/omni/util.dart +232 -0
  220. package/.sdk/tm/haskell/LICENSE +21 -0
  221. package/.sdk/tm/haskell/Makefile +22 -0
  222. package/.sdk/tm/haskell/VERSION +1 -0
  223. package/.sdk/tm/haskell/src/SdkFeatures.hs +1440 -0
  224. package/.sdk/tm/haskell/src/SdkHelpers.hs +337 -0
  225. package/.sdk/tm/haskell/src/SdkJson.hs +111 -0
  226. package/.sdk/tm/haskell/src/SdkRuntime.hs +1279 -0
  227. package/.sdk/tm/haskell/src/SdkTypes.hs +195 -0
  228. package/.sdk/tm/haskell/src/VoxgigStruct.hs +2299 -0
  229. package/.sdk/tm/haskell/src/Vregex.hs +237 -0
  230. package/.sdk/tm/haskell/src/feature/README.md +5 -0
  231. package/.sdk/tm/haskell/src/feature/audit/.gitkeep +0 -0
  232. package/.sdk/tm/haskell/src/feature/base/.gitkeep +0 -0
  233. package/.sdk/tm/haskell/src/feature/cache/.gitkeep +0 -0
  234. package/.sdk/tm/haskell/src/feature/clienttrack/.gitkeep +0 -0
  235. package/.sdk/tm/haskell/src/feature/debug/.gitkeep +0 -0
  236. package/.sdk/tm/haskell/src/feature/idempotency/.gitkeep +0 -0
  237. package/.sdk/tm/haskell/src/feature/log/.gitkeep +0 -0
  238. package/.sdk/tm/haskell/src/feature/metrics/.gitkeep +0 -0
  239. package/.sdk/tm/haskell/src/feature/netsim/.gitkeep +0 -0
  240. package/.sdk/tm/haskell/src/feature/paging/.gitkeep +0 -0
  241. package/.sdk/tm/haskell/src/feature/proxy/.gitkeep +0 -0
  242. package/.sdk/tm/haskell/src/feature/ratelimit/.gitkeep +0 -0
  243. package/.sdk/tm/haskell/src/feature/rbac/.gitkeep +0 -0
  244. package/.sdk/tm/haskell/src/feature/retry/.gitkeep +0 -0
  245. package/.sdk/tm/haskell/src/feature/streaming/.gitkeep +0 -0
  246. package/.sdk/tm/haskell/src/feature/telemetry/.gitkeep +0 -0
  247. package/.sdk/tm/haskell/src/feature/test/.gitkeep +0 -0
  248. package/.sdk/tm/haskell/src/feature/timeout/.gitkeep +0 -0
  249. package/.sdk/tm/haskell/test/Harness.hs +281 -0
  250. package/.sdk/tm/haskell/test/OmniResolver.hs +252 -0
  251. package/.sdk/tm/haskell/test/Runner.hs +49 -0
  252. package/.sdk/tm/haskell/test/StructCorpus.hs +449 -0
  253. package/.sdk/tm/haskell/test/TCustomUtility.hs +38 -0
  254. package/.sdk/tm/haskell/test/TFeature.hs +794 -0
  255. package/.sdk/tm/haskell/test/TNetsim.hs +50 -0
  256. package/.sdk/tm/haskell/test/TPipeline.hs +334 -0
  257. package/.sdk/tm/haskell/test/TPrimaryCorpus.hs +263 -0
  258. package/.sdk/tm/haskell/test/TPrimaryUtility.hs +386 -0
  259. package/.sdk/tm/haskell/test/Testutil.hs +59 -0
  260. package/.sdk/tm/haskell/test/vendor/omni/Omni.hs +1147 -0
  261. package/.sdk/tm/lean/LICENSE +21 -0
  262. package/.sdk/tm/lean/Makefile +32 -0
  263. package/.sdk/tm/lean/VERSION +1 -0
  264. package/.sdk/tm/lean/src/SdkFeature.lean +171 -0
  265. package/.sdk/tm/lean/src/SdkFeatures.lean +787 -0
  266. package/.sdk/tm/lean/src/SdkJson.lean +134 -0
  267. package/.sdk/tm/lean/src/SdkRuntime.lean +374 -0
  268. package/.sdk/tm/lean/src/SdkUtility.lean +809 -0
  269. package/.sdk/tm/lean/src/VoxgigStruct.lean +2880 -0
  270. package/.sdk/tm/lean/src/Vregex.lean +412 -0
  271. package/.sdk/tm/lean/src/feature/README.md +5 -0
  272. package/.sdk/tm/lean/src/feature/audit/.gitkeep +0 -0
  273. package/.sdk/tm/lean/src/feature/base/.gitkeep +0 -0
  274. package/.sdk/tm/lean/src/feature/cache/.gitkeep +0 -0
  275. package/.sdk/tm/lean/src/feature/clienttrack/.gitkeep +0 -0
  276. package/.sdk/tm/lean/src/feature/cost/.gitkeep +0 -0
  277. package/.sdk/tm/lean/src/feature/debug/.gitkeep +0 -0
  278. package/.sdk/tm/lean/src/feature/idempotency/.gitkeep +0 -0
  279. package/.sdk/tm/lean/src/feature/log/.gitkeep +0 -0
  280. package/.sdk/tm/lean/src/feature/metrics/.gitkeep +0 -0
  281. package/.sdk/tm/lean/src/feature/netsim/.gitkeep +0 -0
  282. package/.sdk/tm/lean/src/feature/paging/.gitkeep +0 -0
  283. package/.sdk/tm/lean/src/feature/proxy/.gitkeep +0 -0
  284. package/.sdk/tm/lean/src/feature/ratelimit/.gitkeep +0 -0
  285. package/.sdk/tm/lean/src/feature/rbac/.gitkeep +0 -0
  286. package/.sdk/tm/lean/src/feature/retry/.gitkeep +0 -0
  287. package/.sdk/tm/lean/src/feature/streaming/.gitkeep +0 -0
  288. package/.sdk/tm/lean/src/feature/telemetry/.gitkeep +0 -0
  289. package/.sdk/tm/lean/src/feature/test/.gitkeep +0 -0
  290. package/.sdk/tm/lean/src/feature/timeout/.gitkeep +0 -0
  291. package/.sdk/tm/lean/test/OmniResolver.lean +358 -0
  292. package/.sdk/tm/lean/test/OmniSmoke.lean +174 -0
  293. package/.sdk/tm/lean/test/StructCorpus.lean +368 -0
  294. package/.sdk/tm/lean/test/TFeature.lean +281 -0
  295. package/.sdk/tm/lean/test/TPrimaryUtility.lean +227 -0
  296. package/.sdk/tm/lean/test/vendor/omni/Omni.lean +997 -0
  297. package/LICENSE +21 -0
  298. package/README.md +104 -0
  299. package/package.json +78 -0
  300. package/sdkgen-package.json +22 -0
@@ -0,0 +1,649 @@
1
+ // ignore_for_file: non_constant_identifier_names
2
+
3
+ import 'dart:async';
4
+ import 'dart:convert';
5
+
6
+ import '../base/BaseFeature.dart';
7
+
8
+ // The plugin DEFINITIONS the model selected for this feature, emitted by
9
+ // Config generically from the catalogue's active `plugin.def` entries.
10
+ // Upstream sekreto's contract since the registry was retired: a kind not
11
+ // passed in `plugins` is unknown to that Sekreto, so the model's choice of
12
+ // plugin groups IS the SDK's provider vocabulary.
13
+ //
14
+ // Config.dart imports this file (the generated #ImportFeatures block) and
15
+ // this file imports Config.dart back, which is a CYCLE - legal in Dart, and
16
+ // safe here because `FEATURE_PLUGINS` is a lazily-initialised top-level
17
+ // final that is first read in `init`, long after both libraries have
18
+ // loaded. Config emits the map unconditionally (empty when no group is
19
+ // active), so this import resolves in an SDK that carries the feature
20
+ // source without selecting a single plugin group.
21
+ import '../../Config.dart' show FEATURE_PLUGINS;
22
+
23
+ import 'sekreto/src/provider.dart';
24
+ import 'sekreto/src/sekreto.dart';
25
+ import 'sekreto/src/spec.dart';
26
+ import 'sekreto/src/support.dart';
27
+
28
+
29
+ // Secret access via a vendored @voxgig/sekreto provider chain, and the
30
+ // access-token exchange some APIs require on top of it. The dart port of
31
+ // tm/ts/src/feature/secrets/SecretsFeature.ts - same contract, dart idiom,
32
+ // and structurally the GO port rather than the ts one (see below).
33
+ //
34
+ // The SDK's `apikey` option keeps exactly its old meaning: an explicit
35
+ // credential given in code. This feature makes it ONE SOURCE among several
36
+ // rather than the only one: when active, the apikey is resolved through a
37
+ // sekreto chain in which the explicit option (when set) is the FIRST
38
+ // provider - a `memory` store named `options` - so an explicit value always
39
+ // wins, by sekreto's own first-hit rule rather than by special-case logic.
40
+ // When the option is unset, the remaining providers (env, dotenv, a vault)
41
+ // are asked in order, and moving a credential from code to a vault becomes
42
+ // a configuration change.
43
+ //
44
+ // WHY THE TRANSPORT SEAM, AND NOT PreSpec. Dart's feature hooks ARE
45
+ // awaited (EntityBase's `fres = featureHook(ctx, 'PreSpec'); if (fres is
46
+ // Future) await fres;`), so a PreSpec resolve COULD fail an entity op the
47
+ // ts way. It would not be enough. `ProjectNameSDK.prepare()` runs no
48
+ // feature hooks at all, and `direct()` and `graphql()` reach the wire
49
+ // through it - so a feature that only resolved in PreSpec would leave both
50
+ // RAW paths uncredentialed and, worse, fail OPEN: a broken vault would
51
+ // still send the request, unauthenticated. Every wire path instead crosses
52
+ // one mutable field, `ctx.utility.fetcher`, so this feature wraps that -
53
+ // the same seam the netsim/retry/cache features wrap - and resolves there.
54
+ // One gate, every path, entity and raw alike.
55
+ //
56
+ // THE CREDENTIAL LIVES IN FEATURE STATE, never in the shared options map.
57
+ // The ts reference writes `client._options.apikey` so the synchronous
58
+ // prepareAuth picks it up; here the transport wrapper rewrites the header
59
+ // itself, from the same `options.auth.prefix` prepareAuth uses, so the two
60
+ // cannot drift and the options map stays exactly as makeOptions built it.
61
+ // (go documents the same choice for a stronger reason - a shared map read
62
+ // by concurrent goroutines. Dart is single-isolate, so this is not a data
63
+ // race here; it is what makes the raw paths work and keeps the seam the
64
+ // single writer of the credential.)
65
+ //
66
+ // MISS vs ERROR (sekreto's invariant): a provider MISS falls through - the
67
+ // op proceeds, unauthenticated if nothing else supplies a credential. A
68
+ // provider ERROR (unreachable vault, bad creds) must FAIL the op: a broken
69
+ // vault never degrades into an unauthenticated request. The wrapper
70
+ // refuses to call the inner transport at all in that case, and answers
71
+ // with the provider's OWN message.
72
+ //
73
+ // EXCHANGE: some APIs will not take a long-lived credential at all. What
74
+ // the chain resolves is then a REFRESH token, which buys a short-lived
75
+ // ACCESS token from a token endpoint (`exchange.path`, relative to
76
+ // options.base); the access token is what every request carries, and when
77
+ // a response status in `exchange.statuses` (401) says it is spent the
78
+ // wrapper buys another and retries the same request once. Concurrent
79
+ // purchases share the one in-flight exchange; test mode buys nothing and
80
+ // answers with a deterministic fake token.
81
+ class SecretsFeature extends BaseFeature {
82
+ dynamic _client;
83
+
84
+ // The LIVE options map (root ctx options), read for `auth`, `apikey`,
85
+ // `base` and `system.fetch`. NEVER written: see the note above.
86
+ dynamic _liveopts;
87
+
88
+ Sekreto? _sekreto;
89
+ String _secretname = 'apikey';
90
+ bool _cache = true;
91
+
92
+ // A chain that would not BUILD (an unknown provider kind, a spec a
93
+ // definition refused). init cannot fail construction the way ts's
94
+ // throwing init does, so the failure is held here and the transport gate
95
+ // refuses to send - a misconfigured chain is fail-closed, not silently
96
+ // unauthenticated.
97
+ Object? _initerr;
98
+
99
+ // The RESOLVED credential, held in feature state and injected into each
100
+ // request at the transport seam.
101
+ String _cred = '';
102
+
103
+ // The one in-flight resolution concurrent operations share. Dart is
104
+ // single-isolate, so a plain nullable Future is all go's mutex and
105
+ // channel machinery collapses to.
106
+ Future<void>? _resolving;
107
+
108
+ // Exchange state: null config when off; the refresh credential the chain
109
+ // resolved; the single in-flight purchase.
110
+ _Exchange? _exchange;
111
+ String _refresh = '';
112
+ Future<String>? _buying;
113
+
114
+ SecretsFeature() {
115
+ version = '0.1.0';
116
+ name = 'secrets';
117
+ active = true;
118
+ }
119
+
120
+ // Sync by feature contract (init cannot await): build the chain only,
121
+ // never look anything up here.
122
+ @override
123
+ dynamic init(dynamic ctx, dynamic opts) {
124
+ _client = ctx.client;
125
+ _liveopts = ctx.options;
126
+ options = opts is Map ? Map<String, dynamic>.from(opts) : {};
127
+ active = true == options['active'];
128
+
129
+ if (!active) {
130
+ return null;
131
+ }
132
+
133
+ final rawname = options['name'];
134
+ _secretname =
135
+ (rawname is String && rawname.isNotEmpty) ? rawname : 'apikey';
136
+ _cache = false != options['cache'];
137
+
138
+ // Exchange config, normalised once. Null when off, so every later
139
+ // decision is a null check rather than a repeated `true == ...active`.
140
+ final xopts = options['exchange'];
141
+ if (xopts is Map && true == xopts['active']) {
142
+ _exchange = _Exchange(
143
+ path: _str(xopts['path'], 'auth/token'),
144
+ method: _str(xopts['method'], 'POST'),
145
+ request: _str(xopts['request'], 'refresh_token'),
146
+ response: _str(xopts['response'], 'access_token'),
147
+ statuses: _ints(xopts['statuses'], const [401]),
148
+ retries: xopts['retries'] is num ? (xopts['retries'] as num).toInt() : 1,
149
+ );
150
+ }
151
+
152
+ // The explicit credential, when set, is the first store in the chain.
153
+ //
154
+ // WHICH option that is depends on the exchange. Without one, the secret
155
+ // being resolved IS the credential the transport sends, so `apikey` is
156
+ // it. With one, the secret is a REFRESH token and `apikey` means the
157
+ // opposite thing - an access token the caller already holds - so the
158
+ // explicit seat belongs to `exchange.refresh`, and apikey is left alone
159
+ // to serve as the starting access token (see _resolveonce).
160
+ final explicit = null == _exchange
161
+ ? _optstr('apikey')
162
+ : (xopts is Map ? _str(xopts['refresh'], '') : '');
163
+
164
+ final providers = <Object?>[];
165
+
166
+ if (explicit.isNotEmpty) {
167
+ // `envkey` VALIDATES the name, and a bad one (`Api.Token`, `api..token`)
168
+ // raises. Held rather than thrown: init runs inside the SDK
169
+ // constructor, where a throw is a stack trace from `ProjectNameSDK(...)`
170
+ // naming nothing the caller can act on. The transport gate reports it
171
+ // instead - with sekreto's own message - and refuses to send, which is
172
+ // the same fail-closed answer a broken store gets.
173
+ try {
174
+ providers.add(ProviderSpec(
175
+ kind: 'memory',
176
+ name: 'options',
177
+ values: <String, String>{envkey(_secretname): explicit},
178
+ ));
179
+ } catch (err) {
180
+ _initerr = err;
181
+ }
182
+ }
183
+
184
+ final given = options['providers'];
185
+ if (given is List) {
186
+ for (final p in given) {
187
+ // A live Provider or a built ProviderSpec joins the chain as it is.
188
+ // A declarative MAP - `{ kind: 'env', prefix: 'X' }`, the shape a
189
+ // config file and the docs use - goes through sekreto's own
190
+ // converter, because the Sekreto constructor accepts nothing else
191
+ // ("sekreto: not a provider or a provider spec").
192
+ if (p is ProviderSpec || p is Provider) {
193
+ providers.add(p);
194
+ } else if (p is Map) {
195
+ try {
196
+ providers.add(specof(Map<String, dynamic>.from(
197
+ p.map((k, v) => MapEntry('$k', v)))));
198
+ } catch (err) {
199
+ _initerr = err;
200
+ }
201
+ } else {
202
+ _initerr = SekretoError(
203
+ 'secrets: not a provider or a provider spec: ${p ?? ''}');
204
+ }
205
+ }
206
+ }
207
+
208
+ try {
209
+ _sekreto = Sekreto(
210
+ providers: providers,
211
+ plugins: FEATURE_PLUGINS[name] ?? const <Object?>[],
212
+ cache: _cache,
213
+ );
214
+ } catch (err) {
215
+ _initerr = err;
216
+ }
217
+
218
+ // NO `client._secrets = this` HERE, and the omission is load-bearing.
219
+ // The ts and js ports plant that field for their `secrets()` accessor
220
+ // to read; in Dart a leading underscore is LIBRARY-private, and this
221
+ // file is a different library from ProjectNameSDK.dart - so a dynamic
222
+ // `_client._secrets = this` would create/seek a distinct private symbol
223
+ // and throw NoSuchMethodError at construction. The generated accessor
224
+ // finds this feature by name in `client.features` instead, which is
225
+ // public and needs no seam at all.
226
+
227
+ // Wrap the transport. Unlike the ts reference - which wraps only when
228
+ // exchanging, because its PreSpec hook covers the ordinary case - the
229
+ // wrapper is the fail-closed gate AND the credential injector here, so
230
+ // it is installed whenever the feature is active.
231
+ final self = this;
232
+ final utility = ctx.utility;
233
+ final inner = utility.fetcher;
234
+
235
+ utility.fetcher = (dynamic ctx2, dynamic url, dynamic fetchdef) async {
236
+ return self._transport(ctx2, url, fetchdef, inner);
237
+ };
238
+
239
+ return null;
240
+ }
241
+
242
+ // The LIVE Sekreto instance, for the SDK's secrets() accessor and for
243
+ // callers who want arbitrary secrets or redaction:
244
+ //
245
+ // await sdk.secrets().get('db.password')
246
+ // sdk.secrets().redact(logline)
247
+ //
248
+ // Never a clone: sekreto holds provider state (caches, vault leases) that
249
+ // has to stay live to be worth anything.
250
+ Sekreto? sekreto() => _sekreto;
251
+
252
+ // The resolved credential (empty when none) - the state the transport
253
+ // injects. The dart peer of go's Credential(): tests and callers read it
254
+ // here rather than from the options map, which this feature never writes.
255
+ String get credential => _cred;
256
+
257
+ // Resolve the secret. Concurrent operations share the one IN-FLIGHT
258
+ // future; a settled HIT is kept only when caching is on (`cache: false`
259
+ // means every resolve asks the chain again). A FAILURE is always cleared,
260
+ // so a transient vault outage never poisons the client permanently - the
261
+ // next operation asks the chain again.
262
+ //
263
+ // A MISS is cleared too, however caching is set. That rule is sekreto's,
264
+ // not this feature's: `A miss is never cached: the next read asks again`,
265
+ // in sekreto's own source (sekreto/src/sekreto.dart). Keeping a settled
266
+ // miss here would override that from the layer above, and a secret
267
+ // provisioned after startup - a mounted file, a policy granted a minute
268
+ // late - would never be picked up for the life of the client. `cache` is
269
+ // about caching a HIT; it was never a promise to keep saying no.
270
+ Future<void> resolve() {
271
+ final err = _initerr;
272
+ if (null != err) {
273
+ return Future<void>.error(err);
274
+ }
275
+
276
+ final current = _resolving;
277
+ if (null != current) {
278
+ return current;
279
+ }
280
+
281
+ final inflight = _resolveonce().then((bool hit) {
282
+ if (!_cache || !hit) {
283
+ _resolving = null;
284
+ }
285
+ }, onError: (Object e) {
286
+ _resolving = null;
287
+ throw e;
288
+ });
289
+
290
+ _resolving = inflight;
291
+
292
+ return inflight;
293
+ }
294
+
295
+ // Resolve once, reporting whether a credential came out of it. That bool
296
+ // is the whole of what resolve() needs to tell a cacheable HIT from a miss
297
+ // it must not keep.
298
+ Future<bool> _resolveonce() async {
299
+ final sek = _sekreto;
300
+ if (null == sek) {
301
+ return false;
302
+ }
303
+
304
+ // `tryget` is FutureOr: a chain of purely local stores answers without
305
+ // yielding. `await` reads either, and this function being async is what
306
+ // turns a SYNCHRONOUS provider throw into a failed future rather than
307
+ // an exception escaping resolve()'s caller.
308
+ final found = await sek.tryget(_secretname);
309
+
310
+ if (null == _exchange) {
311
+ // An UNCACHED miss after an earlier hit is a revocation: the chain
312
+ // now says no provider has the secret, so the resolved value must not
313
+ // keep going out on the wire. (An explicit apikey OPTION is never
314
+ // lost here - it seats FIRST in the chain as a memory provider, so
315
+ // the chain HITS while one is set and this branch writes it back.)
316
+ _cred = found ?? '';
317
+ return null != found;
318
+ }
319
+
320
+ // Exchanging: what the chain resolved is the REFRESH token, kept for
321
+ // every later purchase. A miss is not fatal here - an explicit `apikey`
322
+ // may already hold a usable access token, and the API is what gets to
323
+ // say whether it does.
324
+ _refresh = found ?? '';
325
+
326
+ if (_cred.isEmpty) {
327
+ // A starting access token supplied as the OPTION.
328
+ _cred = _optstr('apikey');
329
+ }
330
+
331
+ if (_cred.isNotEmpty) {
332
+ // Spend it: if it is stale the API answers with an expiry status and
333
+ // the transport wrapper buys another, which is the same path expiry
334
+ // takes anyway.
335
+ return true;
336
+ }
337
+
338
+ // `auth: null` is the documented way to send NO credential, and a
339
+ // purchase is a credential-bearing call: the refresh token goes to the
340
+ // token endpoint in the request body. _withRefresh honours suppression
341
+ // for the RETRY, but it runs after this - by then the refresh token has
342
+ // already left the process, and no later check can call it back. The
343
+ // suppression has to be honoured here, before the first purchase, or it
344
+ // only ever half-held.
345
+ if (null == _rawauth()) {
346
+ return false;
347
+ }
348
+
349
+ _cred = await _buy();
350
+
351
+ return true;
352
+ }
353
+
354
+ // The transport wrapper: the ONE seam every wire path crosses.
355
+ //
356
+ // Entity ops, prepare()/direct()/graphql() and the exchange retries all
357
+ // come through here, so resolving HERE is what gives the raw paths -
358
+ // which run no feature hooks at all - the same credential the entity
359
+ // pipeline gets. resolve() is shared and cached: concurrent callers join
360
+ // the in-flight attempt, a cached success is free, and with `cache:
361
+ // false` the chain is asked once per REQUEST, which is that option's
362
+ // meaning.
363
+ Future<dynamic> _transport(
364
+ dynamic ctx, dynamic url, dynamic fetchdef, dynamic inner) async {
365
+ // FAIL CLOSED. A provider ERROR refuses the request, carrying the
366
+ // provider's own message - never an unauthenticated send. Returned as
367
+ // an error VALUE rather than thrown, which is this pipeline's shape for
368
+ // a transport failure (netsim does the same): _rawRequest reports it as
369
+ // `{ok: false, err: ...}` and an entity op fails on it.
370
+ try {
371
+ await resolve();
372
+ } catch (err) {
373
+ return ctx.error('secrets_provider', _why(err));
374
+ }
375
+
376
+ // Inject the resolved credential into THIS request's header. The header
377
+ // was built by prepareAuth from the options apikey; the chain-resolved
378
+ // value lives in feature state instead, so the wrapper writes it here -
379
+ // same construction, same suppression rules.
380
+ if (_cred.isNotEmpty) {
381
+ _reauth(fetchdef, _cred);
382
+ }
383
+
384
+ if (null == _exchange) {
385
+ return Future.value(inner(ctx, url, fetchdef));
386
+ }
387
+
388
+ return _withRefresh(ctx, url, fetchdef, inner);
389
+ }
390
+
391
+ // Buy a token and try the request again when the API says the current one
392
+ // is spent.
393
+ //
394
+ // The retry rewrites the authorization header IN PLACE on the fetchdef,
395
+ // because the header was built by the synchronous prepareAuth before this
396
+ // request left, and it carries the token that just failed. Rebuilt the
397
+ // way prepareAuth builds it, from the same options auth.prefix, so the
398
+ // two cannot drift.
399
+ Future<dynamic> _withRefresh(
400
+ dynamic ctx, dynamic url, dynamic fetchdef, dynamic inner) async {
401
+ // `auth: null` is the documented way to send NO credential, and
402
+ // prepareAuth honours it by removing the header. A refusal of a
403
+ // deliberately unauthenticated request is not an expired token and
404
+ // cannot be fixed by buying one - retrying would transmit exactly the
405
+ // credential the caller suppressed.
406
+ if (null == _rawauth()) {
407
+ return Future.value(inner(ctx, url, fetchdef));
408
+ }
409
+
410
+ final max = _exchange!.retries;
411
+ var attempt = 0;
412
+
413
+ for (;;) {
414
+ // The credential THIS attempt goes out with, captured before it
415
+ // leaves: it is what tells a stale refusal apart from a fresh one.
416
+ final used = _cred;
417
+
418
+ final res = await Future.value(inner(ctx, url, fetchdef));
419
+
420
+ if (attempt >= max || !_spent(res)) {
421
+ return res;
422
+ }
423
+
424
+ // Another request may have bought a token while this one was in
425
+ // flight. Concurrent expiries share the in-flight purchase, but
426
+ // STAGGERED ones do not - so spend what is current before buying: a
427
+ // second exchange for a token that is already fresh is wasted, and on
428
+ // a provider that invalidates the previous credential on issuance it
429
+ // breaks the first request's own retry.
430
+ final current = _cred;
431
+ String token;
432
+
433
+ if (current.isNotEmpty && current != used) {
434
+ token = current;
435
+ } else {
436
+ try {
437
+ token = await _buy();
438
+ } catch (_err) {
439
+ // The purchase failed: answer with the API's own refusal rather
440
+ // than this one. The caller asked for data, and the refusal is
441
+ // the more useful of the two - the exchange error is a symptom.
442
+ return res;
443
+ }
444
+ _cred = token;
445
+ }
446
+
447
+ _reauth(fetchdef, token);
448
+
449
+ attempt++;
450
+ }
451
+ }
452
+
453
+ bool _spent(dynamic res) {
454
+ if (null == res || res is Error || res is Exception || res is! Map) {
455
+ return false;
456
+ }
457
+ final status = res['status'];
458
+ if (status is! num) {
459
+ return false;
460
+ }
461
+ return _exchange!.statuses.contains(status.toInt());
462
+ }
463
+
464
+ // Buy an access token with the refresh token. Concurrent callers share
465
+ // the ONE in-flight purchase: a client running four operations at once
466
+ // must not open four token requests. The slot is cleared once settled, so
467
+ // the next expiry buys a fresh token rather than replaying this result.
468
+ Future<String> _buy() {
469
+ // TEST MODE BUYS NOTHING. The test feature replaces the transport so no
470
+ // request leaves the process; an exchange here would be the one HTTP
471
+ // call it could not stop, and it would need a live token endpoint for a
472
+ // suite whose whole point is not needing one. A deterministic,
473
+ // obviously-fake token instead - the same answer makeOptions gives a
474
+ // required server variable, for the same reason.
475
+ if ('live' != _client.mode) {
476
+ return Future.value('test-' + _exchange!.response);
477
+ }
478
+
479
+ final current = _buying;
480
+ if (null != current) {
481
+ return current;
482
+ }
483
+
484
+ final buying = _buyonce().then((String token) {
485
+ _buying = null;
486
+ return token;
487
+ }, onError: (Object err) {
488
+ _buying = null;
489
+ throw err;
490
+ });
491
+
492
+ _buying = buying;
493
+
494
+ return buying;
495
+ }
496
+
497
+ Future<String> _buyonce() async {
498
+ final x = _exchange!;
499
+
500
+ if (_refresh.isEmpty) {
501
+ throw SekretoError(
502
+ "secrets: no refresh token: the provider chain has no '"
503
+ "$_secretname', and feature.secrets.exchange.refresh is unset");
504
+ }
505
+
506
+ // The token endpoint is RELATIVE to the base, which already carries
507
+ // whatever account or tenant segment the server URL declares.
508
+ var base = _optstr('base');
509
+ while (base.endsWith('/')) {
510
+ base = base.substring(0, base.length - 1);
511
+ }
512
+ var path = x.path;
513
+ while (path.startsWith('/')) {
514
+ path = path.substring(1);
515
+ }
516
+ final url = '$base/$path';
517
+
518
+ // From the LIVE options captured at init, NEVER from client.options():
519
+ // that returns `struct.clone(_options)`, and makeOptions specially
520
+ // preserves the function-valued system.fetch across merge/validate
521
+ // exactly because a clone is where a function is lost. Reading the
522
+ // clone risks a real token purchase where a test injected a transport.
523
+ final system = _liveopts is Map ? _liveopts['system'] : null;
524
+ final fetch = system is Map ? system['fetch'] : null;
525
+
526
+ if (fetch is! Function) {
527
+ throw SekretoError(
528
+ 'secrets: no fetch implementation for the token exchange');
529
+ }
530
+
531
+ // The body is MARSHALLED, never concatenated: a refresh token (or a
532
+ // configured request-field name) carrying a quote, backslash or newline
533
+ // must arrive as that literal value, not as malformed JSON.
534
+ final body = jsonEncode(<String, String>{x.request: _refresh});
535
+
536
+ // Deliberately NOT the SDK transport. The transport is what this
537
+ // feature wraps, and sending the token request back through it would
538
+ // recurse on the first expiry - and would route the exchange through
539
+ // the test mock, which knows nothing about it.
540
+ final res = await Future.value(fetch(url, <String, dynamic>{
541
+ 'method': x.method,
542
+ 'headers': <String, dynamic>{'content-type': 'application/json'},
543
+ 'body': body,
544
+ }));
545
+
546
+ final rawstatus = (res is Map) ? res['status'] : null;
547
+ final status = rawstatus is num ? rawstatus.toInt() : 0;
548
+
549
+ if (200 > status || 300 <= status) {
550
+ throw SekretoError(
551
+ 'secrets: token exchange failed: $status from $url');
552
+ }
553
+
554
+ dynamic decoded;
555
+ if (res is Map) {
556
+ final jsonfn = res['json'];
557
+ decoded = jsonfn is Function ? await Future.value(jsonfn()) : res['body'];
558
+ }
559
+
560
+ final token = decoded is Map ? decoded[x.response] : null;
561
+
562
+ if (token is! String || token.isEmpty) {
563
+ throw SekretoError("secrets: token exchange returned no '"
564
+ "${x.response}' field from $url");
565
+ }
566
+
567
+ return token;
568
+ }
569
+
570
+ // The raw `auth` option: a Map when auth is configured, null when the
571
+ // caller suppressed it with `auth: null`.
572
+ dynamic _rawauth() => _liveopts is Map ? _liveopts['auth'] : null;
573
+
574
+ void _reauth(dynamic fetchdef, String token) {
575
+ if (fetchdef is! Map) {
576
+ return;
577
+ }
578
+ final headers = fetchdef['headers'];
579
+ if (headers is! Map) {
580
+ return;
581
+ }
582
+
583
+ // Suppressed auth means NO header, the same answer prepareAuth gives.
584
+ // Reached defensively for the exchange path - _withRefresh does not
585
+ // retry at all when auth is null - but this is the function that writes
586
+ // the credential, so it is where the rule has to hold.
587
+ final auth = _rawauth();
588
+ if (auth is! Map) {
589
+ headers.remove('authorization');
590
+ return;
591
+ }
592
+
593
+ final prefix = auth['prefix'];
594
+ headers['authorization'] = (prefix is String && prefix.isNotEmpty)
595
+ ? '$prefix $token'
596
+ : token;
597
+ }
598
+
599
+ String _optstr(String key) {
600
+ final value = _liveopts is Map ? _liveopts[key] : null;
601
+ return value is String ? value : '';
602
+ }
603
+
604
+ static String _str(dynamic value, String dflt) =>
605
+ (value is String && value.isNotEmpty) ? value : dflt;
606
+
607
+ static List<int> _ints(dynamic value, List<int> dflt) {
608
+ if (value is! List) {
609
+ return dflt;
610
+ }
611
+ final out = <int>[];
612
+ for (final one in value) {
613
+ if (one is num) {
614
+ out.add(one.toInt());
615
+ }
616
+ }
617
+ return out.isEmpty ? dflt : out;
618
+ }
619
+
620
+ // What a failure has to say for itself. A SekretoError's whole contract
621
+ // is its message (the shared spec pins every one of them byte for byte),
622
+ // so it is passed through rather than decorated - a test that asserts on
623
+ // the PROVIDER's own words is asserting on what the operator will read.
624
+ static String _why(Object err) {
625
+ if (err is SekretoError) {
626
+ return err.message;
627
+ }
628
+ return '$err';
629
+ }
630
+ }
631
+
632
+
633
+ class _Exchange {
634
+ final String path;
635
+ final String method;
636
+ final String request;
637
+ final String response;
638
+ final List<int> statuses;
639
+ final int retries;
640
+
641
+ _Exchange({
642
+ required this.path,
643
+ required this.method,
644
+ required this.request,
645
+ required this.response,
646
+ required this.statuses,
647
+ required this.retries,
648
+ });
649
+ }