@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.
- package/bin/voxgig-sdkgen +1 -1
- package/dist/action/check.js +15 -0
- package/dist/action/check.js.map +1 -1
- package/dist/cmp/AgentGuide.js +1 -1
- package/dist/cmp/AgentGuide.js.map +1 -1
- package/dist/cmp/AgentGuideContent.d.ts +1 -1
- package/dist/cmp/AgentGuideContent.js +8 -2
- package/dist/cmp/AgentGuideContent.js.map +1 -1
- package/dist/cmp/Feature.js +17 -0
- package/dist/cmp/Feature.js.map +1 -1
- package/dist/cmp/FeatureDocs.d.ts +1 -1
- package/dist/cmp/FeatureDocs.js +6 -1
- package/dist/cmp/FeatureDocs.js.map +1 -1
- package/dist/cmp/ReadmeExplanation.js +3 -1
- package/dist/cmp/ReadmeExplanation.js.map +1 -1
- package/dist/cmp/ReadmeFeatures.js +1 -1
- package/dist/cmp/ReadmeFeatures.js.map +1 -1
- package/dist/cmp/ReadmeRefFeatures.js +1 -1
- package/dist/cmp/ReadmeRefFeatures.js.map +1 -1
- package/dist/helpers/applicability.d.ts +6 -0
- package/dist/helpers/applicability.js +103 -0
- package/dist/helpers/applicability.js.map +1 -0
- package/dist/helpers/collectDeps.js +4 -2
- package/dist/helpers/collectDeps.js.map +1 -1
- package/dist/helpers/serverVars.d.ts +2 -1
- package/dist/helpers/serverVars.js +17 -0
- package/dist/helpers/serverVars.js.map +1 -1
- package/dist/sdkgen.d.ts +3 -2
- package/dist/sdkgen.js +9 -2
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utility.js +7 -1
- package/dist/utility.js.map +1 -1
- package/model/sdkgen.aon +39 -0
- package/package.json +1 -1
- package/project/.sdk/model/feature/feature-index.aon +1 -0
- package/project/.sdk/model/feature/secrets.aon +118 -0
- package/project/.sdk/model/target/ts.aon +8 -1
- package/project/.sdk/src/cmp/c/Config_c.ts +5 -1
- package/project/.sdk/src/cmp/cpp/Config_cpp.ts +5 -1
- package/project/.sdk/src/cmp/csharp/Config_csharp.ts +5 -1
- package/project/.sdk/src/cmp/dart/Config_dart.ts +5 -1
- package/project/.sdk/src/cmp/elixir/Config_elixir.ts +5 -1
- package/project/.sdk/src/cmp/elixir/Main_elixir.ts +5 -1
- package/project/.sdk/src/cmp/go/Config_go.ts +5 -1
- package/project/.sdk/src/cmp/go/Main_go.ts +6 -2
- package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +16 -3
- package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +16 -3
- package/project/.sdk/src/cmp/go/TestDirect_go.ts +28 -4
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +43 -10
- package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +5 -5
- package/project/.sdk/src/cmp/java/Config_java.ts +22 -1
- package/project/.sdk/src/cmp/java/Main_java.ts +5 -1
- package/project/.sdk/src/cmp/java/ReadmeQuick_java.ts +17 -3
- package/project/.sdk/src/cmp/java/ReadmeTopQuick_java.ts +17 -3
- package/project/.sdk/src/cmp/java/TestDirect_java.ts +23 -4
- package/project/.sdk/src/cmp/java/TestEntity_java.ts +29 -4
- package/project/.sdk/src/cmp/js/Config_js.ts +5 -1
- package/project/.sdk/src/cmp/js/Main_js.ts +5 -1
- package/project/.sdk/src/cmp/js/Package_js.ts +4 -1
- package/project/.sdk/src/cmp/kotlin/Config_kotlin.ts +5 -1
- package/project/.sdk/src/cmp/lean/Config_lean.ts +5 -1
- package/project/.sdk/src/cmp/lua/Config_lua.ts +5 -1
- package/project/.sdk/src/cmp/lua/Main_lua.ts +5 -1
- package/project/.sdk/src/cmp/lua/Package_lua.ts +4 -1
- package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +5 -1
- package/project/.sdk/src/cmp/perl/Main_perl.ts +5 -1
- package/project/.sdk/src/cmp/php/Config_php.ts +5 -1
- package/project/.sdk/src/cmp/php/Main_php.ts +5 -1
- package/project/.sdk/src/cmp/py/Config_py.ts +5 -1
- package/project/.sdk/src/cmp/py/Main_py.ts +5 -1
- package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +16 -3
- package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +16 -3
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +24 -5
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +23 -3
- package/project/.sdk/src/cmp/rb/Config_rb.ts +5 -1
- package/project/.sdk/src/cmp/rb/Main_rb.ts +5 -1
- package/project/.sdk/src/cmp/rust/Config_rust.ts +5 -1
- package/project/.sdk/src/cmp/rust/Main_rust.ts +5 -1
- package/project/.sdk/src/cmp/scala/Config_scala.ts +5 -1
- package/project/.sdk/src/cmp/scala/Main_scala.ts +5 -1
- package/project/.sdk/src/cmp/swift/Config_swift.ts +5 -1
- package/project/.sdk/src/cmp/ts/Config_ts.ts +5 -1
- package/project/.sdk/src/cmp/ts/Main_ts.ts +57 -1
- package/project/.sdk/src/cmp/ts/Package_ts.ts +4 -1
- package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +15 -3
- package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +18 -5
- package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +19 -5
- package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +67 -7
- package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +27 -4
- package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +9 -2
- package/project/.sdk/src/cmp/ts/fragment/Entity.test.fragment.ts +9 -2
- package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +7 -0
- package/project/.sdk/src/cmp/zig/Config_zig.ts +5 -1
- package/project/.sdk/tm/c/utility/make_options.c +22 -0
- package/project/.sdk/tm/clojure/src/sdk/core.clj +18 -1
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +23 -0
- package/project/.sdk/tm/csharp/test/CustomUtilityTest.cs +15 -0
- package/project/.sdk/tm/csharp/utility/MakeOptions.cs +23 -0
- package/project/.sdk/tm/dart/lib/utility/MakeOptionsUtility.dart +22 -0
- package/project/.sdk/tm/elixir/lib/projectname/utility.ex +19 -0
- package/project/.sdk/tm/go/core/context.go +1 -1
- package/project/.sdk/tm/go/feature/cost_feature.go +1 -1
- package/project/.sdk/tm/go/feature/paging_feature.go +5 -5
- package/project/.sdk/tm/go/feature/test_feature.go +12 -5
- package/project/.sdk/tm/go/test/custom_utility_test.go +15 -0
- package/project/.sdk/tm/go/test/feature_corpus_test.go +7 -0
- package/project/.sdk/tm/go/test/runner_test.go +46 -0
- package/project/.sdk/tm/go/test/struct_runner_test.go +7 -7
- package/project/.sdk/tm/go/test/struct_utility_test.go +63 -27
- package/project/.sdk/tm/go/utility/fetcher.go +2 -2
- package/project/.sdk/tm/go/utility/make_options.go +24 -5
- package/project/.sdk/tm/go/utility/make_point.go +1 -1
- package/project/.sdk/tm/go/utility/make_spec.go +17 -1
- package/project/.sdk/tm/go/utility/prepare_auth.go +1 -1
- package/project/.sdk/tm/go/utility/struct/voxgigstruct.go +370 -307
- package/project/.sdk/tm/go/utility/transform_request.go +29 -1
- package/project/.sdk/tm/go/utility/transform_response.go +20 -1
- package/project/.sdk/tm/java/test/CustomUtilityTest.java +10 -0
- package/project/.sdk/tm/java/test/FeatureCorpusTest.java +7 -0
- package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +6 -0
- package/project/.sdk/tm/java/test/RunnerSupport.java +43 -0
- package/project/.sdk/tm/java/utility/MakeOptions.java +84 -1
- package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +24 -0
- package/project/.sdk/tm/js/src/utility/StructUtility.js +2076 -1837
- package/project/.sdk/tm/js/test/feature/Corpus.test.js +9 -0
- package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +21 -0
- package/project/.sdk/tm/lean/src/SdkUtility.lean +12 -1
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +11 -0
- package/project/.sdk/tm/perl/utility/make_options.pm +18 -0
- package/project/.sdk/tm/php/test/FeatureCorpusTest.php +10 -1
- package/project/.sdk/tm/php/utility/MakeOptions.php +24 -0
- package/project/.sdk/tm/py/pkg/utility/make_options.py +20 -0
- package/project/.sdk/tm/py/test/runner.py +32 -0
- package/project/.sdk/tm/py/test/test_feature_corpus.py +10 -1
- package/project/.sdk/tm/rb/test/feature_corpus_test.rb +9 -1
- package/project/.sdk/tm/rb/utility/make_options.rb +17 -0
- package/project/.sdk/tm/rust/utility/make_options.rs +25 -0
- package/project/.sdk/tm/scala/utility/Make.scala +17 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +21 -0
- package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +419 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Providers.ts +1221 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sekreto.ts +381 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sigv4.ts +151 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/index.ts +42 -0
- package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +18 -0
- package/project/.sdk/tm/ts/src/utility/StructUtility.ts +1321 -710
- package/project/.sdk/tm/ts/test/feature/Corpus.test.ts +9 -0
- package/project/.sdk/tm/ts/test/feature/secrets/Secrets.test.ts +764 -0
- package/project/.sdk/tm/ts/test/omni.test.ts +84 -0
- package/project/.sdk/tm/ts/test/omni.ts +86 -0
- package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +6 -2
- package/project/.sdk/tm/ts/test/utility/StructUtility.test.ts +2 -2
- package/project/.sdk/tm/ts/test/utility.ts +122 -0
- package/project/.sdk/tm/ts/test/vendor/omni/Runner.ts +692 -0
- package/project/.sdk/tm/ts/test/vendor/omni/Util.ts +238 -0
- package/project/.sdk/tm/ts/test/vendor/omni/compat.ts +188 -0
- package/project/.sdk/tm/ts/test/vendor/omni/index.ts +38 -0
- package/project/.sdk/tm/zig/core/utility.zig +23 -0
- package/project/sdkgen-package.json +2 -1
- package/src/action/check.ts +18 -0
- package/src/cmp/AgentGuide.ts +1 -1
- package/src/cmp/AgentGuideContent.ts +9 -2
- package/src/cmp/Feature.ts +19 -0
- package/src/cmp/FeatureDocs.ts +7 -1
- package/src/cmp/ReadmeExplanation.ts +4 -1
- package/src/cmp/ReadmeFeatures.ts +1 -1
- package/src/cmp/ReadmeRefFeatures.ts +1 -1
- package/src/helpers/applicability.ts +123 -0
- package/src/helpers/collectDeps.ts +5 -1
- package/src/helpers/serverVars.ts +19 -0
- package/src/sdkgen.ts +9 -1
- package/src/utility.ts +10 -1
- 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
|
package/src/action/check.ts
CHANGED
|
@@ -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
|
}
|
package/src/cmp/AgentGuide.ts
CHANGED
|
@@ -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
|
-
|
|
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)
|
|
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[] {
|
package/src/cmp/Feature.ts
CHANGED
|
@@ -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
|
package/src/cmp/FeatureDocs.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
@@ -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
|