@voxgig/sdkgen 4.5.3 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/action/check.js +15 -0
  3. package/dist/action/check.js.map +1 -1
  4. package/dist/cmp/AgentGuide.js +1 -1
  5. package/dist/cmp/AgentGuide.js.map +1 -1
  6. package/dist/cmp/AgentGuideContent.d.ts +1 -1
  7. package/dist/cmp/AgentGuideContent.js +8 -2
  8. package/dist/cmp/AgentGuideContent.js.map +1 -1
  9. package/dist/cmp/Feature.js +17 -0
  10. package/dist/cmp/Feature.js.map +1 -1
  11. package/dist/cmp/FeatureDocs.d.ts +1 -1
  12. package/dist/cmp/FeatureDocs.js +6 -1
  13. package/dist/cmp/FeatureDocs.js.map +1 -1
  14. package/dist/cmp/ReadmeExplanation.js +3 -1
  15. package/dist/cmp/ReadmeExplanation.js.map +1 -1
  16. package/dist/cmp/ReadmeFeatures.js +1 -1
  17. package/dist/cmp/ReadmeFeatures.js.map +1 -1
  18. package/dist/cmp/ReadmeRefFeatures.js +1 -1
  19. package/dist/cmp/ReadmeRefFeatures.js.map +1 -1
  20. package/dist/helpers/applicability.d.ts +6 -0
  21. package/dist/helpers/applicability.js +103 -0
  22. package/dist/helpers/applicability.js.map +1 -0
  23. package/dist/helpers/collectDeps.js +4 -2
  24. package/dist/helpers/collectDeps.js.map +1 -1
  25. package/dist/helpers/serverVars.d.ts +2 -1
  26. package/dist/helpers/serverVars.js +17 -0
  27. package/dist/helpers/serverVars.js.map +1 -1
  28. package/dist/sdkgen.d.ts +3 -2
  29. package/dist/sdkgen.js +9 -2
  30. package/dist/sdkgen.js.map +1 -1
  31. package/dist/tsconfig.tsbuildinfo +1 -1
  32. package/dist/utility.js +7 -1
  33. package/dist/utility.js.map +1 -1
  34. package/model/sdkgen.aon +39 -0
  35. package/package.json +1 -1
  36. package/project/.sdk/model/feature/feature-index.aon +1 -0
  37. package/project/.sdk/model/feature/secrets.aon +118 -0
  38. package/project/.sdk/model/target/ts.aon +8 -1
  39. package/project/.sdk/src/cmp/c/Config_c.ts +5 -1
  40. package/project/.sdk/src/cmp/cpp/Config_cpp.ts +5 -1
  41. package/project/.sdk/src/cmp/csharp/Config_csharp.ts +5 -1
  42. package/project/.sdk/src/cmp/dart/Config_dart.ts +5 -1
  43. package/project/.sdk/src/cmp/elixir/Config_elixir.ts +5 -1
  44. package/project/.sdk/src/cmp/elixir/Main_elixir.ts +5 -1
  45. package/project/.sdk/src/cmp/go/Config_go.ts +5 -1
  46. package/project/.sdk/src/cmp/go/Main_go.ts +6 -2
  47. package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +16 -3
  48. package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +16 -3
  49. package/project/.sdk/src/cmp/go/TestDirect_go.ts +28 -4
  50. package/project/.sdk/src/cmp/go/TestEntity_go.ts +43 -10
  51. package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +5 -5
  52. package/project/.sdk/src/cmp/java/Config_java.ts +22 -1
  53. package/project/.sdk/src/cmp/java/Main_java.ts +5 -1
  54. package/project/.sdk/src/cmp/java/ReadmeQuick_java.ts +17 -3
  55. package/project/.sdk/src/cmp/java/ReadmeTopQuick_java.ts +17 -3
  56. package/project/.sdk/src/cmp/java/TestDirect_java.ts +23 -4
  57. package/project/.sdk/src/cmp/java/TestEntity_java.ts +29 -4
  58. package/project/.sdk/src/cmp/js/Config_js.ts +5 -1
  59. package/project/.sdk/src/cmp/js/Main_js.ts +5 -1
  60. package/project/.sdk/src/cmp/js/Package_js.ts +4 -1
  61. package/project/.sdk/src/cmp/kotlin/Config_kotlin.ts +5 -1
  62. package/project/.sdk/src/cmp/lean/Config_lean.ts +5 -1
  63. package/project/.sdk/src/cmp/lua/Config_lua.ts +5 -1
  64. package/project/.sdk/src/cmp/lua/Main_lua.ts +5 -1
  65. package/project/.sdk/src/cmp/lua/Package_lua.ts +4 -1
  66. package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +5 -1
  67. package/project/.sdk/src/cmp/perl/Main_perl.ts +5 -1
  68. package/project/.sdk/src/cmp/php/Config_php.ts +5 -1
  69. package/project/.sdk/src/cmp/php/Main_php.ts +5 -1
  70. package/project/.sdk/src/cmp/py/Config_py.ts +5 -1
  71. package/project/.sdk/src/cmp/py/Main_py.ts +5 -1
  72. package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +16 -3
  73. package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +16 -3
  74. package/project/.sdk/src/cmp/py/TestDirect_py.ts +24 -5
  75. package/project/.sdk/src/cmp/py/TestEntity_py.ts +23 -3
  76. package/project/.sdk/src/cmp/rb/Config_rb.ts +5 -1
  77. package/project/.sdk/src/cmp/rb/Main_rb.ts +5 -1
  78. package/project/.sdk/src/cmp/rust/Config_rust.ts +5 -1
  79. package/project/.sdk/src/cmp/rust/Main_rust.ts +5 -1
  80. package/project/.sdk/src/cmp/scala/Config_scala.ts +5 -1
  81. package/project/.sdk/src/cmp/scala/Main_scala.ts +5 -1
  82. package/project/.sdk/src/cmp/swift/Config_swift.ts +5 -1
  83. package/project/.sdk/src/cmp/ts/Config_ts.ts +5 -1
  84. package/project/.sdk/src/cmp/ts/Main_ts.ts +57 -1
  85. package/project/.sdk/src/cmp/ts/Package_ts.ts +4 -1
  86. package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +15 -3
  87. package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +18 -5
  88. package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +19 -5
  89. package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +67 -7
  90. package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +27 -4
  91. package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +9 -2
  92. package/project/.sdk/src/cmp/ts/fragment/Entity.test.fragment.ts +9 -2
  93. package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +7 -0
  94. package/project/.sdk/src/cmp/zig/Config_zig.ts +5 -1
  95. package/project/.sdk/tm/c/utility/make_options.c +22 -0
  96. package/project/.sdk/tm/clojure/src/sdk/core.clj +18 -1
  97. package/project/.sdk/tm/cpp/utility/pipeline.hpp +23 -0
  98. package/project/.sdk/tm/csharp/test/CustomUtilityTest.cs +15 -0
  99. package/project/.sdk/tm/csharp/utility/MakeOptions.cs +23 -0
  100. package/project/.sdk/tm/dart/lib/utility/MakeOptionsUtility.dart +22 -0
  101. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +19 -0
  102. package/project/.sdk/tm/go/core/context.go +1 -1
  103. package/project/.sdk/tm/go/feature/cost_feature.go +1 -1
  104. package/project/.sdk/tm/go/feature/paging_feature.go +5 -5
  105. package/project/.sdk/tm/go/feature/test_feature.go +12 -5
  106. package/project/.sdk/tm/go/test/custom_utility_test.go +15 -0
  107. package/project/.sdk/tm/go/test/feature_corpus_test.go +7 -0
  108. package/project/.sdk/tm/go/test/runner_test.go +46 -0
  109. package/project/.sdk/tm/go/test/struct_runner_test.go +7 -7
  110. package/project/.sdk/tm/go/test/struct_utility_test.go +63 -27
  111. package/project/.sdk/tm/go/utility/fetcher.go +2 -2
  112. package/project/.sdk/tm/go/utility/make_options.go +24 -5
  113. package/project/.sdk/tm/go/utility/make_point.go +1 -1
  114. package/project/.sdk/tm/go/utility/make_spec.go +17 -1
  115. package/project/.sdk/tm/go/utility/prepare_auth.go +1 -1
  116. package/project/.sdk/tm/go/utility/struct/voxgigstruct.go +370 -307
  117. package/project/.sdk/tm/go/utility/transform_request.go +29 -1
  118. package/project/.sdk/tm/go/utility/transform_response.go +20 -1
  119. package/project/.sdk/tm/java/test/CustomUtilityTest.java +10 -0
  120. package/project/.sdk/tm/java/test/FeatureCorpusTest.java +7 -0
  121. package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +6 -0
  122. package/project/.sdk/tm/java/test/RunnerSupport.java +43 -0
  123. package/project/.sdk/tm/java/utility/MakeOptions.java +84 -1
  124. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +24 -0
  125. package/project/.sdk/tm/js/src/utility/StructUtility.js +2076 -1837
  126. package/project/.sdk/tm/js/test/feature/Corpus.test.js +9 -0
  127. package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +21 -0
  128. package/project/.sdk/tm/lean/src/SdkUtility.lean +12 -1
  129. package/project/.sdk/tm/ocaml/sdk_runtime.ml +11 -0
  130. package/project/.sdk/tm/perl/utility/make_options.pm +18 -0
  131. package/project/.sdk/tm/php/test/FeatureCorpusTest.php +10 -1
  132. package/project/.sdk/tm/php/utility/MakeOptions.php +24 -0
  133. package/project/.sdk/tm/py/pkg/utility/make_options.py +20 -0
  134. package/project/.sdk/tm/py/test/runner.py +32 -0
  135. package/project/.sdk/tm/py/test/test_feature_corpus.py +10 -1
  136. package/project/.sdk/tm/rb/test/feature_corpus_test.rb +9 -1
  137. package/project/.sdk/tm/rb/utility/make_options.rb +17 -0
  138. package/project/.sdk/tm/rust/utility/make_options.rs +25 -0
  139. package/project/.sdk/tm/scala/utility/Make.scala +17 -0
  140. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +21 -0
  141. package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +419 -0
  142. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Providers.ts +1221 -0
  143. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sekreto.ts +381 -0
  144. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sigv4.ts +151 -0
  145. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/index.ts +42 -0
  146. package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +18 -0
  147. package/project/.sdk/tm/ts/src/utility/StructUtility.ts +1321 -710
  148. package/project/.sdk/tm/ts/test/feature/Corpus.test.ts +9 -0
  149. package/project/.sdk/tm/ts/test/feature/secrets/Secrets.test.ts +764 -0
  150. package/project/.sdk/tm/ts/test/omni.test.ts +84 -0
  151. package/project/.sdk/tm/ts/test/omni.ts +86 -0
  152. package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +6 -2
  153. package/project/.sdk/tm/ts/test/utility/StructUtility.test.ts +2 -2
  154. package/project/.sdk/tm/ts/test/utility.ts +122 -0
  155. package/project/.sdk/tm/ts/test/vendor/omni/Runner.ts +692 -0
  156. package/project/.sdk/tm/ts/test/vendor/omni/Util.ts +238 -0
  157. package/project/.sdk/tm/ts/test/vendor/omni/compat.ts +188 -0
  158. package/project/.sdk/tm/ts/test/vendor/omni/index.ts +38 -0
  159. package/project/.sdk/tm/zig/core/utility.zig +23 -0
  160. package/project/sdkgen-package.json +2 -1
  161. package/src/action/check.ts +18 -0
  162. package/src/cmp/AgentGuide.ts +1 -1
  163. package/src/cmp/AgentGuideContent.ts +9 -2
  164. package/src/cmp/Feature.ts +19 -0
  165. package/src/cmp/FeatureDocs.ts +7 -1
  166. package/src/cmp/ReadmeExplanation.ts +4 -1
  167. package/src/cmp/ReadmeFeatures.ts +1 -1
  168. package/src/cmp/ReadmeRefFeatures.ts +1 -1
  169. package/src/helpers/applicability.ts +123 -0
  170. package/src/helpers/collectDeps.ts +5 -1
  171. package/src/helpers/serverVars.ts +19 -0
  172. package/src/sdkgen.ts +9 -1
  173. package/src/utility.ts +10 -1
  174. package/project/.sdk/tm/ts/test/runner.ts +0 -425
@@ -0,0 +1,238 @@
1
+ // VENDORED: @voxgig/omni 0.1.2 (typescript/src/Util.ts)
2
+ // Source: https://github.com/voxgig/omni @ bc9535d655564c0833f6eff003b0b13dad8b350f
3
+ // License: MIT (c) voxgig - see repository LICENSE. Do not edit: resync from upstream.
4
+ // Omni internal JSON utilities.
5
+ //
6
+ // This module is deliberately self-contained: the omni runner must be able
7
+ // to test *any* library, including libraries that provide these same
8
+ // operations, so it can never borrow them from the system under test.
9
+ // Zero third-party dependencies, by design.
10
+
11
+ // A JSON value: null, boolean, number, string, list or map.
12
+ export type Json = any
13
+
14
+ const NULLMARK = '__NULL__' // Value is JSON null.
15
+ const UNDEFMARK = '__UNDEF__' // Value is not present (thus, undefined).
16
+ const EXISTSMARK = '__EXISTS__' // Value exists (not undefined).
17
+
18
+ // A map (JSON object)?
19
+ function ismap(val: Json): boolean {
20
+ return null != val && 'object' === typeof val && !Array.isArray(val)
21
+ }
22
+
23
+ // A list (JSON array)?
24
+ function islist(val: Json): boolean {
25
+ return Array.isArray(val)
26
+ }
27
+
28
+ // A container (map or list)?
29
+ function isnode(val: Json): boolean {
30
+ return ismap(val) || islist(val)
31
+ }
32
+
33
+ // Deep copy a JSON value. Non-JSON values (functions, class instances) are
34
+ // passed through by reference - the runner only ever clones test data.
35
+ function clone(val: Json): Json {
36
+ if (islist(val)) {
37
+ return val.map((entry: Json) => clone(entry))
38
+ }
39
+
40
+ if (ismap(val)) {
41
+ const out: Record<string, Json> = {}
42
+ for (const key of Object.keys(val)) {
43
+ out[key] = clone(val[key])
44
+ }
45
+ return out
46
+ }
47
+
48
+ return val
49
+ }
50
+
51
+ // Read a value from a nested structure by path. The path is a list of
52
+ // string keys (map) or integer-like keys (list). Returns undefined when
53
+ // any step is missing.
54
+ function getpath(val: Json, path: (string | number)[]): Json {
55
+ let current = val
56
+
57
+ for (const part of path) {
58
+ if (islist(current)) {
59
+ const index = 'number' === typeof part ? part : parseInt(String(part), 10)
60
+ if (isNaN(index) || index < 0 || index >= current.length) {
61
+ return undefined
62
+ }
63
+ current = current[index]
64
+ } else if (ismap(current)) {
65
+ const key = String(part)
66
+ if (!Object.prototype.hasOwnProperty.call(current, key)) {
67
+ return undefined
68
+ }
69
+ current = current[key]
70
+ } else {
71
+ return undefined
72
+ }
73
+ }
74
+
75
+ return current
76
+ }
77
+
78
+ // Depth-first walk, applying `apply` to every node and leaf, children
79
+ // first, then the containing node. `apply` may replace the value.
80
+ function walk(
81
+ val: Json,
82
+ apply: (key: string | number | undefined, val: Json, parent: Json, path: (string | number)[]) => Json,
83
+ key?: string | number,
84
+ parent?: Json,
85
+ path?: (string | number)[],
86
+ ): Json {
87
+ const curpath = path || []
88
+
89
+ if (isnode(val)) {
90
+ if (islist(val)) {
91
+ for (let index = 0; index < val.length; index++) {
92
+ val[index] = walk(val[index], apply, index, val, [...curpath, index])
93
+ }
94
+ } else {
95
+ for (const childkey of Object.keys(val)) {
96
+ val[childkey] = walk(val[childkey], apply, childkey, val, [...curpath, childkey])
97
+ }
98
+ }
99
+ }
100
+
101
+ return apply(key, val, parent, curpath)
102
+ }
103
+
104
+ // Deep structural equality. Numbers compare by value (1 and 1.0 are the
105
+ // same), booleans never equal numbers, map key order is not significant.
106
+ function deepequal(a: Json, b: Json): boolean {
107
+ if (a === b) {
108
+ return true
109
+ }
110
+
111
+ if (null == a || null == b) {
112
+ // undefined and null are distinct: only both-absent compares equal.
113
+ return (undefined === a && undefined === b) || (null === a && null === b)
114
+ }
115
+
116
+ const atype = typeof a
117
+ const btype = typeof b
118
+
119
+ if ('number' === atype && 'number' === btype) {
120
+ return a === b || (isNaN(a) && isNaN(b))
121
+ }
122
+
123
+ if (atype !== btype) {
124
+ return false
125
+ }
126
+
127
+ if (islist(a) && islist(b)) {
128
+ if (a.length !== b.length) {
129
+ return false
130
+ }
131
+ for (let index = 0; index < a.length; index++) {
132
+ if (!deepequal(a[index], b[index])) {
133
+ return false
134
+ }
135
+ }
136
+ return true
137
+ }
138
+
139
+ if (ismap(a) && ismap(b)) {
140
+ const akeys = Object.keys(a)
141
+ const bkeys = Object.keys(b)
142
+ if (akeys.length !== bkeys.length) {
143
+ return false
144
+ }
145
+ for (const key of akeys) {
146
+ if (!Object.prototype.hasOwnProperty.call(b, key)) {
147
+ return false
148
+ }
149
+ if (!deepequal(a[key], b[key])) {
150
+ return false
151
+ }
152
+ }
153
+ return true
154
+ }
155
+
156
+ return false
157
+ }
158
+
159
+ // Compact JSON text with map keys sorted, so that messages are identical
160
+ // in every port regardless of local map ordering.
161
+ // PATCH (solardemo prototype, pending upstream fix): cycle guard. The
162
+ // corpus drives LIVE Context objects through entries (entry.ctx, and the
163
+ // entry bookkeeping fail() prints with jsonstr), and a live ctx is cyclic
164
+ // (sdk._rootctx.client === sdk). Upstream jsonstr recursed forever; the
165
+ // struct repos' original runner emitted '[Circular]', restored here.
166
+ function jsonstr(val: Json, seen?: WeakSet<object>): string {
167
+ if (undefined === val) {
168
+ return 'undefined'
169
+ }
170
+
171
+ if (null === val) {
172
+ return 'null'
173
+ }
174
+
175
+ if ('string' === typeof val) {
176
+ return JSON.stringify(val)
177
+ }
178
+
179
+ if ('number' === typeof val) {
180
+ return Number.isFinite(val) ? String(val) : 'null'
181
+ }
182
+
183
+ if ('boolean' === typeof val) {
184
+ return val ? 'true' : 'false'
185
+ }
186
+
187
+ if (islist(val)) {
188
+ seen = seen || new WeakSet()
189
+ if (seen.has(val)) {
190
+ return '"[Circular]"'
191
+ }
192
+ seen.add(val)
193
+ return '[' + val.map((entry: Json) => jsonstr(entry, seen)).join(',') + ']'
194
+ }
195
+
196
+ if (ismap(val)) {
197
+ seen = seen || new WeakSet()
198
+ if (seen.has(val)) {
199
+ return '"[Circular]"'
200
+ }
201
+ seen.add(val)
202
+ const keys = Object.keys(val).sort()
203
+ return '{' + keys.map((key) => JSON.stringify(key) + ':' + jsonstr(val[key], seen)).join(',') + '}'
204
+ }
205
+
206
+ if ('function' === typeof val) {
207
+ return '[Function' + (val.name ? ' ' + val.name : '') + ']'
208
+ }
209
+
210
+ return JSON.stringify(String(val))
211
+ }
212
+
213
+ // Human readable form of a value: strings are shown verbatim (so that
214
+ // error-message matching is exact), everything else as compact JSON.
215
+ function stringify(val: Json): string {
216
+ return 'string' === typeof val ? val : jsonstr(val)
217
+ }
218
+
219
+ // Render a path as a dotted string.
220
+ function pathify(path: (string | number)[]): string {
221
+ return (path || []).map((part) => String(part)).join('.')
222
+ }
223
+
224
+ export {
225
+ NULLMARK,
226
+ UNDEFMARK,
227
+ EXISTSMARK,
228
+ clone,
229
+ deepequal,
230
+ getpath,
231
+ islist,
232
+ ismap,
233
+ isnode,
234
+ jsonstr,
235
+ pathify,
236
+ stringify,
237
+ walk,
238
+ }
@@ -0,0 +1,188 @@
1
+ // VENDORED: @voxgig/omni 0.1.2 (typescript/compat/struct.ts), import path adapted ('../src' -> './index').
2
+ // Source: https://github.com/voxgig/omni @ bc9535d655564c0833f6eff003b0b13dad8b350f
3
+ // License: MIT (c) voxgig - see repository LICENSE. Do not edit: resync from upstream.
4
+ // Drop-in replacement for the in-situ test runner in the voxgig/struct
5
+ // repository (`typescript/test/runner.ts`).
6
+ //
7
+ // struct's own runner and omni's runner implement the same spec format;
8
+ // this module exposes omni behind struct's exact runner API, so a struct
9
+ // port switches over by changing one import:
10
+ //
11
+ // -import { makeRunner, nullModifier, NULLMARK } from './runner'
12
+ // +import { makeRunner, nullModifier, NULLMARK } from './omni'
13
+ //
14
+ // where `./omni` is a small resolver in the port's test directory that
15
+ // locates a local omni checkout. Everything else - the corpus, the SDK,
16
+ // the test file - is unchanged. This is the TypeScript peer of
17
+ // javascript/compat/struct.js and python/voxgig_omni/compat/struct.py.
18
+
19
+ import { dirname, isAbsolute, join, sep } from 'node:path'
20
+ import { fileURLToPath } from 'node:url'
21
+
22
+ import { EXISTSMARK, NULLMARK, UNDEFMARK, makeRunner as omnimakerunner, nullmodifier } from './index'
23
+
24
+ import type { Json, Provider, Subject } from './index'
25
+
26
+ // struct's data model is JSON-shaped `any` at its boundaries, and so is
27
+ // its SDK; these aliases say that on purpose rather than by omission.
28
+ export type StructSDK = any
29
+ export type StructUtility = any
30
+
31
+ // struct's runner API, name for name.
32
+ export type StructSubject = (...args: any[]) => any
33
+
34
+ export type StructRunSet = (testspec: any, testsubject?: StructSubject) => Promise<void>
35
+
36
+ export type StructRunSetFlags = (
37
+ testspec: any,
38
+ flags: Record<string, any>,
39
+ testsubject?: StructSubject,
40
+ ) => Promise<void>
41
+
42
+ export type StructRunPack = {
43
+ spec: any
44
+ runset: StructRunSet
45
+ runsetflags: StructRunSetFlags
46
+ subject?: StructSubject
47
+ client: StructProvider
48
+ }
49
+
50
+ export type StructRunner = (name: string, store?: any) => Promise<StructRunPack>
51
+
52
+ // An omni provider that is also a struct client: test code reaches through
53
+ // the runpack's `client` as an SDK (`client.utility().struct`), so the
54
+ // wrapper forwards `utility()` and `tester()` alongside the four hooks.
55
+ export type StructProvider = Provider & {
56
+ utility: () => StructUtility
57
+ tester: (options?: any) => any
58
+ sdk: StructSDK
59
+ }
60
+
61
+ // The directory this shim was loaded from: dist/compat when built, compat
62
+ // when run from source. Its parent is the port root, so every frame from
63
+ // inside omni is skipped when locating the caller.
64
+ //
65
+ // It is derived from __dirname rather than matched against a known path,
66
+ // so it holds wherever the package sits - a checkout, or
67
+ // node_modules/@voxgig/omni. The trailing separator matters: without it a
68
+ // sibling whose name merely EXTENDS this one (`omni-js-extra` beside
69
+ // `omni-js`) would read as inside.
70
+ const OMNIDIR = dirname(__dirname)
71
+
72
+ // A relative test-file path is resolved against the first stack frame
73
+ // outside omni - the caller.
74
+ //
75
+ // PREFER AN ABSOLUTE PATH. This heuristic guesses at what "relative to"
76
+ // means, and the guess is wrong whenever a consumer's test FILES sit at a
77
+ // different depth from the module that loads the runner. struct's TypeScript
78
+ // port is exactly that shape: its loader compiles to `dist-test/` and its
79
+ // test files to `dist-test/utility/`, so the same relative string resolved
80
+ // one directory too deep and read `typescript/build/test/test.json`. That
81
+ // port now resolves the path itself, in `test/omni.ts`, and never reaches
82
+ // this. (An earlier version of this comment asserted it already did - it did
83
+ // not; this shim shipped before any consumer had proved it.)
84
+ // A stack frame's file, as a filesystem path.
85
+ //
86
+ // An ESM caller's frame reports a file:// URL rather than a path, and
87
+ // `dirname('file:///a/b.mjs')` yields 'file:/a', so a relative spec path
88
+ // resolved against it died on `ENOENT ... 'file:/.../fib.json'`. Frames
89
+ // that name no path at all - node: internals, data: URLs, eval - are
90
+ // skipped rather than mistaken for the caller.
91
+ function framepath(frame: any): string | null {
92
+ const file = 'function' === typeof frame.getFileName ? frame.getFileName() : null
93
+ if (null == file) {
94
+ return null
95
+ }
96
+ if (file.startsWith('file://')) {
97
+ try {
98
+ return fileURLToPath(file)
99
+ } catch {
100
+ return null
101
+ }
102
+ }
103
+ return isAbsolute(file) ? file : null
104
+ }
105
+
106
+ function callerdir(): string {
107
+ const original = Error.prepareStackTrace
108
+ Error.prepareStackTrace = (_err, stack) => stack
109
+ const holder: any = {}
110
+ Error.captureStackTrace(holder, callerdir)
111
+ const stack: any = holder.stack
112
+ Error.prepareStackTrace = original
113
+
114
+ for (const frame of stack) {
115
+ const file = framepath(frame)
116
+ if (file && !file.startsWith(OMNIDIR + sep)) {
117
+ return dirname(file)
118
+ }
119
+ }
120
+
121
+ return process.cwd()
122
+ }
123
+
124
+ // Wrap a struct SDK client as an omni provider.
125
+ function structprovider(sdk: StructSDK): StructProvider {
126
+ return {
127
+ // struct resolves a subject from the utility, or from utility.struct.
128
+ subject: (name: string): Subject | undefined => {
129
+ const utility = sdk.utility()
130
+ return utility[name] || (utility.struct && utility.struct[name])
131
+ },
132
+
133
+ // A DEF.client entry becomes another SDK instance.
134
+ client: async (options: Json) => structprovider(await sdk.tester(options)),
135
+
136
+ // struct's SDK supplies its own context wrapper.
137
+ contextify: (val: Json): Json => {
138
+ const utility = sdk.utility()
139
+ const hook =
140
+ 'function' === typeof utility.contextify
141
+ ? utility.contextify
142
+ : 'function' === typeof utility.makeContext
143
+ ? utility.makeContext
144
+ : null
145
+ const ctx = null == hook ? val : hook.call(utility, val)
146
+ if (null != ctx && 'object' === typeof ctx) {
147
+ ;(ctx as any).utility = utility
148
+ }
149
+ return ctx
150
+ },
151
+
152
+ // Client options may reference the runner store.
153
+ inject: (options: Json, store: Json): Json => {
154
+ const structutils = sdk.utility().struct
155
+ if (structutils && 'function' === typeof structutils.inject) {
156
+ return structutils.inject(options, store)
157
+ }
158
+ return options
159
+ },
160
+
161
+ utility: () => sdk.utility(),
162
+ tester: (options?: any) => sdk.tester(options),
163
+ sdk,
164
+ }
165
+ }
166
+
167
+ // struct's makeRunner(testfile, client) signature, backed by omni.
168
+ async function makeRunner(testfile: string, client: StructSDK): Promise<StructRunner> {
169
+ const specpath = isAbsolute(testfile) ? testfile : join(callerdir(), testfile)
170
+ const provider = structprovider(client)
171
+ const runner = await omnimakerunner(specpath, provider)
172
+
173
+ return async function structrunner(name: string, store?: any): Promise<StructRunPack> {
174
+ const runpack = await runner(name, store)
175
+
176
+ return {
177
+ spec: runpack.spec,
178
+ runset: runpack.runset,
179
+ runsetflags: runpack.runsetflags,
180
+ subject: runpack.subject,
181
+ client: provider,
182
+ }
183
+ }
184
+ }
185
+
186
+ const nullModifier = nullmodifier
187
+
188
+ export { EXISTSMARK, NULLMARK, UNDEFMARK, makeRunner, nullModifier, structprovider }
@@ -0,0 +1,38 @@
1
+ // VENDORED: @voxgig/omni 0.1.2 (typescript/src/index.ts)
2
+ // Source: https://github.com/voxgig/omni @ bc9535d655564c0833f6eff003b0b13dad8b350f
3
+ // License: MIT (c) voxgig - see repository LICENSE. Do not edit: resync from upstream.
4
+ // @voxgig/omni - shared multi-language test runner.
5
+
6
+ export {
7
+ CAPABILITIES,
8
+ EXISTSMARK,
9
+ NULLMARK,
10
+ OmniError,
11
+ SPECVERSION,
12
+ UNDEFMARK,
13
+ errify,
14
+ fixjson,
15
+ loadspec,
16
+ makeRunner,
17
+ match,
18
+ matchval,
19
+ nullmodifier,
20
+ resolvespec,
21
+ } from './Runner'
22
+
23
+ export type { Flags, Provider, RunPack, RunSet, RunSetFlags, Runner, Subject } from './Runner'
24
+
25
+ export {
26
+ clone,
27
+ deepequal,
28
+ getpath,
29
+ islist,
30
+ ismap,
31
+ isnode,
32
+ jsonstr,
33
+ pathify,
34
+ stringify,
35
+ walk,
36
+ } from './Util'
37
+
38
+ export type { Json } from './Util'
@@ -318,8 +318,26 @@ pub fn make_options_util(ctx: *Context) Value {
318
318
  }
319
319
  }
320
320
 
321
+ // `auth: null` is the documented way to suppress auth outright, and
322
+ // prepare_auth honours it before it ever reads the apikey. It cannot
323
+ // survive validate: a stored null reads as "no value", so the optspec
324
+ // `auth` default fires and the suppression becomes "use the default auth"
325
+ // - transmitting the credential the caller withheld. Withhold the key for
326
+ // validate, then put the null back. Same fix as ts/js/go make_options.
327
+ //
328
+ // Value has no separate undefined variant (is_noval IS `== .null`), so
329
+ // getp cannot tell an absent key from a stored null. The raw MapRef.get
330
+ // optional can: a null OPTIONAL is absent, a `.null` payload is a stored
331
+ // JSON null.
332
+ const auth_suppressed = switch (options) {
333
+ .object => |m| if (m.get("auth")) |a| a == .null else false,
334
+ else => false,
335
+ };
336
+
321
337
  var opts = h.clone(options);
322
338
 
339
+ if (auth_suppressed) h.del_prop(opts, h.vstr("auth"));
340
+
323
341
  // Feature add-order. options.feature may be an ordered list of
324
342
  // { name, active, ...opts } entries (the list position IS the order in
325
343
  // which features are added), or a { name: {opts} } map. Normalize a list
@@ -396,6 +414,11 @@ pub fn make_options_util(ctx: *Context) Value {
396
414
  if (vr.err == null and vr.out == .object) opts = vr.out;
397
415
  }
398
416
 
417
+ // Restore the suppression the optspec default would otherwise erase. setp
418
+ // does a direct map put, so the explicit null is STORED, not treated as a
419
+ // delete.
420
+ if (auth_suppressed) h.setp(opts, "auth", h.vnull());
421
+
399
422
  // Resolve a templated base URL (e.g. https://{tenant_id}.hanko.io).
400
423
  // Every placeholder must resolve to a non-empty value: from options.server
401
424
  // (user), else the Config default. A placeholder that resolves to "" is a
@@ -3,7 +3,7 @@
3
3
  "package": 1
4
4
  },
5
5
  "name": "@voxgig/sdkgen",
6
- "version": "4.5.3",
6
+ "version": "4.6.0",
7
7
  "provides": {
8
8
  "target": [
9
9
  "c",
@@ -48,6 +48,7 @@
48
48
  "ratelimit",
49
49
  "rbac",
50
50
  "retry",
51
+ "secrets",
51
52
  "streaming",
52
53
  "telemetry",
53
54
  "test",
@@ -32,6 +32,7 @@
32
32
  // is the first finding and the rest of the battery still runs, because an
33
33
  // author who has not written it yet is precisely who needs the rest.
34
34
 
35
+ import { unknownTags, TAGS } from '../helpers/applicability'
35
36
  import Path from 'node:path'
36
37
 
37
38
  import { KIT } from '../types'
@@ -326,6 +327,23 @@ function checkDefinition(
326
327
  err + ' (unified with the base schema — this is what a consumer compiles)'))
327
328
  }
328
329
 
330
+ // 5b. APPLICABILITY TAGS come from a CLOSED vocabulary (see
331
+ // helpers/applicability). `provides: &: boolean` accepts any key, so
332
+ // without this a typo — `sekrreto` for `sekreto` — compiles cleanly
333
+ // and silently makes the feature apply to NO target at all. That is
334
+ // the worst shape a mistake can take here: the feature simply
335
+ // vanishes from every generated SDK with no diagnostic anywhere.
336
+ const tagkey = 'feature' === kind ? 'needs' : 'provides'
337
+ const unknown = null == declared ? [] : unknownTags((declared as any)[tagkey])
338
+
339
+ if (0 < unknown.length) {
340
+ found.push(at('error', 'model-tag-unknown',
341
+ 'declares unknown applicability tag(s) in `' + tagkey + '`: ' +
342
+ unknown.join(', ') + ' — the vocabulary is CLOSED (' + TAGS.join(', ') +
343
+ '), so an unrecognised tag makes this ' + kind +
344
+ ' match nothing rather than failing loudly'))
345
+ }
346
+
329
347
  if ('target' === kind) {
330
348
  found.push(...checkTargetModel(src, name, file, at))
331
349
  }
@@ -31,7 +31,7 @@ const AgentGuide = cmp(function AgentGuide(props: any) {
31
31
  const title = target.title || lang
32
32
  const surface = langCmd(lang).note
33
33
 
34
- const features = activeFeatures(model)
34
+ const features = activeFeatures(model, target)
35
35
  // go-cli/go-mcp disable the feature phase; ts/js lay features out as
36
36
  // per-feature directories, the other SDK targets as flat files.
37
37
  const featuresOn = featuresEnabled(target)
@@ -9,6 +9,8 @@
9
9
  // `.sdk/model/...`) — NOT the `project/.sdk/...` form used by the sdkgen repo's
10
10
  // own developer docs.
11
11
 
12
+ import { featureApplies } from '../helpers/applicability'
13
+
12
14
  import { each } from 'jostraca'
13
15
 
14
16
  import {
@@ -114,9 +116,14 @@ function activeTargets(model: any): any[] {
114
116
  return each(target).filter((t: any) => t && t.active !== false)
115
117
  }
116
118
 
117
- function activeFeatures(model: any): any[] {
119
+ // With a target, also drops features that do not APPLY to it — a guide
120
+ // must not document a feature the target has no implementation for.
121
+ // Without one (the repo-level guide) every active feature is listed.
122
+ function activeFeatures(model: any, target?: any): any[] {
118
123
  const feature = getModelPath(model, `main.${KIT}.feature`) || {}
119
- return each(feature).filter((f: any) => f && f.active !== false)
124
+ return each(feature)
125
+ .filter((f: any) => f && f.active !== false)
126
+ .filter((f: any) => null == target || featureApplies(f, target))
120
127
  }
121
128
 
122
129
  function activeEntities(model: any): any[] {
@@ -2,11 +2,30 @@
2
2
  import { cmp, Copy, Folder } from 'jostraca'
3
3
 
4
4
  import { ensureStdrep } from '../helpers/stdrep'
5
+ import { featureApplies, featureTags } from '../helpers/applicability'
5
6
 
6
7
  const Feature = cmp(function Feature(props: any) {
7
8
  const { target, feature, ctx$ } = props
8
9
  const { log } = ctx$
9
10
 
11
+ // A feature the target cannot take generates NOTHING for it — not the
12
+ // source, and (via targetFeatures in the Config/Main components) not the
13
+ // import or registry entry either. Copy would otherwise stat-fail on the
14
+ // missing template folder and abort the whole run, taking every other
15
+ // target with it. See helpers/applicability and docs/design/feature-tags.
16
+ if (!featureApplies(feature, target)) {
17
+ const provided = featureTags(target.provides)
18
+ const unmet = featureTags(feature.needs).filter((n) => !provided.includes(n))
19
+
20
+ log.info({
21
+ point: 'feature-not-applicable', target: target.name, feature: feature.name,
22
+ needs: feature.needs, provides: target.provides, unmet,
23
+ note: feature.name + ': target ' + target.name +
24
+ ' does not provide ' + unmet.join(', ')
25
+ })
26
+ return
27
+ }
28
+
10
29
  if (false !== target.srcfeature) {
11
30
  Folder({ name: 'src/feature/' + feature.name }, () => {
12
31
  // TODO: Copy should just warn if from not found
@@ -1,3 +1,5 @@
1
+ import { featureApplies } from '../helpers/applicability'
2
+
1
3
  import { each } from 'jostraca'
2
4
 
3
5
  import { KIT, getModelPath } from '../types'
@@ -46,11 +48,15 @@ function renderValue(v: any): string {
46
48
 
47
49
  // Every feature the model declares active, in a stable order, with its
48
50
  // options and their defaults.
49
- function featureDocs(model: any): FeatureDoc[] {
51
+ // With a target, also drops features that do not APPLY to it: a target
52
+ // README must not document a feature that target has no implementation
53
+ // for. Without one (the repo-level README) every active feature is listed.
54
+ function featureDocs(model: any, target?: any): FeatureDoc[] {
50
55
  const feature = getModelPath(model, `main.${KIT}.feature`)
51
56
 
52
57
  return each(feature)
53
58
  .filter((f: any) => false !== f.active && 'base' !== f.name)
59
+ .filter((f: any) => null == target || featureApplies(f, target))
54
60
  .map((f: any) => {
55
61
  const opts = (f.config && f.config.options) || {}
56
62
  const options = Object.keys(opts).sort().map((k) => ({
@@ -1,4 +1,6 @@
1
1
 
2
+ import { targetFeatures } from '../helpers/applicability'
3
+
2
4
  import { cmp, each, names, Content } from 'jostraca'
3
5
 
4
6
  import {
@@ -222,7 +224,8 @@ const ReadmeExplanation = cmp(function ReadmeExplanation(props: any) {
222
224
  const { target, ctx$ } = props
223
225
  const { model } = ctx$
224
226
 
225
- const feature = getModelPath(model, `main.${KIT}.feature`)
227
+ // Gated: this section describes a TARGET's features.
228
+ const feature = targetFeatures(model, target)
226
229
  const lang = LANGS[target.name] || DEFAULT_LANG
227
230
 
228
231
  // Pick a real example entity WITH a real op (prefer a read op) so the
@@ -27,7 +27,7 @@ const ReadmeFeatures = cmp(function ReadmeFeatures(props: any) {
27
27
  return
28
28
  }
29
29
 
30
- const features: FeatureDoc[] = featureDocs(model)
30
+ const features: FeatureDoc[] = featureDocs(model, target)
31
31
 
32
32
  if (0 === features.length) {
33
33
  return
@@ -19,7 +19,7 @@ const ReadmeRefFeatures = cmp(function ReadmeRefFeatures(props: any) {
19
19
  const { target, ctx$ } = props
20
20
  const { model } = ctx$
21
21
 
22
- const features: FeatureDoc[] = featureDocs(model)
22
+ const features: FeatureDoc[] = featureDocs(model, target)
23
23
 
24
24
  if (0 === features.length) {
25
25
  return